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

UART问题解析

一、先破误区:结构体指针数组 →绝对不能直接放结构体变量!

先看你的代码:
// 结构体指针数组 struct UART_Device *g_uart_devs[] = {&g_stm32_uart1};

1. 先分清 3 个东西(核心!)

代码写法
是什么?
比喻
struct UART_Device
结构体类型(图纸)
房子设计图
g_stm32_uart1
结构体
变量
(实体)
真实的房子(设备)
&g_stm32_uart1
结构体
指针
(地址)
房子的
门牌号
struct UART_Device *[]
结构体
指针数组
一本
通讯录

2. 关键结论

  • 结构体指针数组:里面的每个格子,只能存「门牌号(指针 / 地址)」
  • 不能直接把「房子(结构体变量)」塞进数组里!
struct UART_Device *g_uart_devs[] = {&g_stm32_uart1};
翻译成人话:
我创建了一个通讯录(指针数组),里面只记了1 个门牌号:这个门牌号指向g_stm32_uart1这个真实的串口设备。

3. 为什么要这么写?(嵌入式必知)

  1. 省空间:指针只有 4 字节(32 位单片机),结构体很大,存地址更高效
  2. 方便操作:拿到门牌号(指针),就能直接找到房子(设备),调用它的功能
  3. 统一管理:所有设备的门牌号都放一起,方便查找

二、核心:这个数组 +GetUARTDevice函数 →如何互相配合?

我用 **「通讯录 + 查通讯录」** 的比喻,结合你的代码,一步一动讲联动逻辑:

前置准备(两者配合的基础)

1. 你先造了一个「真实设备」(房子)

// 实体结构体变量:实实在在的uart1设备,自带名字、方法、私有数据 static struct UART_Device g_stm32_uart1 = { .name = "stm32_uart1", .init = stm32_uart_init, .send = stm32_uart_send, .recv = stm32_uart_recv, .priv_data = &g_stm32_uart1_data, };

2. 你把「设备的门牌号」放进「通讯录数组」

// 指针数组 = 通讯录:只存设备的地址(门牌号) struct UART_Device *g_uart_devs[] = {&g_stm32_uart1};
✅ 此时通讯录状态:g_uart_devs[0]= 门牌号 → 指向g_stm32_uart1设备

正式配合:上层调用GetUARTDevice函数

// 指针数组 = 通讯录:只存设备的地址(门牌号) struct UART_Device *g_uart_devs[] = {&g_stm32_uart1};

函数开始工作,和数组完美联动:

struct UART_Device *GetUARTDevice(char *name) { int i = 0; // 👇 第一步:遍历通讯录(指针数组),看有几个门牌号 for(i=0; i<(sizeof(g_uart_devs) / sizeof(g_uart_devs[0])); i++) { // 👇 第二步:拿出通讯录里的第i个门牌号 → 找到对应的房子 // 👇 第三步:比对房子的名字 和 你要找的名字 if(0 == strcmp(name, g_uart_devs[i]->name)) // 👇 第四步:名字匹配!把这个门牌号返回给上层 return g_uart_devs[i]; } return NULL; }

逐步骤联动拆解(最关键!)

步骤 1:函数找数组 → 「我要查通讯录了」

for循环先计算数组长度:知道通讯录里有1 个门牌号

步骤 2:数组给函数 → 「给你第一个门牌号」

g_uart_devs[0]&g_stm32_uart1这个指针交给函数。

步骤 3:函数用指针 → 「通过门牌号找到房子,看它的名字」

g_uart_devs[i]->name→ 通过指针(门牌号),访问设备结构体的name成员。

步骤 4:名字匹配 → 函数把指针返回上层

return g_uart_devs[i];→ 把这个设备的 ** 门牌号(指针)** 还给上层。

最终结果:

上层拿到指针 → 就能调用这个设备的init/send/recv方法!

三、可视化:它们的关系(一眼看懂)

【上层应用】 ↓(调用 GetUARTDevice("stm32_uart1")) 【查找函数】 ↓(遍历) 【指针数组 g_uart_devs】 ↓(存的是:&g_stm32_uart1 指针) 【实体设备 g_stm32_uart1】 (包含:名字、init、send、recv、私有数据)

四、扩展:以后加 UART2,它们怎么配合?

你只需要加 2 行代码,函数完全不用改!这就是配合的强大之处:
// 1. 新增uart2实体设备 static struct UART_Device g_stm32_uart2 = {...}; // 2. 把uart2的门牌号加入通讯录数组 struct UART_Device *g_uart_devs[] = {&g_stm32_uart1, &g_stm32_uart2};
✅ 查找函数自动遍历 2 个门牌号,依旧能精准找到设备。

五、终极总结(两句话记住)

1. 结构体指针数组

  • 只能存结构体的地址(指针 / 门牌号),不能直接存结构体变量
  • 作用:统一管理所有设备的地址,相当于设备通讯录

2. 数组 + 查找函数 的配合逻辑

  • 数组是花名册(记所有设备的门牌号)
  • 函数是查花名册的人
  • 函数通过遍历数组 → 拿到设备指针 → 比对名字 → 返回匹配的设备指针

一句话秒懂

数组负责把所有设备的「门牌号」集中存放,函数负责拿着你给的名字,去数组里挨个查门牌号,找到对应设备就把地址还给你!
http://www.jsqmd.com/news/706911/

相关文章:

  • 2026成都合同纠纷维权指南:成都劳动合同纠纷律师事务所/成都合伙合同纠纷律师事务所/成都合同欠款纠纷律师事务所/选择指南 - 优质品牌商家
  • 2026年优秀单元门标杆名录:铝合金窗/防火卷帘门/防火门/防爆门/防盗门/隔音门/不锈钢门/保温门/别墅大门/选择指南 - 优质品牌商家
  • 2026丙烯酸复合橡胶弹性隔声涂层厂家排行:四川楼板隔声材料厂家、四川隔声材料哪家专业、四川隔声材料哪家好、地面隔音涂料选择指南 - 优质品牌商家
  • MySQL 零基础全套入门教程|DDL+DML + 五大约束 + DQL 查询(超详细代码笔记)
  • 先进制造与高端装备类航空发动机研制项目方案
  • HashMap底层原理
  • 成都地区、H型钢、400X400X13X21、Q235B、安泰、现货批发供应 - 四川盛世钢联营销中心
  • 好用的景观灯源头厂家哪个靠谱
  • Power BI学习笔记第20篇:面试题汇总 · 第三篇:高级应用与最佳实践篇
  • 成都地区、H型钢、390X300X10X16、Q235B、安泰、现货批发供应 - 四川盛世钢联营销中心
  • AI写论文不用愁!4款AI论文写作工具,快速产出高质量论文!
  • CAM++说话人识别系统快速入门:科哥镜像3步搭建声纹验证工具
  • S32K3双核实战:手把手教你配置CAN与CANFD,中断和轮询到底怎么选?
  • 工业数字隔离技术与高可靠性设计实战指南
  • 从Transformer到大模型:主流预训练模型架构演进与Transformers库实战指南
  • 【MySQL深入详解】第18篇:索引维护——保持索引高效的日常操作
  • 成都地区、H型钢、340X250X9X14、Q235B、安泰、现货批发供应 - 四川盛世钢联营销中心
  • 2026 成都GEO优化服务商行业分析报告(橙鱼传媒专项研究)
  • LM文生图镜像部署教程:非技术人员也能理解的Web服务启动逻辑
  • SOLIDWORKS异形孔向导3D草图约束
  • Phi-3-mini-4k-instruct-gguf镜像部署教程:适配A10/A100/T4的vLLM GPU算力配置
  • 2026Q2热门上海财务代理:上海财务代理记账、上海财务咨询、上海财务外包、上海财务审计报告、上海外资公司注册选择指南 - 优质品牌商家
  • 避开中介套路,姚店长给购房者满满的安心
  • ofa_image-caption步骤详解:临时文件管理、Pipeline超参设置与结果缓存机制
  • 【Docker AI Toolkit 2026终极指南】:5大颠覆性新功能+3步极速安装+插件生态全图谱(仅限首批认证开发者)
  • QNX迷你驱动技术:解决车载系统启动延迟的革新方案
  • 保姆级教程:在OpenHarmony 3.2上用ESP32驱动MQ-2烟雾传感器(附完整代码与避坑指南)
  • 大模型内部的数学世界
  • 成都地区、H型钢、250X250X9X14、Q235B、安泰、现货批发供应 - 四川盛世钢联营销中心
  • AI应用开发工作流工具:标准化与简化AI集成开发