困扰一周的奇葩bug:重复相似代码多,导致单片机程序跑飞

简介: 困扰一周的奇葩bug:重复相似代码多,导致单片机程序跑飞

今天是个好日子,困扰一周的bug终于解决了,迫不及待将这个奇葩问题分享给各位朋友~


硬件环境:


国产MCU:华大HC32L130


问题描述:


最近做一款基于Modbus协议的三通道温度采集模块,程序设计是移植之前验证过的两通道温度、压力采集模块的程序,完成后,三通道温度采集程序可正常运行。


最后需要对三通道温度采集模块添加二次校准算法功能,新功能写好后,也可正常采集和通信,但是使用IAP功能时,flash扇区擦除失败,无法跳转到升级程序,且程序跑飞。


问题分析和解决:


尝试1:修改新增加的二次校准算法功能程序。


将二次校准算法功能屏蔽,升级程序可正常使用,估计是这里的问题,进行修改:变量定义、指针地址、内存管理等一系列操作下来,问题没有解决。


此时我的排查侧重点是数据内存或者地址溢出方面。


尝试2:查看flash配置是否存在问题。


既然是flash扇区擦除失败,会不是是配置存在问题?通过查看寄存器,修改时隙间隔等方面,还是无法解决问题,主要是之前运行一直没问题,排除这点。


那么会不会新添加的二次校准算法功能和已经存在的功能冲突呢?或者是使用的全局结构体变量有问题?


尝试3:整体研读项目代码,重点排查二次校准算法功能中全局变量、全局结构体变量的使用。


并没有变量使用不合理或者逻辑错误的地方。


尝试4:按照功能模块屏蔽代码,是否是程序中某部分功能与二次校准算法功能程序冲突。


通过一点点屏蔽程序,发现在二次校准算法功能程序正常运行前提下,屏蔽主循环的Modbus显示功能、Modbus配置UART功能、传感器GPIO配置等多个部分均可正常使用IAP功能。


通过仔细分析,这些功能模块中变量定义和使用均不存在问题,此时心态很郁闷了,这些模块功能基本没有关联。


尝试5:通过修改某个功能模块代码,是否可使程序正常运行。


此时项目整体功能是不存在逻辑问题和bug的,是否可以通过将以上那些存在未知冲突故障的代码换种写法,让程序正常运行呢?


经过了一系列操作和尝试,将主循环的Modbus显示功能代码换种更简洁的写法,程序可以完美运行~


原程序如下所示:


if(nModbusCalRegs[Modbus_RegCalChan-Modbus_RegCalChan] == TEMP1_CHANNEL_ID)
 {
   ///< 初始化温度传感器:校准量程、零点偏移、灵敏度、零点偏移系数和灵敏度偏移系数
   nModbusCalRegs[Modbus_CalChanIndex] = strDeviceParamSave.temp1_range;
   memcpy((uint8_t *) &ltemp,(uint8_t *) &strDeviceParamSave.temp1_bias1, 4);
   ntemp = (uint16_t) ltemp;
   nModbusCalRegs[Modbus_CalZeroIndex] = ntemp;
   ntemp = (uint16_t) (ltemp >> 16);
   nModbusCalRegs[Modbus_CalZeroIndex+1] = ntemp;
   memcpy((uint8_t *) &ltemp,(uint8_t *) &strDeviceParamSave.temp1_kate1, 4);
   ntemp = (uint16_t) ltemp;
   nModbusCalRegs[Modbus_CalKateIndex] = ntemp;
   ntemp = (uint16_t) (ltemp >> 16);
   nModbusCalRegs[Modbus_CalKateIndex+1] = ntemp;
   memcpy((uint8_t *) &ltemp,(uint8_t *) &strDeviceParamSave.temp1_bias2, 4);
   ntemp = (uint16_t) ltemp;
   nModbusCalRegs[Modbus_CalKZeroIndex] = ntemp;
   ntemp = (uint16_t) (ltemp >> 16);
   nModbusCalRegs[Modbus_CalKZeroIndex+1] = ntemp;
   memcpy((uint8_t *) &ltemp,(uint8_t *) &strDeviceParamSave.temp1_kate2, 4);
   ntemp = (uint16_t) ltemp;
   nModbusCalRegs[Modbus_CalKSensiIndex] = ntemp;
   ntemp = (uint16_t) (ltemp >> 16);
   nModbusCalRegs[Modbus_CalKSensiIndex+1] = ntemp;
 }
 else if(nModbusCalRegs[Modbus_RegCalChan-Modbus_RegCalChan] == TEMP2_CHANNEL_ID)
 {
   ///< 初始化温度传感器:校准量程、零点偏移、灵敏度、零点偏移系数和灵敏度偏移系数
   nModbusCalRegs[Modbus_CalChanIndex] = strDeviceParamSave.temp2_range;
   memcpy((uint8_t *) &ltemp,(uint8_t *) &strDeviceParamSave.temp2_bias1, 4);
   ntemp = (uint16_t) ltemp;
   nModbusCalRegs[Modbus_CalZeroIndex] = ntemp;
   ntemp = (uint16_t) (ltemp >> 16);
   nModbusCalRegs[Modbus_CalZeroIndex+1] = ntemp;
   memcpy((uint8_t *) &ltemp,(uint8_t *) &strDeviceParamSave.temp2_kate1, 4);
   ntemp = (uint16_t) ltemp;
   nModbusCalRegs[Modbus_CalKateIndex] = ntemp;
   ntemp = (uint16_t) (ltemp >> 16);
   nModbusCalRegs[Modbus_CalKateIndex+1] = ntemp;
   memcpy((uint8_t *) &ltemp,(uint8_t *) &strDeviceParamSave.temp2_bias2, 4);
   ntemp = (uint16_t) ltemp;
   nModbusCalRegs[Modbus_CalKZeroIndex] = ntemp;
   ntemp = (uint16_t) (ltemp >> 16);
   nModbusCalRegs[Modbus_CalKZeroIndex+1] = ntemp;
   memcpy((uint8_t *) &ltemp,(uint8_t *) &strDeviceParamSave.temp2_kate2, 4);
   ntemp = (uint16_t) ltemp;
   nModbusCalRegs[Modbus_CalKSensiIndex] = ntemp;
   ntemp = (uint16_t) (ltemp >> 16);
   nModbusCalRegs[Modbus_CalKSensiIndex+1] = ntemp;
 }
 else if(nModbusCalRegs[Modbus_RegCalChan-Modbus_RegCalChan] == TEMP3_CHANNEL_ID)
 {
   ///< 初始化温度传感器:校准量程、零点偏移、灵敏度、零点偏移系数和灵敏度偏移系数
   nModbusCalRegs[Modbus_CalChanIndex] = strDeviceParamSave.temp3_range;
   memcpy((uint8_t *) &ltemp,(uint8_t *) &strDeviceParamSave.temp3_bias1, 4);
   ntemp = (uint16_t) ltemp;
   nModbusCalRegs[Modbus_CalZeroIndex] = ntemp;
   ntemp = (uint16_t) (ltemp >> 16);
   nModbusCalRegs[Modbus_CalZeroIndex+1] = ntemp;
   memcpy((uint8_t *) &ltemp,(uint8_t *) &strDeviceParamSave.temp3_kate1, 4);
   ntemp = (uint16_t) ltemp;
   nModbusCalRegs[Modbus_CalKateIndex] = ntemp;
   ntemp = (uint16_t) (ltemp >> 16);
   nModbusCalRegs[Modbus_CalKateIndex+1] = ntemp;
   memcpy((uint8_t *) &ltemp,(uint8_t *) &strDeviceParamSave.temp3_bias2, 4);
   ntemp = (uint16_t) ltemp;
   nModbusCalRegs[Modbus_CalKZeroIndex] = ntemp;
   ntemp = (uint16_t) (ltemp >> 16);
   nModbusCalRegs[Modbus_CalKZeroIndex+1] = ntemp;
   memcpy((uint8_t *) &ltemp,(uint8_t *) &strDeviceParamSave.temp3_kate2, 4);
   ntemp = (uint16_t) ltemp;
   nModbusCalRegs[Modbus_CalKSensiIndex] = ntemp;
   ntemp = (uint16_t) (ltemp >> 16);
   nModbusCalRegs[Modbus_CalKSensiIndex+1] = ntemp;
 }
 else
 {
   nModbusCalRegs[Modbus_CalChanIndex] = 0;
   nModbusCalRegs[Modbus_CalZeroIndex] = 0;
   nModbusCalRegs[Modbus_CalZeroIndex+1] = 0;
   nModbusCalRegs[Modbus_CalKateIndex] = 0;
   nModbusCalRegs[Modbus_CalKateIndex+1] = 0;
   nModbusCalRegs[Modbus_CalKZeroIndex] = 0;
   nModbusCalRegs[Modbus_CalKZeroIndex+1] = 0;
   nModbusCalRegs[Modbus_CalKSensiIndex] = 0;
   nModbusCalRegs[Modbus_CalKSensiIndex+1] = 0;
 }

优化后程序如下所示:


 

if(nModbusCalRegs[Modbus_RegCalChan-Modbus_RegCalChan] == TEMP1_CHANNEL_ID)
  {
    temp_range = strDeviceParamSave.temp1_range;
    temp_bias1 = strDeviceParamSave.temp1_bias1;
    temp_kate1 = strDeviceParamSave.temp1_kate1;
    temp_bias2 = strDeviceParamSave.temp1_bias2;
    temp_kate2 = strDeviceParamSave.temp1_kate2;
  }
  else if(nModbusCalRegs[Modbus_RegCalChan-Modbus_RegCalChan] == TEMP2_CHANNEL_ID)
  {
    temp_range = strDeviceParamSave.temp2_range;
    temp_bias1 = strDeviceParamSave.temp2_bias1;
    temp_kate1 = strDeviceParamSave.temp2_kate1;
    temp_bias2 = strDeviceParamSave.temp2_bias2;
    temp_kate2 = strDeviceParamSave.temp2_kate2;   
  }
  else if(nModbusCalRegs[Modbus_RegCalChan-Modbus_RegCalChan] == TEMP3_CHANNEL_ID)
  {
    temp_range = strDeviceParamSave.temp3_range;
    temp_bias1 = strDeviceParamSave.temp3_bias1;
    temp_kate1 = strDeviceParamSave.temp3_kate1;
    temp_bias2 = strDeviceParamSave.temp3_bias2;
    temp_kate2 = strDeviceParamSave.temp3_kate2;
  }
  ///< 初始化温度传感器:校准量程、零点偏移、灵敏度、零点偏移系数和灵敏度偏移系数
  nModbusCalRegs[Modbus_CalChanIndex] = temp_range;
  memcpy((uint8_t *) &ltemp,(uint8_t *) &temp_bias1, 4);
  ntemp = (uint16_t) ltemp;
  nModbusCalRegs[Modbus_CalZeroIndex] = ntemp;
  ntemp = (uint16_t) (ltemp >> 16);
  nModbusCalRegs[Modbus_CalZeroIndex+1] = ntemp;
  memcpy((uint8_t *) &ltemp,(uint8_t *) &temp_kate1, 4);
  ntemp = (uint16_t) ltemp;
  nModbusCalRegs[Modbus_CalKateIndex] = ntemp;
  ntemp = (uint16_t) (ltemp >> 16);
  nModbusCalRegs[Modbus_CalKateIndex+1] = ntemp;
  memcpy((uint8_t *) &ltemp,(uint8_t *) &temp_bias2, 4);
  ntemp = (uint16_t) ltemp;
  nModbusCalRegs[Modbus_CalKZeroIndex] = ntemp;
  ntemp = (uint16_t) (ltemp >> 16);
  nModbusCalRegs[Modbus_CalKZeroIndex+1] = ntemp;
  memcpy((uint8_t *) &ltemp,(uint8_t *) &temp_kate2, 4);
  ntemp = (uint16_t) ltemp;
  nModbusCalRegs[Modbus_CalKSensiIndex] = ntemp;
  ntemp = (uint16_t) (ltemp >> 16);
  nModbusCalRegs[Modbus_CalKSensiIndex+1] = ntemp;

哎,泪奔,回头想想,可能是重复代码过多,导致编译过程存在问题,硬件开发工程师的程序bug往往出其不意,切忌先入为主,始终要保持质疑的态度呀~


相关文章
|
5月前
|
存储 算法 编译器
如何优化单片机程序里面的C代码方法
如何优化单片机程序里面的C代码方法
43 0
|
数据处理 C语言
侃侃单片机的裸奔程序的框架
侃侃单片机的裸奔程序的框架
97 0
|
2月前
51单片机用汇编语言实现独立按键检测,每个按键有不同功能,包含按键消抖程序
51单片机用汇编语言实现独立按键检测,每个按键有不同功能,包含按键消抖程序
|
2月前
|
C语言
【51单片机】LCD1602显示字符串,时间、时间+按键校准、秒表计时的功能代码。
【51单片机】LCD1602显示字符串,时间、时间+按键校准、秒表计时的功能代码。
|
2月前
|
C语言
51单片机汇编语言流水灯代码
51单片机汇编语言流水灯代码
|
2月前
|
人工智能 开发者 芯片
【51单片机】单片机开发者的福音: 让AI看电路图帮你编写程序(使用ChatGPT 中训练好的单片机工程师模型)
使用AI大语言模型编写 单片机程序. 使用的是 OpenAI公司发布的 ChatGPT .在ChatGPT上有别人训练好的 单片机工程师 with Keil uVision 5 - C Code Explainer模型, 可以上传电路图改模型可以通过这个用户所给的电路图进行编程.
【51单片机】单片机开发者的福音: 让AI看电路图帮你编写程序(使用ChatGPT 中训练好的单片机工程师模型)
|
5月前
|
传感器
51单片机循迹小车原理介绍和代码示例
51单片机循迹小车原理介绍和代码示例
51单片机循迹小车原理介绍和代码示例
|
4月前
技术心得记录:单片机开发过程中使用结构体简化程序
技术心得记录:单片机开发过程中使用结构体简化程序
20 0
|
5月前
|
传感器
51单片机矩阵键盘超详解!(内含LCD1602代码)
51单片机矩阵键盘超详解!(内含LCD1602代码)
60 0
|
5月前
基于51单片机的简单交通灯程序
基于51单片机的简单交通灯程序
72 2