meiyaolei 发表于 2025-5-26 11:24

IO复用,增加加锁机制

“嵌入式开发代码复用,你咋玩才省心?”
嵌入式开发老写重复代码,烦得要命。你们咋搞代码复用的?模块化封装一顿秀,还是抄个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口拉低了电压,导致采样值跳变。最后增加了一个加锁机制,确保同一时间只有一种模式生效。
// 全局管理器实例
PinMuxManager io_manager;

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

void GPIO_Task(void) {
    if(PINMUX_SafeSwitchMode(&io_manager, PIN_GPIO_OUT_MODE, 100) == HAL_OK) {
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);
      HAL_Delay(10);
      PINMUX_SafeSwitchMode(&io_manager, PIN_FREE, 100); // 释放引脚
    }
}

// 安全异常处理
void HardFault_Handler(void) {
    PINMUX_ForceUnlock(&io_manager);// 强制解锁
    while(1);
}

玛尼玛尼哄 发表于 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

确实,嵌入式开发中代码复用是个大学问。我通常也会把常用的功能封装成模块,方便调用和移植。不过,确实要注意模块间的资源冲突问题,加锁机制是个不错的解决方案。
页: [1]
查看完整版本: IO复用,增加加锁机制