打印
[技术问答]

N76E003中某个变量好象被强行锁定了,是什么原因?付费求解

[复制链接]
1654|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kt98741|  楼主 | 2019-4-8 09:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
        u8 k;
        u8 k2;

        k = 0;
        k2 = 0;
                  
        Send_Data_To_UART0(k);
        Send_Data_To_UART0(k2);

        k++;
        k2++;
        Send_Data_To_UART0(k);  
        Send_Data_To_UART0(k2);  


        //这里循环中,k的值一直为5,无法改变,导致了死循环
        for (k=0;k<10;k++)
        {  
                Send_Data_To_UART0(k);
                Timer1_Delay10ms(10);  //让输出慢一点
        }

变量k在循环里不知道为什么,被锁定为5,正常程序应该输出0123456789,但实际上程序死循环了不停地输出5。

解决方法其实也很多,把k定义在idata里,或者随便删掉其它一些和这段程序无关的代码,输出就正常了,其它代码不多,仔细检查也没发现数组越界之类的问题。

希望不是简单地解决问题,而是搞清楚为什么会出现这个问题,是系统的BUG吗?

打开项目直接编译就可以了,程序会在串口以9600bps速度不停输出5。

哪位高手能帮忙看一下,问题解决后奉上100元辛苦费,本人菜鸟一枚,对这问题的难度没什么概念,如果问题很难需要加钱请私信或QQ聊

test.rar

389.11 KB

使用特权

评论回复
沙发
jasontu| | 2019-4-8 10:18 | 只看该作者
編譯器上面的reentrant問題
void FirstRunSetDefaultPara() 後面加上reentrant即可。

使用特权

评论回复
评论
kt98741 2019-4-9 20:36 回复TA
问题已解决,请发支付宝帐号给我吧,私信就行 
板凳
lomo1316| | 2019-4-8 11:05 | 只看该作者
在Timer0_ISR中断函数中调用了CheckACOnOffTimes函数,这个函数又调用了FirstRunSetDefaultPara函数,如果在运行到FirstRunSetDefaultPara函数时,这时候产生了Timer0_ISR中断,会造成FirstRunSetDefaultPara函数的重入问题,上面仁兄给出了解决思路,重点考虑函数的重入问题。

使用特权

评论回复
地板
kt98741|  楼主 | 2019-4-8 13:25 | 只看该作者
测试:正确的输出 把变量放到idata里
void FirstRunSetDefaultPara()
{

   idata u8 i;
        Send_Data_To_UART0(0xcc);
        i=0;          
        Send_Data_To_UART0(i);
                i++;
        Send_Data_To_UART0(i);
                i++;
        Send_Data_To_UART0(i);
                                         
        Send_Data_To_UART0(0xdd);
        for (i=0;i<10;i++)
        {                                                                  
        Send_Data_To_UART0(i);                  
                //Timer0_Delay1ms(10); //让输出慢一点                  
        }
}
输出:cc 0 1 2 dd 0 1 2 3 4 5 6 7 8 9
结果正确


测试:原来的问题
void FirstRunSetDefaultPara()
{

   u8 i;
        Send_Data_To_UART0(0xcc);
        i=0;          
        Send_Data_To_UART0(i);
                i++;
        Send_Data_To_UART0(i);
                i++;
        Send_Data_To_UART0(i);
                                         
        Send_Data_To_UART0(0xdd);
        for (i=0;i<10;i++)
        {                                                                  
        Send_Data_To_UART0(i);                  
                //Timer0_Delay1ms(10); //让输出慢一点                  
        }
}
输出:cc 0 5 5 dd 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 ......死循环
前面的累加不正确,后面的循环也不正确


测试:添加reentrant关键字后
void FirstRunSetDefaultPara() reentrant
{

   u8 i;
        Send_Data_To_UART0(0xcc);
        i=0;          
        Send_Data_To_UART0(i);
                i++;
        Send_Data_To_UART0(i);
                i++;
        Send_Data_To_UART0(i);
                                         
        Send_Data_To_UART0(0xdd);
        for (i=0;i<10;i++)
        {                                                                  
        Send_Data_To_UART0(i);                  
                //Timer0_Delay1ms(10); //让输出慢一点                  
        }
}
输出:cc 0 0 0 dd 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  ......死循环
前面的累加不正确,后面的循环也不正确


添加reentrant关键字后,输出只是从5的死循环变成0的死循环,前面的赋值操作结果也不正确。

重要的是这个问题是否确认是由于函数重入导致的?

1、为什么如果删掉前面的SendDataToAC();也能有正确输出,这个函数和出错代码完全无关联,是怎么影响到的?

2、在两个运行FirstRunSetDefaultPara()的地方,一个是系统第一次上电时运行,一个是在运行中由人手去触发运行,这两个条件基本不太可能会同时运行到函数。

项目重新整理过,添加了reentrant,输出死循环0

是否确认是由于函数重入导致的?

test2.rar

442.16 KB

使用特权

评论回复
5
lomo1316| | 2019-4-8 17:44 | 只看该作者
实际验证可以的,就是重入的问题,你的项目都没有选择N76E003,搞清楚你到底用的那款单片机,你再试试吧,我验证OK的

使用特权

评论回复
6
mintspring| | 2019-4-8 19:34 | 只看该作者
有点意思,没想到一个变量这么多学问。

使用特权

评论回复
7
mintspring| | 2019-4-8 19:37 | 只看该作者
多谢楼主分享。

使用特权

评论回复
8
jekey| | 2019-4-8 20:24 | 只看该作者
修改程序结构吧,避免中断时做长时间的操作。
(这个程序在中断里打印数据就是一个耗时的操作)

使用特权

评论回复
9
小S咯| | 2019-4-9 11:24 | 只看该作者
应该是重入问题,你在中断最开始的地方加两句clr_TR0;clr_ET0;,然后中断最后面的地方加set_TR0;set_ET0;

使用特权

评论回复
10
菜鸟同学| | 2019-4-9 16:31 | 只看该作者
配置你的编译环境,要么开了 莫您堆栈,定义函数的时候就要写 关键字 reetrant 不然,你的内存可能出现定位错误或者被强行覆盖。
要么就不是不开模拟堆栈。我目前也用这个芯片,不会出现问题的。

使用特权

评论回复
11
菜鸟同学| | 2019-4-9 16:32 | 只看该作者
菜鸟同学 发表于 2019-4-9 16:31
配置你的编译环境,要么开了 莫您堆栈,定义函数的时候就要写 关键字 reetrant 不然,你的内存可能出现定位 ...

模拟堆栈 是要在启动文件中配置的。只写关键字 不行的。

使用特权

评论回复
12
kt98741|  楼主 | 2019-4-9 20:35 | 只看该作者
本帖最后由 kt98741 于 2019-4-9 21:05 编辑

按1楼和2楼的思路重新配置过代码,使逻辑上不会出现重入的可能,问题就解决了,看来确实是重入的问题了。
这个问题可以结贴了,谢谢各位兄弟的解答。
请jasontu和两位兄@发个支付宝帐号给我吧,或者手机号也行,我直接充钱进去,私信线我就好,一人一半,钱实在不多,意思一下,两位勿怪。

使用特权

评论回复
13
kt98741|  楼主 | 2019-4-9 21:06 | 只看该作者
lomo1316 发表于 2019-4-8 11:05
在Timer0_ISR中断函数中调用了CheckACOnOffTimes函数,这个函数又调用了FirstRunSetDefaultPara函数,如果 ...

支付宝帐号私信给我,谢谢

使用特权

评论回复
14
21mengnan| | 2019-4-9 21:21 | 只看该作者
太深奥了,没看懂。。。

使用特权

评论回复
15
小明的同学| | 2019-4-9 23:39 | 只看该作者
借楼学经验。

使用特权

评论回复
16
598330983| | 2019-4-9 23:43 | 只看该作者
有点不太理解人家的回答,看来要深入学习啊

使用特权

评论回复
17
jasontu| | 2019-4-10 08:32 | 只看该作者
kt98741 发表于 2019-4-9 21:06
支付宝帐号私信给我,谢谢

小事…不用客氣

使用特权

评论回复
18
lomo1316| | 2019-4-10 08:52 | 只看该作者
kt98741 发表于 2019-4-9 21:06
支付宝帐号私信给我,谢谢

不需要了,共同进步

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

25

主题

51

帖子

1

粉丝