[STC单片机] 求助一个百思不得姐的怪异变量名问题

[复制链接]
3669|44
 楼主| linxi6414 发表于 2020-4-1 21:06 | 显示全部楼层
打开程序里的可以看到,我写了两处数据监控,第一处的为T1,第二处的为T2,正常的时候,T1和T2是相同的,异常的时候,T2的地方变成了0,在发上来之前,我又特意测试了一下,故障现象还是一样的。
john_lee 发表于 2020-4-1 21:22 | 显示全部楼层
抱歉,已经多年不用keil了,没有环境,而且你只给部分程序没有意义,map文件是链接阶段产生的,需要全部的代码和IDE配置。
所以,还是只有你提供map文件才行。

生成map文件很简单啊,option那个页面把Linker Listing和下面的选项都勾上,重新build一次就OK了啊。
 楼主| linxi6414 发表于 2020-4-1 21:30 | 显示全部楼层
本帖最后由 linxi6414 于 2020-4-2 13:36 编辑
john_lee 发表于 2020-4-1 21:22
抱歉,已经多年不用keil了,没有环境,而且你只给部分程序没有意义,map文件是链接阶段产生的,需要全部的 ...

上面就有,刚刚开始不知道是哪个,实际就是那个.M51的文件,我以为是.map的文件,一直找不到,后来在网上搜才知道的,不好意思,水平太差,现在传上面板的MAP文件。
john_lee 发表于 2020-4-1 21:39 | 显示全部楼层
怎么没有变量SYS_Over_Current_Count?你的map文件是这个工程的吗?主板还是面板?
 楼主| linxi6414 发表于 2020-4-1 22:04 | 显示全部楼层
john_lee 发表于 2020-4-1 21:39
怎么没有变量SYS_Over_Current_Count?你的map文件是这个工程的吗?主板还是面板? ...

主板,异常的那个文件里才有
john_lee 发表于 2020-4-1 22:33 | 显示全部楼层
所以,你要给我主板的map文件!
 楼主| linxi6414 发表于 2020-4-1 22:58 | 显示全部楼层
john_lee 发表于 2020-4-1 22:33
所以,你要给我主板的map文件!

485数据异常的那个压缩包里有。
john_lee 发表于 2020-4-2 08:26 | 显示全部楼层
本帖最后由 john_lee 于 2020-4-2 22:59 编辑

你的变量SYS_Over_Current_Count或SYS_Overload_Count是定义在xdata中的。相关内存布局如下(文件经过整理,这里要吐槽一下keil,这些地址居然不排序):
正常的(变量名是SYS_Overload_Count)的内存布局:
  1.   X:0000H         PUBLIC        SYS_Max_Temp
  2.   X:0001H         PUBLIC        SYS_Maj_Run_Coe
  3.   X:0002H         PUBLIC        SYS_Overload_Count
  4.   X:0003H         PUBLIC        S4_RX_JS
  5.   X:0004H         PUBLIC        SYS_SET_TRA
  6.   X:0005H         PUBLIC        SYS_MEM_Major
  7.   X:0006H         PUBLIC        SYS_SET_POR
  8.   X:0007H         PUBLIC        SYS_Working_Mode
  9.   X:0008H         PUBLIC        XT_RX_DATA
  10.   X:0016H         PUBLIC        XT_TX_DATA
  11.   X:0024H         PUBLIC        CC1101_CH
  12.   ......

异常的(变量名是SYS_Over_Current_Count)的内存布局:
  1.   X:0000H         PUBLIC        SYS_Max_Temp
  2.   X:0001H         PUBLIC        SYS_Maj_Run_Coe
  3.   X:0002H         PUBLIC        S4_RX_JS
  4.   X:0003H         PUBLIC        SYS_SET_TRA
  5.   X:0004H         PUBLIC        SYS_MEM_Major
  6.   X:0005H         PUBLIC        SYS_SET_POR
  7.   X:0006H         PUBLIC        SYS_Working_Mode
  8.   X:0007H         PUBLIC        XT_RX_DATA
  9.   X:0015H         PUBLIC        SYS_Over_Current_Count
  10.   X:0016H         PUBLIC        XT_TX_DATA
  11.   X:0024H         PUBLIC        CC1101_CH
  12.   ......

可以看出,“正常”的内存布局的SYS_Overload_Count变量的地址是X:0002H,前一个变量是SYS_Maj_Run_Coe,应该是一个字节的变量。
一般来说,越界几乎都出现在访问数组元素的情况下,那么这个SYS_Maj_Run_Coe自然不会有这种问题。

而异常的内存布局的SYS_Over_Current_Count变量,地址被安排到了X:0015H,前一个变量是XT_RX_DATA,地址为X:0007H,从变量名来看,好像是一个接收数据的缓冲区,长度为15H-7H=14个字节,几乎可以肯定是一个数组,如果接收程序没有限制长度的话,那么当接收到第15个字节时,就会越界覆盖变量SYS_Over_Current_Count。

如果我分析不错的话,楼主遇到的问题就是这样。

然后再补充一下,即使楼主改了变量名,程序也是有隐患的,在“正常”的内存布局中XT_RX_DATA数组的后面是XT_TX_DATA,当越界发生时,数据会覆盖XT_TX_DATA,只是可能XT_TX_DATA很多时候并不包含有效数据,覆盖了也无所谓,发生异常的概率比较小而已。

评论

高手,还有这个方法,帮板凳学习。  发表于 2020-4-2 14:01
以前没遇到这样的问题,也第一次看到您这样的分析办法。受教了。(๑•̀ㅂ•́)و✧  发表于 2020-4-2 09:13
aerwa 发表于 2020-4-2 08:31 来自手机 | 显示全部楼层
这个很赞,我是第一次看到你这种分析软件故障的方式。以前出现类似的问题都是逐步运行看变量变化。
ayb_ice 发表于 2020-4-2 08:52 | 显示全部楼层
linxi6414 发表于 2020-4-1 19:54
主板里没有用指针,只有面板程序里有用指针,与主板没有关系,用逻辑分析仪分析过面板发往主板的数据,也 ...

也可能是发送方的数据太多,导致接收缓冲越界

索引号也可能导致越界
 楼主| linxi6414 发表于 2020-4-2 12:29 | 显示全部楼层
本帖最后由 john_lee 于 2020-4-2 13:07 编辑
john_lee 发表于 2020-4-2 08:26
你的变量SYS_Over_Current_Count或SYS_Overload_Count是定义在xdata中的。相关内存布局如下(文件经过整理 ...

请问这个问题如何纠正?
定义的接收缓冲区:unsigned char xdata XT_RX_DATA[14];
接收中断:

  1. void Uart4() interrupt 18 using 1 //串口4中断
  2. {
  3.     IE2=0x00;
  4.     if(S4CON&0x01)
  5.     {
  6.         S4CON=0x10; //清除S4RI位        
  7.         if(RxNum<14)
  8.         {
  9.             XT_RX_DATA[RxNum]=S4BUF;
  10.             RxNum++;            
  11.         }
  12.         TR_ERR_MAX_TIME=255;
  13.         RX_DATA_TIME=2;
  14.         SYS_TR_MAX_TIM=10;        
  15.         RX_EN_B=1;
  16.     }
  17.     if(S4CON&0x02)
  18.     {
  19.         S4CON=0x10;//清除S4TI位
  20.     }
  21.     IE2=0x10;
  22. }





john_lee 发表于 2020-4-2 13:11 | 显示全部楼层
linxi6414 发表于 2020-4-2 12:29
请问这个问题如何纠正?
定义的接收缓冲区:unsigned char xdata XT_RX_DATA[14];
接收中断:

你这个代码就应该没有问题了,第8行已经做了判断,不会越界了,多说一句,RxNum要定义为无符号数。
 楼主| linxi6414 发表于 2020-4-2 13:25 | 显示全部楼层
本帖最后由 linxi6414 于 2020-4-2 13:28 编辑

问题已经找到了,问题是出在清除接收和发送缓存上,异常的:
void CLR_RX_BUF(void)
{
    unsigned char i;
        for (i=0; i<20; i++)
        {
                XT_RX_DATA=0;                        
        }
        RxNum=0;
        RX_EN_B=0;
}

void CLR_TX_BUF(void)
{
    unsigned char i;
        for (i=0; i<20; i++)
        {
                XT_TX_DATA
=0;                        
        }
}

正确的应该为:
void CLR_RX_BUF(void)
{
    unsigned char i;
        for (i=0; i<14; i++)
        {
                XT_RX_DATA
=0;                        
        }
        RxNum=0;
        RX_EN_B=0;
}

void CLR_TX_BUF(void)
{
    unsigned char i;
        for (i=0; i<14; i++)
        {
                XT_TX_DATA
=0;                        
        }
}
这个要怪自己,不能怪别人。在这里要非常感谢john_lee坛友,帮忙分析问题,非常感谢!!!!
 楼主| linxi6414 发表于 2020-4-2 13:29 | 显示全部楼层
怎么显示的不正常,在XT_TX_DATA的后面应该有中括号,中括号里有i,怎么显示不出来。
ayb_ice 发表于 2020-4-2 13:41 | 显示全部楼层
linxi6414 发表于 2020-4-2 12:29
请问这个问题如何纠正?
定义的接收缓冲区:unsigned char xdata XT_RX_DATA[14];
接收中断:

这段代码其实是有隐患的,可以优化如下,但问题不一定在此处

首先没有禁止中断,因为这个中断不可能自己中断自己,
这个中断很简单,不需要使用using 1
要先取数据,再清除接收位,
因为一旦清除接收标志,此时如果有其它高优先级中断正好来了,又耗时较长时间,后面的接收数据可以覆盖掉S4BUF内容,导致数据出错,



void Uart4() interrupt 18 using 1 //串口4中断
{
        u8 ucTmp;
    //IE2=0x00;
    if(S4CON&0x01)
    {
                ucTmp = S4BUF;
        S4CON=0x10; //清除S4RI位        
        if(RxNum<14)
        {
            XT_RX_DATA[RxNum]=ucTmp;
            RxNum++;            
        }
        TR_ERR_MAX_TIME=255;
        RX_DATA_TIME=2;
        SYS_TR_MAX_TIM=10;        
        RX_EN_B=1;
    }
    if(S4CON&0x02)
    {
        S4CON=0x10;//清除S4TI位
    }
    //IE2=0x10;
}
 楼主| linxi6414 发表于 2020-4-2 13:57 | 显示全部楼层
ayb_ice 发表于 2020-4-2 13:41
这段代码其实是有隐患的,可以优化如下,但问题不一定在此处

首先没有禁止中断,因为这个中断不可能自己 ...

谢谢指正,真正的问题已经找出来了,是清除接收和发送缓存,清除多了,本来只有14个接收和发送缓存的,却各清除了20个缓存,结果问题就来了。
叶春勇 发表于 2020-4-2 18:37 | 显示全部楼层
  1. void Uart() __interrupt (4)

  2. {

  3.     if (RI)

  4.     {

  5.         RI = 0;                 //??RI?

  6.                         if(mb_t.mb_state==MB_READY) {mb_t.rx_len=0;mb_t.rx[mb_t.rx_len]=SBUF;mb_t.rx_len+=1;mb_t.mb_state=MB_RECV;}

  7.                         else if(mb_t.mb_state==MB_RECV) {mb_t.rx[mb_t.rx_len]=SBUF;mb_t.rx_len+=1;}

  8.                         mb_frame_timeout=0;

  9.     }

  10.     if (TI)

  11.     {

  12.         TI = 0;                 //??TI?

  13.         busy = 0;               //????

  14.     }

  15. }
  16. 我的modbus串口中断,状态优先。
maximQ820270087 发表于 2020-4-2 20:56 | 显示全部楼层
john_lee 发表于 2020-4-2 23:11 | 显示全部楼层
linxi6414 发表于 2020-4-2 13:29
怎么显示的不正常,在XT_TX_DATA的后面应该有中括号,中括号里有i,怎么显示不出来。 ...

你文本里有[ i ],这是Discuz代码(自己搜),表示“斜体”。
你应该用代码[ code ]和[ /code ]把你的程序包起来。效果是这样的:
  1. void CLR_RX_BUF(void)
  2. {
  3.     unsigned char i;
  4.     for (i=0; i<20; i++)
  5.     {
  6.         XT_RX_DATA[i]=0;
  7.     }
  8.     RxNum=0;
  9.     RX_EN_B=0;
  10. }
叶春勇 发表于 2020-4-3 08:25 | 显示全部楼层
这个i<20 用i<RX_BUF_MAX_LENGTH,用宏定义吧,一次解决了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部