打印
[STC单片机]

求助一个百思不得姐的怪异变量名问题

[复制链接]
楼主: linxi6414
手机看帖
扫描二维码
随时随地手机跟帖
21
linxi6414|  楼主 | 2020-4-1 21:06 | 只看该作者 回帖奖励 |倒序浏览
打开程序里的可以看到,我写了两处数据监控,第一处的为T1,第二处的为T2,正常的时候,T1和T2是相同的,异常的时候,T2的地方变成了0,在发上来之前,我又特意测试了一下,故障现象还是一样的。

使用特权

评论回复
22
john_lee| | 2020-4-1 21:22 | 只看该作者
抱歉,已经多年不用keil了,没有环境,而且你只给部分程序没有意义,map文件是链接阶段产生的,需要全部的代码和IDE配置。
所以,还是只有你提供map文件才行。

生成map文件很简单啊,option那个页面把Linker Listing和下面的选项都勾上,重新build一次就OK了啊。

使用特权

评论回复
23
linxi6414|  楼主 | 2020-4-1 21:30 | 只看该作者
本帖最后由 linxi6414 于 2020-4-2 13:36 编辑
john_lee 发表于 2020-4-1 21:22
抱歉,已经多年不用keil了,没有环境,而且你只给部分程序没有意义,map文件是链接阶段产生的,需要全部的 ...

上面就有,刚刚开始不知道是哪个,实际就是那个.M51的文件,我以为是.map的文件,一直找不到,后来在网上搜才知道的,不好意思,水平太差,现在传上面板的MAP文件。

使用特权

评论回复
24
john_lee| | 2020-4-1 21:39 | 只看该作者
怎么没有变量SYS_Over_Current_Count?你的map文件是这个工程的吗?主板还是面板?

使用特权

评论回复
25
linxi6414|  楼主 | 2020-4-1 22:04 | 只看该作者
john_lee 发表于 2020-4-1 21:39
怎么没有变量SYS_Over_Current_Count?你的map文件是这个工程的吗?主板还是面板? ...

主板,异常的那个文件里才有

使用特权

评论回复
26
john_lee| | 2020-4-1 22:33 | 只看该作者
所以,你要给我主板的map文件!

使用特权

评论回复
27
linxi6414|  楼主 | 2020-4-1 22:58 | 只看该作者
john_lee 发表于 2020-4-1 22:33
所以,你要给我主板的map文件!

485数据异常的那个压缩包里有。

使用特权

评论回复
28
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)的内存布局:
  X:0000H         PUBLIC        SYS_Max_Temp
  X:0001H         PUBLIC        SYS_Maj_Run_Coe
  X:0002H         PUBLIC        SYS_Overload_Count
  X:0003H         PUBLIC        S4_RX_JS
  X:0004H         PUBLIC        SYS_SET_TRA
  X:0005H         PUBLIC        SYS_MEM_Major
  X:0006H         PUBLIC        SYS_SET_POR
  X:0007H         PUBLIC        SYS_Working_Mode
  X:0008H         PUBLIC        XT_RX_DATA
  X:0016H         PUBLIC        XT_TX_DATA
  X:0024H         PUBLIC        CC1101_CH
  ......

异常的(变量名是SYS_Over_Current_Count)的内存布局:
  X:0000H         PUBLIC        SYS_Max_Temp
  X:0001H         PUBLIC        SYS_Maj_Run_Coe
  X:0002H         PUBLIC        S4_RX_JS
  X:0003H         PUBLIC        SYS_SET_TRA
  X:0004H         PUBLIC        SYS_MEM_Major
  X:0005H         PUBLIC        SYS_SET_POR
  X:0006H         PUBLIC        SYS_Working_Mode
  X:0007H         PUBLIC        XT_RX_DATA
  X:0015H         PUBLIC        SYS_Over_Current_Count
  X:0016H         PUBLIC        XT_TX_DATA
  X:0024H         PUBLIC        CC1101_CH
  ......

可以看出,“正常”的内存布局的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 回复TA
高手,还有这个方法,帮板凳学习。 
光轮TreeOS 2020-4-2 09:13 回复TA
以前没遇到这样的问题,也第一次看到您这样的分析办法。受教了。(๑•̀ㅂ•́)و✧ 
29
aerwa| | 2020-4-2 08:31 | 只看该作者
这个很赞,我是第一次看到你这种分析软件故障的方式。以前出现类似的问题都是逐步运行看变量变化。

使用特权

评论回复
30
ayb_ice| | 2020-4-2 08:52 | 只看该作者
linxi6414 发表于 2020-4-1 19:54
主板里没有用指针,只有面板程序里有用指针,与主板没有关系,用逻辑分析仪分析过面板发往主板的数据,也 ...

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

索引号也可能导致越界

使用特权

评论回复
31
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];
接收中断:

void Uart4() interrupt 18 using 1 //串口4中断
{
    IE2=0x00;
    if(S4CON&0x01)
    {
        S4CON=0x10; //清除S4RI位        
        if(RxNum<14)
        {
            XT_RX_DATA[RxNum]=S4BUF;
            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;
}





使用特权

评论回复
32
john_lee| | 2020-4-2 13:11 | 只看该作者
linxi6414 发表于 2020-4-2 12:29
请问这个问题如何纠正?
定义的接收缓冲区:unsigned char xdata XT_RX_DATA[14];
接收中断:

你这个代码就应该没有问题了,第8行已经做了判断,不会越界了,多说一句,RxNum要定义为无符号数。

使用特权

评论回复
33
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坛友,帮忙分析问题,非常感谢!!!!

使用特权

评论回复
34
linxi6414|  楼主 | 2020-4-2 13:29 | 只看该作者
怎么显示的不正常,在XT_TX_DATA的后面应该有中括号,中括号里有i,怎么显示不出来。

使用特权

评论回复
35
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;
}

使用特权

评论回复
36
linxi6414|  楼主 | 2020-4-2 13:57 | 只看该作者
ayb_ice 发表于 2020-4-2 13:41
这段代码其实是有隐患的,可以优化如下,但问题不一定在此处

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

谢谢指正,真正的问题已经找出来了,是清除接收和发送缓存,清除多了,本来只有14个接收和发送缓存的,却各清除了20个缓存,结果问题就来了。

使用特权

评论回复
37
叶春勇| | 2020-4-2 18:37 | 只看该作者
void Uart() __interrupt (4)

{

    if (RI)

    {

        RI = 0;                 //??RI?

                        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;}

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

                        mb_frame_timeout=0;

    }

    if (TI)

    {

        TI = 0;                 //??TI?

        busy = 0;               //????

    }

}
我的modbus串口中断,状态优先。

使用特权

评论回复
38
maximQ820270087| | 2020-4-2 20:56 | 只看该作者

使用特权

评论回复
39
john_lee| | 2020-4-2 23:11 | 只看该作者
linxi6414 发表于 2020-4-2 13:29
怎么显示的不正常,在XT_TX_DATA的后面应该有中括号,中括号里有i,怎么显示不出来。 ...

你文本里有[ i ],这是Discuz代码(自己搜),表示“斜体”。
你应该用代码[ code ]和[ /code ]把你的程序包起来。效果是这样的:
void CLR_RX_BUF(void)
{
    unsigned char i;
    for (i=0; i<20; i++)
    {
        XT_RX_DATA[i]=0;
    }
    RxNum=0;
    RX_EN_B=0;
}

使用特权

评论回复
40
叶春勇| | 2020-4-3 08:25 | 只看该作者
这个i<20 用i<RX_BUF_MAX_LENGTH,用宏定义吧,一次解决了。

使用特权

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

本版积分规则