[其他产品] IO复用,增加加锁机制

[复制链接]
2759|7
 楼主| meiyaolei 发表于 2025-5-26 11:24 | 显示全部楼层 |阅读模式
“嵌入式开发代码复用,你咋玩才省心?”
嵌入式开发老写重复代码,烦得要命。你们咋搞代码复用的?模块化封装一顿秀,还是抄个HAL库改改?快来聊聊你的代码复用妙招,或者讲讲哪次代码抄来抄去抄出Bug的糗事!


嵌入式开发里老重复造轮子,代码写得手抽筋,还容易埋雷!我跟你唠唠我的代码复用骚操作,顺便吐槽下抄代码翻车的糗事。

其实代码复用的“骚操作”是非常的常见的,又想用便宜的IC,但是又想把IC的资源全部都用上,就会出现很多利用的现象,而且很多都会封装成模块。

之前写过个GPIO驱动模块,把ADC采集、PWM输出、中断触发这些功能全封装成接口。用GPIO_Init()初始化引脚,ADC_Read()读电压,GPIO_Set()当普通IO输出,这样做有的是时候功能稍微没有配合好,就会出现很多复杂的用法,会增加蛮多的代码量而且当自己写好的时候也会感觉 自己有一些提升,但是如果没有配合好就会出现一定有BUG,就会让自己拼命的在DUG,找问题解决问题。

这个也有一定的好处,如果封装成模块,那出现问题时就直接模块,而且换项目时直接拖模块,改个引脚号就能用,省得每次翻手册查寄存器。
不过用STM32的HAL库时,发现它的ADC初始化代码太啰嗦,有经验的工程师都会有自己的想法,我就封装了个ADC的模块,把配置参数塞进去,一键生成驱动。

当需要改模块和库时,肯定会出问题改库得谨慎!比如把ADC引脚复用成普通IO时,得先调HAL_GPIO_DeInit()释放资源,不然下次用ADC会炸,配合不会就会严重影响工作。有次项目里,ADC采集和普通IO口复用同一个引脚。调试时发现ADC读数不稳定,排查半天发现是GPIO模式和ADC模式切换时引脚状态冲突——ADC采样时引脚被其他模块偷偷当IO口拉低了电压,导致采样值跳变。最后增加了一个加锁机制,确保同一时间只有一种模式生效。

  1. // 全局管理器实例
  2. PinMuxManager io_manager;

  3. void ADC_Task(void) {
  4.     if(PINMUX_SafeSwitchMode(&io_manager, PIN_ADC_MODE, 100) == HAL_OK) {
  5.         HAL_ADC_Start(io_manager.adc_handle);
  6.         if(HAL_ADC_PollForConversion(io_manager.adc_handle, 10) == HAL_OK) {
  7.             uint16_t value = HAL_ADC_GetValue(io_manager.adc_handle);
  8.             printf("ADC Value: %d\n", value);
  9.         }
  10.         PINMUX_SafeSwitchMode(&io_manager, PIN_FREE, 100); // 释放引脚
  11.     }
  12. }

  13. void GPIO_Task(void) {
  14.     if(PINMUX_SafeSwitchMode(&io_manager, PIN_GPIO_OUT_MODE, 100) == HAL_OK) {
  15.         HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);
  16.         HAL_Delay(10);
  17.         PINMUX_SafeSwitchMode(&io_manager, PIN_FREE, 100); // 释放引脚
  18.     }
  19. }

  20. // 安全异常处理
  21. void HardFault_Handler(void) {
  22.     PINMUX_ForceUnlock(&io_manager);  // 强制解锁
  23.     while(1);
  24. }


玛尼玛尼哄 发表于 2025-5-27 07:01 | 显示全部楼层
看看什么是枷锁机制
zjsx8192 发表于 2025-5-27 08:17 | 显示全部楼层
不会复用到这个程度吧,adc口一般专用
tpgf 发表于 2025-5-27 08:57 | 显示全部楼层
这个枷锁的意思是通过软件来实现互斥,保证变量不被非法利用吗?
dffzh 发表于 2025-5-27 10:50 | 显示全部楼层
用过的复用操作就是把烧录调试口用作I2C使用,每次debug时总是要多一步屏蔽I2C配置的操作,引脚复用是有些麻烦的,尽量少用
xuanhuanzi 发表于 2025-5-29 21:38 | 显示全部楼层
MCC的代码就类似这种。
迷雾隐者 发表于 2025-6-3 08:31 | 显示全部楼层
确实,代码复用是嵌入式开发中的一大挑战。我通常会创建一个配置文件,将所有引脚配置和功能映射到文件中,这样在不同项目中只需要修改配置文件即可快速复用代码。
作业粉碎机 发表于 2025-6-3 20:58 | 显示全部楼层
确实,嵌入式开发中代码复用是个大学问。我通常也会把常用的功能封装成模块,方便调用和移植。不过,确实要注意模块间的资源冲突问题,加锁机制是个不错的解决方案。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:工程师
简介:超越自我,为设计激发灵感和想象。

263

主题

836

帖子

6

粉丝
快速回复 在线客服 返回列表 返回顶部