当前位置: 首页 > news >正文

织梦网站标题被改企业网站建设公

织梦网站标题被改,企业网站建设公,上饶婚纱工作室网站建设,小广告的胶怎么清理需求一 现在需要向一个地址写值,但是有两种硬件设备,他们的写入的地址都是不一样,写的值都是一样的。 分析 最简单的就是一个大的if else 用于判断不同的设备类型扩展性,如果后续设备种类增加,写入的地址容易改变&…

需求一

现在需要向一个地址写值,但是有两种硬件设备,他们的写入的地址都是不一样,写的值都是一样的。

分析

  1. 最简单的就是一个大的if else 用于判断不同的设备类型
  2. 扩展性,如果后续设备种类增加,写入的地址容易改变,写入的值也容易变,在if else中就不是很好修改。在switch case会清晰些,但是代码的行数会非常大。

考虑到以后的扩展,对硬件操作进行一个简单的封装。

目标:

业务层用统一 API 读写“逻辑寄存器”,不接触物理地址;HAL 负责把 (设备, 寄存器ID) → 真实地址。

要点

  1. 用二维表 device_regs[dev][reg] 做映射。

  2. 统一的 RegId 集合;两台设备的寄存器数量一致。

  3. 编译期静态断言 + 运行时边界检查,避免越界。

代码

#include <stdint.h>
#include <stdio.h>typedef enum { DEV_A, DEV_B, DEV_MAX } DeviceType;
typedef enum { REG_A, REG_B, REG_C, REG_COUNT } RegId;/* --- 模拟寄存器空间(真实环境换成 MMIO 地址) --- */
static uint8_t devA_space[REG_COUNT] = {0};
static uint8_t devB_space[REG_COUNT] = {0};typedef uint8_t *reg_ptr_t;/* 设备 → 逻辑寄存器 → 地址 */
static const reg_ptr_t device_regs[DEV_MAX][REG_COUNT] = {[DEV_A] = {&devA_space[0], &devA_space[1], &devA_space[2]},[DEV_B] = {&devB_space[0], &devB_space[1], &devB_space[2]},
};_Static_assert(DEV_MAX == 2, "update table when adding devices");
_Static_assert(REG_COUNT == 3, "update table when adding regs");/* HAL API */
int hal_write(DeviceType dev, RegId reg, uint8_t val) {if (dev >= DEV_MAX || reg >= REG_COUNT) return -1;volatile uint8_t *addr = device_regs[dev][reg];*addr                  = val;return 0;
}
int hal_read(DeviceType dev, RegId reg, uint8_t *out) {if (dev >= DEV_MAX || reg >= REG_COUNT || !out) return -1;volatile uint8_t *addr = device_regs[dev][reg];*out                   = *addr;return 0;
}/* demo */
static void show(DeviceType d) {for (int i = 0; i < REG_COUNT; i++)printf("D%d R%d=0x%02x  ", d, i, *device_regs[d][i]);puts("");
}
int main(void) {puts("Scene1:");show(DEV_A);show(DEV_B);hal_write(DEV_A, REG_B, 0x11);hal_write(DEV_B, REG_C, 0x22);show(DEV_A);show(DEV_B);return 0;
}

运行结果

➜  week-two ./hal_demoV2                                              
Scene1:
D0 R0=0x00  D0 R1=0x00  D0 R2=0x00  
D1 R0=0x00  D1 R1=0x00  D1 R2=0x00  
D0 R0=0x00  D0 R1=0x11  D0 R2=0x00  
D1 R0=0x00  D1 R1=0x00  D1 R2=0x22 

这里是对寄存器地址进行了抽象,不同设备写的寄存器地址不一样。

需求二

还是一样的写地址,但是另外一种设备,他只有三个地址供读写(初始的是5个),他们的写入的地址都是不一样,写的值都是一样的。

分析

继续保持统一 API,但不同设备的寄存器个数不一样,访问不存在的寄存器要安全失败。

要点

  1. 每个设备独立一张表 + reg_count。

  2. HAL 在访问前检查 reg < reg_count。

  3. 保留统一的 RegId 超集,但不是所有设备都支持所有 ID。

代码

#include <stdint.h>
#include <stdio.h>typedef enum { DEV_A2, DEV_B2, DEV2_MAX } DeviceType2;
/* 统一超集:A 有 A..E(5个),B 只有 A..C(3个) */
typedef enum { REG2_A, REG2_B, REG2_C, REG2_D, REG2_E, REG2_MAX } RegId2;/* 模拟寄存器空间 */
static uint8_t devA2_space[5] = {0};
static uint8_t devB2_space[3] = {0};typedef uint8_t *reg_ptr_t;static const reg_ptr_t devA2_regs[] = {&devA2_space[0], &devA2_space[1], &devA2_space[2],&devA2_space[3], &devA2_space[4]};
static const reg_ptr_t devB2_regs[] = {&devB2_space[0], &devB2_space[1], &devB2_space[2]};typedef struct {const reg_ptr_t *regs;size_t reg_count;
} DeviceMap2;
static const DeviceMap2 devmap2[DEV2_MAX] = {[DEV_A2] = {devA2_regs, sizeof(devA2_regs) / sizeof(devA2_regs[0])}, // 5[DEV_B2] = {devB2_regs, sizeof(devB2_regs) / sizeof(devB2_regs[0])}, // 3
};int hal2_write(DeviceType2 dev, RegId2 reg, uint8_t val) {if (dev >= DEV2_MAX) return -1;if (reg >= devmap2[dev].reg_count) return -2; // 关键:越界/不支持volatile uint8_t *addr = devmap2[dev].regs[reg];*addr                  = val;return 0;
}
int hal2_read(DeviceType2 dev, RegId2 reg, uint8_t *out) {if (dev >= DEV2_MAX || !out) return -1;if (reg >= devmap2[dev].reg_count) return -2;volatile uint8_t *addr = devmap2[dev].regs[reg];*out                   = *addr;return 0;
}/* demo */
static void show2(DeviceType2 d) {for (size_t i = 0; i < devmap2[d].reg_count; i++)printf("D2-%d R%zu=0x%02x  ", d, i, *devmap2[d].regs[i]);puts("");
}
int main(void) {puts("Scene2:");show2(DEV_A2);show2(DEV_B2);hal2_write(DEV_A2, REG2_D, 0x55);           // A 支持 Dhal2_write(DEV_B2, REG2_C, 0x66);           // B 支持 Cif (hal2_write(DEV_B2, REG2_D, 0x77) < 0) { // B 不支持 Dputs("B2 does not support REG_D (safe fail).");}show2(DEV_A2);show2(DEV_B2);return 0;
}

结果

Scene2:
D2-0 R0=0x00  D2-0 R1=0x00  D2-0 R2=0x00  D2-0 R3=0x00  D2-0 R4=0x00  
D2-1 R0=0x00  D2-1 R1=0x00  D2-1 R2=0x00  
B2 does not support REG_D (safe fail).
D2-0 R0=0x00  D2-0 R1=0x00  D2-0 R2=0x00  D2-0 R3=0x55  D2-0 R4=0x00  
D2-1 R0=0x00  D2-1 R1=0x00  D2-1 R2=0x66  
[1] + Done                       "/usr/bin/gdb" --interpreter=mi --tty=${DbgTerm} 0<"/tmp/Microsoft-MIEngine-In-m45bp0uc.udc" 1>"/tmp/Microsoft-MIEngine-Out-jvqrijcw.44u"

需求三

两种设备,寄存器数量不同;同一个“逻辑操作”(开启/关闭/复位)对应不同寄存器与不同值(甚至写多步)。比如说,对于开启设备的操作,设备A只需要向0x11地址写入aa,设备B需要先向0xa2地址写入a0,再向0x15写入c1。

目标

业务层只说“开启/关闭”,HAL 负责把逻辑操作翻译成设备特定的寄存器写序列与取值。

代码

#include <stdint.h>
#include <stdio.h>typedef enum { DEV_A3, DEV_B3, DEV3_MAX } DeviceType3;
/* A 有 A..E;B 只有 A..C */
typedef enum { R3_A, R3_B, R3_C, R3_D, R3_E, R3_MAX } RegId3;
/* 逻辑操作 */
typedef enum { OP_ENABLE, OP_DISABLE, OP_RESET, OP_MAX } OpId;/* 模拟寄存器 */
static uint8_t A3_space[5] = {0};
static uint8_t B3_space[3] = {0};typedef uint8_t *reg_ptr_t;
/* 地址表 */
static const reg_ptr_t A3_regs[] = {&A3_space[0], &A3_space[1], &A3_space[2], &A3_space[3],&A3_space[4]};
static const reg_ptr_t B3_regs[] = {&B3_space[0], &B3_space[1], &B3_space[2]};typedef struct {const reg_ptr_t *regs;size_t reg_count;
} DevMap3;
static const DevMap3 devmap3[DEV3_MAX] = {[DEV_A3] = {A3_regs, sizeof(A3_regs) / sizeof(A3_regs[0])}, // 5[DEV_B3] = {B3_regs, sizeof(B3_regs) / sizeof(B3_regs[0])}, // 3
};/* 基础 HAL */
static int hal3_write(DeviceType3 d, RegId3 r, uint8_t v) {if (d >= DEV3_MAX) return -1;if (r >= devmap3[d].reg_count) return -2;volatile uint8_t *addr = devmap3[d].regs[r];*addr                  = v;return 0;
}
static int hal3_read(DeviceType3 d, RegId3 r, uint8_t *out) {if (d >= DEV3_MAX || !out) return -1;if (r >= devmap3[d].reg_count) return -2;volatile uint8_t *addr = devmap3[d].regs[r];*out                   = *addr;return 0;
}/* 逻辑操作 → 设备特定写序列 */
typedef struct {RegId3 reg;uint8_t val;
} Step;
typedef struct {const Step *steps;size_t n;
} OpPlan;/* 设备 A:开启需要先写 D=0x44 再写 A=0x01;关闭写 A=0x00;复位写 E=0x5A */
static const Step A_ENABLE[]  = {{R3_D, 0x44}, {R3_A, 0x01}};
static const Step A_DISABLE[] = {{R3_A, 0x00}};
static const Step A_RESET[]   = {{R3_E, 0x5A}};/* 设备 B:开启只写 B=0x80;关闭写 B=0x00;复位写 C=0xA5 再 A=0x01 */
static const Step B_ENABLE[]  = {{R3_B, 0x80}};
static const Step B_DISABLE[] = {{R3_B, 0x00}};
static const Step B_RESET[]   = {{R3_C, 0xA5}, {R3_A, 0x01}};static const OpPlan plans[DEV3_MAX][OP_MAX] ={[DEV_A3] ={[OP_ENABLE]  = {A_ENABLE, sizeof(A_ENABLE) / sizeof(A_ENABLE[0])},[OP_DISABLE] = {A_DISABLE, sizeof(A_DISABLE) / sizeof(A_DISABLE[0])},[OP_RESET]   = {A_RESET, sizeof(A_RESET) / sizeof(A_RESET[0])},},[DEV_B3] = {[OP_ENABLE]  = {B_ENABLE, sizeof(B_ENABLE) / sizeof(B_ENABLE[0])},[OP_DISABLE] = {B_DISABLE, sizeof(B_DISABLE) / sizeof(B_DISABLE[0])},[OP_RESET]   = {B_RESET, sizeof(B_RESET) / sizeof(B_RESET[0])},}};/* 高层 HAL:执行逻辑操作 */
int hal3_op(DeviceType3 d, OpId op) {if (d >= DEV3_MAX || op >= OP_MAX) return -1;const OpPlan *p = &plans[d][op];if (!p->steps || p->n == 0) return -2; /* 不支持该操作 */for (size_t i = 0; i < p->n; i++) {/* 安全:步骤中列出的寄存器也要再检查一次是否被该设备支持 */if (p->steps[i].reg >= devmap3[d].reg_count) return -3; /* 计划配置错误 */int rc = hal3_write(d, p->steps[i].reg, p->steps[i].val);if (rc) return rc;}return 0;
}/* demo */
static void show3(DeviceType3 d) {for (size_t i = 0; i < devmap3[d].reg_count; i++)printf("D3-%d R%zu=0x%02x  ", d, i, *devmap3[d].regs[i]);puts("");
}
int main(void) {puts("Scene3:");show3(DEV_A3);show3(DEV_B3);/* 业务层:完全不知道写哪些寄存器/值,只说“开启/关闭/复位” */hal3_op(DEV_A3, OP_ENABLE);hal3_op(DEV_B3, OP_ENABLE);show3(DEV_A3);show3(DEV_B3);hal3_op(DEV_A3, OP_DISABLE);hal3_op(DEV_B3, OP_RESET);show3(DEV_A3);show3(DEV_B3);return 0;
}

代码执行结果

Scene3:
D3-0 R0=0x00  D3-0 R1=0x00  D3-0 R2=0x00  D3-0 R3=0x00  D3-0 R4=0x00  
D3-1 R0=0x00  D3-1 R1=0x00  D3-1 R2=0x00  
D3-0 R0=0x01  D3-0 R1=0x00  D3-0 R2=0x00  D3-0 R3=0x44  D3-0 R4=0x00  
D3-1 R0=0x00  D3-1 R1=0x80  D3-1 R2=0x00  
D3-0 R0=0x00  D3-0 R1=0x00  D3-0 R2=0x00  D3-0 R3=0x44  D3-0 R4=0x00  
D3-1 R0=0x01  D3-1 R1=0x80  D3-1 R2=0xa5  
[1] + Done                       "/usr/bin/gdb" --interpreter=mi --tty=${DbgTerm} 0<"/tmp/Microsoft-MIEngine-In-ulin2vku.3zm" 1>"/tmp/Microsoft-MIEngine-Out-eystlo0h.ob5"

最后叠甲

  1. 不要做过度的设计,没必要为了一个简单的需求写一个复杂的系统,如果这个需求是后两个版本做的,就把重构工作给后两个版本吧,谁也不知道这个代码中间会不会有改动。
  2. 代码能跑就不要动他,除非你觉得这个代码很复杂繁琐,或者增加代码以及非常的麻烦了,再去重构。
  3. 这里HAL层最好的一个理念就是抽象,业务层不需要了解底层干了啥,只需要了解HAL提供的抽象的接口“打开” “关闭”如何使用。
http://www.dtcms.com/a/612991.html

相关文章:

  • 如何用网站赚钱淮安做网站找哪家公司
  • 最牛的SEO教程网站农产品交易平台
  • 网站详情页怎么做郑州网站制作郑州网站制作
  • 网站建设查看框架的源代码网站建设整个流程
  • 做一下网站网站北京中航空港建设工程有限公司网站
  • 网站建设8万属于资产吗做书一般在哪个网站下载素材
  • 凤岗本地网站wordpress怎么保存xml
  • asp.net做电商网站页面深圳vi设计公司排行
  • 阿里巴巴网站开发信在哪陕西印象信息技术有限公司
  • 网站域名实名认证怎么做seo推广效果怎么样
  • 门户网站建设合同广西中小企业网站建设
  • 淘宝店做网站建设不能开直通车营销型网站建设大千建站
  • 网站推广策划思路的内容广州定制网站设计
  • 微舍 微网站 怎么做有关小城镇建设网站
  • 网站建设与优化推广方案内容中国空间站合作的17个国家
  • 做网站要考虑什么问题seo培训学院
  • 昆明制作网站的公司哪家好青岛百度推广多少钱
  • 设建网站网站留言短信提醒
  • 房地产网站模版企业管理软件管理系统牛
  • 手机网站设计案做五金奖牌进什么网站
  • 做网站搞流量网站建设验收确认书免费下载
  • 精准引流推广文案seo优化系统哪家好
  • 网站数据中心的建设湖北网站建设推荐
  • 网站建设任职软件项目实施流程八个阶段
  • 百度搜不到 但搜关键词有的网站申请一个网站空间
  • 重庆智能网站建设价格西安网站制作公司推荐
  • 企业网站设计布局方式asp网站后台失效
  • 越南做It网站推广全国企业网
  • 网站开发的常用软件奎文区建设局网站
  • 韶关市住房和城乡建设管理局网站中国公司名录大全