OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6868|回复: 6

小白求助,好像是程序bug,问题已经锁定,但是现象却很超级奇怪找不出原因。

[复制链接]

2

主题

8

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2021-5-3
在线时间
3 小时
发表于 2021-5-20 11:48:53 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 17862703213 于 2021-5-20 19:02 编辑

小白求助,好像是程序bug,问题已经锁定,但是现象却很超级奇怪,找不出原因。问题有更新,再回复里面,前面不用看了


这是一个can通信测试的程序,用can盒接收F4开发板发的数据。
数据结构是一次8帧,首字节由40到47.如图1.
我大概描述一下目前遇到的问题,有两个变量,一个本来是用作错误ID(ErrorID),另一个用于计录帧数(NumberForCheck),这两个变量出现的问题一样,只讨论ERRORID这个变量。两变量均初始化为0.
2.png

二维数组是用来存放即将发送的数据,key是我用来照这个bug定义的变量。ERRORID使用的位置就上图所示,加另一个函数里的一行CAN1_DateForCheck[7][5]=ErrorII;(其他引用的赋值的都注释掉了),我把代码赋值出来
情况1
while(ErrorII==0)
{
                delay_ms(3000);                                 //方便看数据设的延时
                Get_CAN1_DateForCheck();                                                //将检查回告报文8帧数据放于数组中
                Can1_SendforCheck(CAN1_DateForCheck);  //发送报文,该函数有返回值1失败(失败处理方式待定)!!!!!!!!
                while(ErrorII==0xE7);

}
另一个函数里
CAN1_DateForCheck[7][5]=ErrorII;

结果:这样会收到CAN1_DateForCheck[7][5]数值为0xE7,然后CAN不再发送(进入第二个while)。我分析ERRORII开始0,后来在3000ms内变为了E7

情况2
while(ErrorII==0)
{
                delay_ms(3000);                                 //方便看数据设的延时
                Get_CAN1_DateForCheck();                                                //将检查回告报文8帧数据放于数组中
                Can1_SendforCheck(CAN1_DateForCheck);  //发送报文,该函数有返回值1失败(失败处理方式待定)!!!!!!!!
                //while(ErrorII==0xE7);

}
另一个函数里
CAN1_DateForCheck[7][5]=ErrorII;

结果:这样第一次会收到CAN1_DateForCheck[7][5]数值为0xE7,以后均为0(0是对的)


然后我又尝试用KEY这个变量替换ERRORID,找ERRORID在什么位置被赋值的,
情况3
while(key==0)
{
                delay_ms(3000);                                 //方便看数据设的延时
                Get_CAN1_DateForCheck();                                                //将检查回告报文8帧数据放于数组中
                Can1_SendforCheck(CAN1_DateForCheck);  //发送报文,该函数有返回值1失败(失败处理方式待定)!!!!!!!!
                while(key==0xE7);

}

另一个函数里
CAN1_DateForCheck[7][5]=ErrorII;


我发现,无论安装什么顺序替换,当最后一处ERRORID被替换后KEY就变的跟ERRORID的现象一样。
比如我先替换CAN1_DateForCheck[7][5]=ErrorII;把ErrorII替换为key,最后替换while里面两处,或者反过来,只要把所有ErrorII替换成key,key就会被赋值E7


更重要的是,这些所有错误现象只在下载完成程序立刻运行的第一次出现,复位,断电,监控都会导致现象变为正常即ERRORID=0(0是对的数值,因为没赋值,但是变量我在main开始手动初始化为0了)

1.png
3.png
2.png
1.png
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

8

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2021-5-3
在线时间
3 小时
 楼主| 发表于 2021-5-20 12:01:17 | 显示全部楼层
帮忙出出主意也可以。或者帮忙找找原因,程序我可以发出来
回复

使用道具 举报

7

主题

480

帖子

0

精华

高级会员

Rank: 4

积分
773
金钱
773
注册时间
2021-4-15
在线时间
304 小时
发表于 2021-5-20 12:26:58 | 显示全部楼层
帮顶  
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4105
金钱
4105
注册时间
2018-8-14
在线时间
696 小时
发表于 2021-5-20 12:27:38 | 显示全部楼层
类似这样的应用, 都需要加上 volatile,假设key 是int

while( (volatile int)key==0)
{
                delay_ms(3000);                                 //方便看数据设的延时
                Get_CAN1_DateForCheck();                                                //将检查回告报文8帧数据放于数组中
                Can1_SendforCheck(CAN1_DateForCheck);  //发送报文,该函数有返回值1失败(失败处理方式待定)!!!!!!!!
                while((volatile int)key==0xE7);

}

回复

使用道具 举报

2

主题

8

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2021-5-3
在线时间
3 小时
 楼主| 发表于 2021-5-20 16:33:30 | 显示全部楼层
edmund1234 发表于 2021-5-20 12:27
类似这样的应用, 都需要加上 volatile,假设key 是int

while( (volatile int)key==0)

不又学到了,我去搜一下这个修饰的作用,谢谢

关于这个bug有什么想法吗,大佬
回复

使用道具 举报

2

主题

8

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2021-5-3
在线时间
3 小时
 楼主| 发表于 2021-5-20 18:39:06 | 显示全部楼层
本帖最后由 17862703213 于 2021-5-20 18:40 编辑

问题又进一步缩小了,貌似是我写的有问题
#include "sys.h"
#include "delay.h"
#include "can.h"

u8 CAN1_DateForCheck[8][8]={0};                        //检查回告报文数据打包数组

u8 NumberForCheck=0;                                //**********这里!!!!!
u8 CAN1_DateForControl[8]={0};   //CAN1控制回告报文
u8 ErrorII=0;

int main(void)
{
    u8 NumberForCheck=0;                                //**********这里!!!!
    HAL_Init();                     //初始化HAL库   
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    delay_init(180);                //初始化延时函数
                CAN1_Mode_Init(CAN_SJW_1TQ,CAN_BS2_6TQ,CAN_BS1_8TQ,6,CAN_MODE_NORMAL); //CAN初始化,波特率500Kbps (先测试回环模式)  普通模式为  CAN_MODE_NORMAL
               
                CAN1_DateForControl[1]=NumberForCheck;//这里!!!!!
    while(1)
    {
                                if(ErrorII==0)
                                {
                                                delay_us(3000);
                                                if(ErrorII==0xE7)
                                                {
                                                        CAN1_DateForCheck[7][5]=ErrorII;
                                                        CAN1_Send_Msg(CAN1_DateForCheck[7],8);
                                                }
                                }                                                        
                                while(1);                        
                }                     
}

我最后把程序删的只剩下上面那些了,变量(NumberForCheck)定义在main外与main里面有什么区别,应该定义在什么地方?
当我把NumberForCheck在main里面重新初始化一下就好了,但是如果不在main里面初始化,只在main外面初始化,再执行CAN1_DateForControl[1]=NumberForCheck;时,大概是在进入wihle循环后2000us左右,ErrorII 的值就会跟着变,我测试过。
请大神帮忙解释一下这是什么原理。
回复

使用道具 举报

2

主题

8

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2021-5-3
在线时间
3 小时
 楼主| 发表于 2021-5-20 19:01:28 | 显示全部楼层
ErrorII和NumberForCheck只要定义在main外就不行,,与main里面赋初值没有关系。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-27 20:37

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表