单片机学习过程中常见问题的解决思路和解决办法!

前面分享了,单片机学习过程中需要面对的143个技术细节,今天和大家分享,在项目中遇到了问题该如何解决。对于依赖外部输入的条件,如果条件比较复杂难以模拟可以考虑程序里预设直接进入对应状态。此类问题只能熟读单片机数据手册,注意类似的细节问题。

1. 问题再次出现

只有稳定地重现问题,才能正确定位问题、解决问题、验证问题。 一般来说,问题越容易重现,解决它就越容易。

1.1 模拟重现条件

有些问题是在特定条件下存在的,可以通过模拟问题发生的条件来重现。 对于依赖外部输入的条件,如果条件复杂、难以模拟,可以考虑预设程序直接进入相应的状态。

1.2 增加相关任务的执行频率

例如,如果某个任务运行时间较长,出现异常,则可以提高该任务的执行频率。

1.3 增加测试样本量

如果程序长时间运行后出现异常,问题就很难重现。 您可以搭建一个测试环境,同时测试多套设备。

2.问题定位

缩小故障排除范围并确定导致问题的任务、功能和语句。

2.1 打印日志

根据问题的现象,在问题代码中添加LOG输出,跟踪程序执行过程以及关键变量的值,观察是否与预期一致。

2.2 在线调试

在线调试可以起到与打印LOG类似的作用。 另外,该方法特别适合排除程序崩溃bug。 当程序陷入异常中断(HardFault、看门狗中断等)时,可以直接STOP查看调用堆栈和内核寄存器。 快速定位问题点的价值。

2.3 版本回滚

使用版本管理工具时,可以不断回滚版本并进行测试验证,定位到最先出现问题的版本,然后围绕该版本中添加和修改的代码进行排查。

2.4 二分注释

二进制注释以类似于二分查找方法的方式注释掉部分代码,以判断问题是否是由注释掉的部分代码引起的。

具体方法是注释掉一半与问题无关的代码,看看问题是否解决。 如果没有解决,则注释掉另一半。 如果解决了,继续将评论范围缩小一半,以此类推逐步缩小问题范围。

2.5 保存内核寄存器快照

当Cortex M核心陷入异常中断时,它会将几个核心寄存器的值压入堆栈,如下所示:

单片机学习过程中常见问题的解决思路和解决办法!

我们可以在发生异常中断时,将堆栈上的内核寄存器值写入RAM中保留复位后默认值的区域。 执行复位操作后,从RAM中读取并分析信息,通过PC和LR确认当时的执行情况。 函数,用R0-R3来分析当时正在处理的变量是否异常,用SP来分析是否可能发生堆栈溢出等。

【学习交流群】不知道如何学习? 有问题但没人问? 到处寻找信息? 邀请您加入我的嵌入式物联网单片机学习交流群。 群里气氛活跃。 有专家、新手、员工、学生。 还有群友整理收集的100G教程资料。 点击下方加入群组并入座。 (点击跳转群二维码,请随意点击!)

单片机学习过程中常见问题的解决思路和解决办法!

三、问题分析与处理

根据问题现象和问题代码所在位置分析问题原因。

3.1 程序继续运行 3.1.1 数值异常 3.1.1.1 软件问题

1.数组越界

写入数组时,下标超出数组长度,导致对应地址内容被修改。 如下:

单片机学习过程中常见问题的解决思路和解决办法!

此类问题通常需要结合map文件进行分析。 通过map文件,观察被篡改变量地址附近的数组,检查对数组的写操作是否包含如上图所示的不安全代码,并修改为安全代码。

2. 堆栈溢出

0x20001ff8g_val

如上所示,此类问题还需要结合map文件来分析。 假设堆栈从高地址向低地址增长,如果发生堆栈溢出,则g_val的值将被堆栈上的值覆盖。

当发生堆栈溢出时,必须分析堆栈的最大使用情况。 函数调用层次过多、中断服务函数内的函数调用、函数内声明的临时变量过大都可能导致堆栈溢出。

解决此类问题有以下几种方法:

3、判断语句条件写错

单片机学习过程中常见问题的解决思路和解决办法!

很容易在判断语句的条件中将等号运算符“==”写成赋值运算符“=”,导致被判断的变量的值发生改变。 此类错误在编译时不会报错,始终返回true。

建议将需要判断的变量写在运算符的右侧,这样如果误写为赋值运算符,编译时会报错。 您还可以使用一些静态代码检查工具来发现此类问题。

4、同步问题

例如,操作队列时,出队操作执行过程中发生中断(任务切换),在中断(切换任务)过程中执行入队操作可能会破坏队列结构。 在这种情况下,应在操作期间关闭中断(使用互斥同步)。

5、优化问题

单片机学习过程中常见问题的解决思路和解决办法!

如上面的程序所示,其初衷是等待irq中断,不再执行foo()函数。 但经过编译器优化后,flg在实际运行时可能会被加载到寄存器中,每次都会判断寄存器中的值,而不需要重新从ram中取出。 即使发生 irq 中断,读取 flg 的值也会导致 foo() 继续运行。 这里需要在flg的声明前添加“volatile”关键字,强制每次从ram中获取flg的值。

3.1.1.2 硬件问题

1.芯片BUG

芯片本身有BUG。 在某些情况下,会向微控制器返回不正确的值。 程序需要对读回的值进行判断,过滤掉异常值。

2、通讯时序错误

单片机学习过程中常见问题的解决思路和解决办法!

例如电源管理芯片Isl78600,假设现在有两个芯片级联,当同时读取两个芯片的电压采样数据时,高端芯片会将数据通过固定周期菊花链,低端芯片只有一个缓存。 区。

如果单片机在规定的时间内没有读取低端芯片上的数据,新的数据到达时就会覆盖当前的数据,导致数据丢失。 此类问题需要仔细分析芯片的数据表并严格遵守芯片通信的时序要求。

3.1.2 运行异常 3.1.2.1 软件问题

1. 设计问题

如果设计中存在错误或遗漏,则需要重新审查设计文件。

2. 实现与设计不符

如果代码的实现与设计文档不符,则需要添加单元测试来覆盖所有条件分支并对代码进行交叉审查。

3. 异常状态变量

例如,记录状态机当前状态的变量已被篡改。 分析此类问题的方法与上一节数值异常相同。

3.1.2.2 硬件问题

1、硬件故障

目标IC出现故障,收到控制命令后不动作。 需要检查硬件。

2、通讯异常

与目标IC通讯出现错误,控制命令无法正确执行。 需要使用示波器或逻辑分析仪观察通信时序,分析发送的信号是否不正确或受到外部干扰。

3.2 程序崩溃 3.2.1 停止运行 3.2.1.1 软件问题

1.硬故障

以下情况可能会导致HardFault:

以little-endian顺序为例,如果我们声明一个强制对齐结构如下:

单片机学习过程中常见问题的解决思路和解决办法!

地址 0x000000000x000000010x000000020x00000003

此时a.val1的地址为0x00000001。 如果使用 uint16_t 类型取消引用该地址,则会因对齐问题而进入 HardFault。 如果必须使用指针来操作变量,则应该使用memcpy()。

2、中断服务函数中没有清除中断标志

中断服务函数退出前未正确清除中断标志。 当程序执行从中断服务函数退出时,会立即进入中断服务函数,呈现出程序的“挂起死亡”现象。

3.NMI中断

在调试过程中,遇到SPI的MISO引脚复用了NMI功能。 当通过SPI连接的外设损坏时,MISO被拉高,导致单片机复位后直接进入NMI中断,然后再将NMI引脚配置为SPI功能。 程序因 NMI 中断而挂起。 这种情况可以通过在NMI中断服务函数中禁用NMI功能来退出NMI中断。

3.2.1.2 硬件问题

1、晶振不启动。

2、电源电压不足

3. 将复位引脚拉低

3.2.2 复位3.2.2.1 软件问题

1. 看门狗复位

除了喂狗超时导致的复位外,还要注意看门狗配置的特殊要求。 以飞思卡尔 KEA 微控制器为例。 微控制器看门狗在配置时需要执行解锁序列(两次不同的连续写入其寄存器)。 值),解锁序列必须在 16 个总线时钟内完成,超时将导致看门狗复位。 对于此类问题,只能仔细阅读单片机数据手册,注意类似细节。

3.2.2.2 硬件问题

1、电源电压不稳定

2、电源负载能力不足

4. 回归测试

问题解决后,需要进行回归测试。 一方面,需要确认问题是否不再出现。 另一方面,需要确认修改不会引入其他问题。

五、经验总结

总结一下这个问题的原因以及如何解决,思考以后如何防止类似的问题,同平台的产品是否值得借鉴,举一反三,从失败中吸取教训。

单片机

人工种植树莓的成本收益是怎样的?种植前景分析

2024-4-7 7:04:05

单片机

基于单片机的超市电子秤设计与实现的设计项目分享

2024-4-7 8:05:04

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索