【单片机】开发中遇到的复杂问题 例子0https://www.kdocs.cn/l/cp1DT0sq6ltW例子1gsm_info NULL; //这里给指针赋值0x00000000 gsm_info (TYPE_GSM_PROCESS *)OSQPend(gsm_process_q, OSCfg_TickRate_Hz, OS_OPT_PEND_BLOCKING, size, NULL, err); if(err OS_ERR_NONE) { if(gsm_info NULL) { continue; //进入下一个循环 } sim800c_status_key gsm_info-sim800c_status_key; } sim800c_main_process(gsm_info);//如果没有新的消息那么gsm_info就是NULL但是在函数里也不会调用。 free_gsm_processreq(gsm_info);//程序在这里就硬件错误了是因为gsm_info是一个空指针不能对其操作例子2void gsmprecheck_task(void *pdata) { OS_ERR err; pdata pdata; while(1) { OSSemPend(gsm_precheck_sem, 0, OS_OPT_PEND_BLOCKING, NULL, err);//这个信号不能正常运行 if(err OS_ERR_NONE) { sim800c_precheck_rev(); } } }信号量gsm_precheck_sem是在串口接受数据后post的。不能正常接受的原因根本上是优先级的问题没有安排好也是因为比它优先级更高的任务里的延时用的delay_ms没有使用OS里延时API。在不用OS的程序里相当于单线程任务与任务之间只能只用标志位交流但是如果使用OS是多线程使用任务之间的交流需要更加紧密、次序分明所以需要使用信号量如果离的比较远要求不高可以使用标志位。例子3在UCOSIII中遇到了程序死机不再运行也不会进HardFault中断但调试时明显的就是延时不正常一般可能就是某个任务的栈空间不够。例子4u8 sim800c_send_cmd(u8 *cmd, u8 *ack, u16 waittime) { u8 times; u8 res 0; if(cmd ! NULL) { sim800c_send_TTL(cmd, strlen((char *)cmd));//指令都是字符串 } waittime waittime*100; sim800c_rx_complete 0; for(times 0; times waittime; times)//由于变量times是一个字节不能大于255所以输入值为3则出问题 { delay_ms(1000/100); if(1 sim800c_rx_complete) { if(sim800c_check_cmd(ack)) { break;//得到有效数据 } else { res 1;//没有得到有效数据 } } } return res; }给一个字节变量赋值大于255的数是经常被疏忽的问题值得警惕。例子5例子6电表休眠后由超级电容供电当出现供电电流变化震荡时可能是超级电容没充满。HT6333在休眠后可以每500ms进行一次温度采样导致供电电流在4~20uA内震荡。例子7FM33LC0单片机串口用8N1上位机用8E1或者8O1通信大部分报文通信失败偶尔成功。改单片机串口用8N2上位机通信都成功。排查次问题测试了两个USB-TTL模块互相发发现校验位停止位大于等于2个bit通信都能成功。应该是模块问题不判断校验位了。例子7头文件异常问题不加#ifndef #define导致无限包含浪费编译资源加#ifndef #define不同头文件交叉引用可能导致某些类型未定义见错误集20250612头文件中定义变量多个C文件包含该头文件重定义编译报错头文件中定义的变量加static浪费空间若多个不同头文件定义同名变量且被一个C文件引用编译报错注意头文件引用包括头文件路径是不判断大小写的例子8SPI全双工是因为它的总线设计但在单片机应用中分主机从机一问一答信息是以半双工的方式传递的。https://www.kdocs.cn/l/cmwq2PdW4jxfUART全双工发送和接收都是独立进行的。CAN和485是差分线只能是半双工。100K速率的EE用页写的话大概10字节1ms不算结束等待时间。例子9在写驱动时对于异常情况的处理如果检查开销小就先检查反之则先运行在超时等错误发生后再处理。软件iic可以提前判断sda口线电平硬件iic可以提前判断busy位如果单片机不支持busy则通过口线配置先当成软件iic处理再设置复用功能。如果是特别重要的器件最好先检查等运行错误后再处理可能就来不及了。例子10参数保固其实是参数和数据保固需要频繁会对外产生交互都可以放在里面。变量保固主要是自己产生并需要频繁使用的。不能在中断中使用参数保固读接口由于参数保固会定期破坏CRC导致在中断中读EE。关于参数保固使用场景总结1、单个参数配单个CRC长度较小且无需在中断中使用。建议使用参数保固服务。2、多个参数配单个CRC或者参数较大或者在中断中使用。建议使用用参数保固的思想将原本服务里的接口代码展开处理。除了定期检查CRC也有用的时候才检查也要定期破坏CRC一般是15分钟刷新RAM的参数。修改参数的时候先改RAM参数然后再写EE。后续可以破坏CRC也可以不破坏可以立马检查CRC也可以等定期。刷新参数的时候先从EE读到临时变量和参数比较后再复制到参数上如果参数需要在中断中使用这个复制过程就需要原子操作。3、某些组件由于高内聚需求即使满足第1点使用情况也不用参数保固服务参数需要自我管理用法上同第2点。4、串口波特率之类的硬件参数最好通过判断变化及时重置硬件可以不用消息机制。例子11int a b c 4; //编译报错b和c未定义 int a, b, c; a b c 4; //ok if (a b c) //编译报错的优先级比高 { } if (a (b c)) //ok { }例子12单片机在调试中打断点暂停的是CPU的运行各外设继续运行。20251202进休眠前一定要先关闭所有可能唤醒休眠的外设然后再设置唤醒源。比如RTC中断即使已经禁用全局中断也无用。HT5023单片机在进sleep模式前要使能全局中断否则不会进休眠原因未知。20251208钜泉单片机的IO有推挽和上拉对于普通输出或者数字输出上拉功能无效对于普通输入和数字输入推挽功能无效对于模拟功能和LCD功能推挽和上拉都无效。20251216正常开发中使用EE存参数和关键数据如果使用flash存参数和关键数据即使用easyflash等的软件组件有磨损均衡、原子操作、坏块管理等但是无法解决在掉电保存时可能触发擦扇区这一动作。EE存一页固定耗时5ms但flash擦一页典型30ms最大400ms无法接受。easyflash可以作为消费级产品上的参数管理但是在工业级别上是不能用的关键数据的及时且100%的保存是必须的。如果使用场景中可以接受掉电时参数回滚就可以用easyflash或者littlefs。easyflash可以认为是一个简化版的文件系统如果用来存参数比较适合参数量少的情况一旦数量上去读写会很慢也不能接受。基本上如果是电表类应用单片机主频很低一般都是直接操作硬件提高响应速度根据实际需求走。如果在电表上不得已只能用flash替代EE需要确保掉电保存时不用擦扇区。1、平时修改参数时使用实时刷写不用走缓存2、上电时准备好掉电保存的扇区掉电时直接写。这样一来就需要重新设计一套方案不能用easyflash可以借鉴它的优秀思想但还是挺麻烦的。。。没有必要搞这一套。同时自己需要对网上那套“库”去魅。20251224节拍不一定指节拍服务更加适用于周期性功能要求或者某种时序实现。延时服务则更多的适用于某些超时或者延续多长时间的概念。虽然某种程度上两者可以互相实现对方的功能但是我们使用的时候尽量贴合它的本意。20260202在实际单片机开发中在环形队列上队列元素最好是2的幂次数这样取模运算40个时钟周期可以用位与替代更加适合在中断通信上。通信环服务是从kfifo的基础上改进而来但回绕点是SIZE1且不判断队满可以不断的塞数据。信号环一般不会频繁调用近似最小实现但是多了一个整倍数回绕点不浪费一个存储空间。现有算法服务虽然不是标准的易理解的但是足够使用并具有较大共识所以我只需要了解它怎么实现并知道标准实现即可不强求、多包容。20260205优化等级对软件延时的影响最大/* ******************************************************************************** * 函 数 名: i2c_Delay * 功能说明: I2C总线位延迟最快400KHz不能被优化 * 形 参: 无 * 返 回 值: 无 ******************************************************************************** */ #pragma optimize none static void i2c_Delay(uint8_t index) { switch (index) { case SOFT_I2C1_INDEX: for (int i 0; i 3; i); break; default: break; } }20260416矩泉单片机上的串口标志只有接收完成和发送完成。串口的驱动代码在移植到GD上时接收完成用接收非空标志替代发送完成用发送空标志替代会出问题。原因矩泉上是先使能发送完成中断然后发送一个字节触发中断在GD上是使能发送空中断后立马就会触发中断导致异常。补充单片机上发送空标志置位后数据还要等一会儿才能从引脚发送完毕只有发送完成标志置位后串口引脚才算真正把数据发完。20260708问题现象HT6025K的休眠功耗高或者测量RTC电池功耗跳变快。原因芯片休眠后即使没有VCC只有VRTC供电也会根据TMPPRD的值周期采样温度补偿RTC。在没有VCC的情况下VRTC断开又连上也算冷启动温度0.5s采样一次。20260709CMOS器件的Latch-Up闩锁效应特性EMC实验时容易有电流进入导致闩锁。浮空输入和无上拉开漏输出高模式容易受影响。norflash的口线容易被打坏无法读写需要重新掉上电。