打印
[STC单片机]

盼高手答疑,keil内存模式选择问题,提前祝大家新年快乐!!!

[复制链接]
1249|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
熊猫烧香|  楼主 | 2016-12-30 21:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 熊猫烧香 于 2017-1-2 12:33 编辑

主程序架构大概是while(1)循环判断定时器100ms标志是否置位,如果置位LCD屏显示。问题是:keil的target中的memory如果选择small模式,主程序正常,而选择large模式,主程序卡死,指示灯不闪烁
void main(void)
{
    while(1)
    {  
      if(nTimer100MSflag ==1)
       {
           LedRun = ~LedRun;
           nTimer100MSflag =0;
           lcd_show();
        }
    }
}
后排查发现lcd_show() 调用的一个延时函数有问题,延时函数如下:
void Delay_1ms(u16 x)
{  
    u16 i ,j;
    for(j=0;j<x;j++)
    {
        for(i=0;i<100;i++);
    }
     
}
延时反汇编如下:
       37: void Delay_1ms(u16 x)  
    38: {   
    39:         u16 i ,j;
    40:         for(j=0;j<x;j++)
C:0x3152    E4       CLR      A
C:0x3153    FD       MOV      R5,A
C:0x3154    FC       MOV      R4,A
C:0x3155    C3       CLR      C
C:0x3156    ED       MOV      A,R5
C:0x3157    9F       SUBB     A,R7
C:0x3158    EC       MOV      A,R4
C:0x3159    9E       SUBB     A,R6
C:0x315A    5015     JNC      C:3171
    41:         {
    42:                 for(i=0;i<100;i++);
C:0x315C    E4       CLR      A
C:0x315D    FB       MOV      R3,A
C:0x315E    FA       MOV      R2,A
C:0x315F    0B       INC      R3
C:0x3160    BB0001   CJNE     R3,#0x00,C:3164
C:0x3163    0A       INC      R2
C:0x3164    EB       MOV      A,R3
C:0x3165    6464     XRL      A,#0x64
C:0x3167    4A       ORL      A,R2
C:0x3168    70F5     JNZ      C:315F
    43:         }


如果延时函数的变量i和j用volatile或data修饰,主程序也正常。如果用xdata修饰,程序卡死。虽然问题可以避免,但还是想请教一下,为什么large模式下会出现这种问题?谢谢!

再补充一个现象,如果把延时函数改一下,在large模式下也正常.如下
void Delay_1ms(u16 x)
{  
    u16 i ,j;
    for(j=0;j<100;j++)
    {
        for(i=0;i<x;i++);
    }
     
}
其反汇编如下:
    49: void Delay_1ms(u16 x)  
    50: {   
    51:         u16 i ,j;
    52:         for(j=0;j<100;j++)
C:0x3152    E4       CLR      A
C:0x3153    FD       MOV      R5,A
C:0x3154    FC       MOV      R4,A
    53:         {
    54:                 for(i=0;i<x;i++);
C:0x3155    E4       CLR      A
C:0x3156    FB       MOV      R3,A
C:0x3157    FA       MOV      R2,A
C:0x3158    C3       CLR      C
C:0x3159    EB       MOV      A,R3
C:0x315A    9F       SUBB     A,R7
C:0x315B    EA       MOV      A,R2
C:0x315C    9E       SUBB     A,R6
C:0x315D    5007     JNC      C:3166
C:0x315F    0B       INC      R3
C:0x3160    BB0001   CJNE     R3,#0x00,C:3164
C:0x3163    0A       INC      R2
C:0x3164    80F2     SJMP     C:3158
    55:         }

补充一下:
延时函数5级优化,主程序正常:
#pragma OPTIMIZE(5)
void Delay_1ms(u16 x)
{  
    u16   i ,  j;
    for(j=0;j<x;j++)
    {
        for(i=0;i<100;i++);
    }
}
#pragma OPTIMIZE(8)
对应反汇编:
    41: void Delay_1ms(u16 x)  
    42: {   
    43:         u16   i ,  j;
    44:         for(j=0;j<x;j++)
C:0x31B3    E4       CLR      A
C:0x31B4    FD       MOV      R5,A
C:0x31B5    FC       MOV      R4,A
C:0x31B6    C3       CLR      C
C:0x31B7    ED       MOV      A,R5
C:0x31B8    9F       SUBB     A,R7
C:0x31B9    EC       MOV      A,R4
C:0x31BA    9E       SUBB     A,R6
C:0x31BB    501A     JNC      C:31D7
    45:         {
    46:                 for(i=0;i<100;i++);
C:0x31BD    E4       CLR      A
C:0x31BE    FB       MOV      R3,A
C:0x31BF    FA       MOV      R2,A
C:0x31C0    C3       CLR      C
C:0x31C1    EB       MOV      A,R3
C:0x31C2    9464     SUBB     A,#0x64
C:0x31C4    EA       MOV      A,R2
C:0x31C5    9400     SUBB     A,#0x00
C:0x31C7    5007     JNC      C:31D0
C:0x31C9    0B       INC      R3
C:0x31CA    EB       MOV      A,R3
C:0x31CB    7001     JNZ      C:31CE
C:0x31CD    0A       INC      R2
C:0x31CE    80F0     SJMP     C:31C0
    47:         }  

延时函数6级优化,主程序卡死:
#pragma OPTIMIZE(6)
void Delay_1ms(u16 x)
{  
    u16   i ,  j;
    for(j=0;j<x;j++)
    {
        for(i=0;i<100;i++);
    }
}
#pragma OPTIMIZE(8)
对应反汇编:
    41: void Delay_1ms(u16 x)  
    42: {   
    43:         u16   i ,  j;
    44:         for(j=0;j<x;j++)
C:0x326D    E4       CLR      A
C:0x326E    FD       MOV      R5,A
C:0x326F    FC       MOV      R4,A
C:0x3270    C3       CLR      C
C:0x3271    ED       MOV      A,R5
C:0x3272    9F       SUBB     A,R7
C:0x3273    EC       MOV      A,R4
C:0x3274    9E       SUBB     A,R6
C:0x3275    5015     JNC      C:328C
    45:         {
    46:                 for(i=0;i<100;i++);
C:0x3277    E4       CLR      A
C:0x3278    FB       MOV      R3,A
C:0x3279    FA       MOV      R2,A
C:0x327A    0B       INC      R3
C:0x327B    BB0001   CJNE     R3,#0x00,C:327F
C:0x327E    0A       INC      R2
C:0x327F    EB       MOV      A,R3
C:0x3280    6464     XRL      A,#0x64
C:0x3282    4A       ORL      A,R2
C:0x3283    70F5     JNZ      C:327A
    47:         }  

谢谢大家!暂时先以调整优化等级为方案解决这个问题!

元旦花了3天终于找到原因:
由于程序中使用了绝对地址定义变量,而这个地址是0xEF,导致栈地址是从0xF1开始,最终程序运行时导致栈溢出。感谢linqing171的提醒以及其他兄弟帮助!
定义了绝对地址变量内存分配如下:
            REG     0000H     0008H     ABSOLUTE     "REG BANK 0"
            DATA    0008H     0005H     UNIT         _DATA_GROUP_
                    000DH     0013H                  *** GAP ***
            BIT     0020H.0   0001H.1   UNIT         _BIT_GROUP_
                    0021H.1   0068H.7                *** GAP ***
            IDATA   00EFH     0002H     ABSOLUTE     
            IDATA   00F1H     0001H     UNIT         ?STACK
去掉绝对地址变量内存分配如下:

            * * * * * * *   D A T A   M E M O R Y   * * * * * * *
            REG     0000H     0008H     ABSOLUTE     "REG BANK 0"
            DATA    0008H     0005H     UNIT         _DATA_GROUP_
                    000DH     0013H                  *** GAP ***
            BIT     0020H.0   0001H.1   UNIT         _BIT_GROUP_
                    0021H.1   0000H.7                *** GAP ***
            IDATA   0022H     004EH     UNIT         ?ID?TIMER
            IDATA   0070H     0001H     UNIT         ?STACK


相关帖子

沙发
xyz549040622| | 2016-12-30 21:13 | 只看该作者
不懂,这是什么问题呢?

使用特权

评论回复
板凳
熊猫烧香|  楼主 | 2016-12-30 22:12 | 只看该作者
xyz549040622 发表于 2016-12-30 21:13
不懂,这是什么问题呢?

没编辑好不小心发出去了,抱歉!

使用特权

评论回复
地板
icecut| | 2016-12-31 17:12 | 只看该作者
你确定 xdata 是有的么?

使用特权

评论回复
5
幸福至上| | 2016-12-31 21:08 | 只看该作者
Large模式下,Keil会把变量数据默认放在xdata区域;而Small模式下,Keil会把变量默认放在idata区域。idata与xdata区别就是,idata是片内RAM,对于一般的51单片机,就是指那64~256byte的空间。xdata是扩展RAM,这个既可以是片内扩展的(如STC15F2Kxxs2系列),也可以是片外扩展的。你自己也说了"如果用xdata修饰,程序卡死",问题也就是此了,你所使用的MCU没有扩展RAM区,却将数据定义为xdata,导致数据读取错误,从而导致BUG.这个问题其实看一下Keil的Help手册是应该能够找到相关描述的。

使用特权

评论回复
6
linqing171| | 2016-12-31 21:36 | 只看该作者
楼主的这个函数只有两个变量,使用一个用R6R7,另外一个用R4R5; 临时运算结果使用的R2R3;
因为寄存器足够用的,所以这个函数无论在什么模式下都一样。问题出在外面有函数变量太多了,使用了xdata。
楼主可以把编译的map文件打开看看(在工程名上双击就可以打开了)。如果单片机没有xdata,是不能用large模式的。

使用特权

评论回复
7
熊猫烧香|  楼主 | 2017-1-1 12:32 | 只看该作者
icecut 发表于 2016-12-31 17:12
你确定 xdata 是有的么?

确定是有的,单片机型号STC15W4K56S4,RAM是4K

使用特权

评论回复
8
熊猫烧香|  楼主 | 2017-1-1 12:49 | 只看该作者
幸福至上 发表于 2016-12-31 21:08
Large模式下,Keil会把变量数据默认放在xdata区域;而Small模式下,Keil会把变量默认放在idata区域。idata与x ...

感谢答复!STC15W4K56S4有4KRAM,是片内扩展的。我后来想了一下,可能是在large模式下,delay延时变长,不能满足LCD的时序要求而导致的bug。我试着改变j的参数和延时形参x,但效果不明显,时好时坏,可能需要示波器准确测量延时函数的时间。后又怀疑大循环100ms来不及处理,试着改成1s,10s,然并没有效果。

使用特权

评论回复
9
熊猫烧香|  楼主 | 2017-1-1 12:55 | 只看该作者
linqing171 发表于 2016-12-31 21:36
楼主的这个函数只有两个变量,使用一个用R6R7,另外一个用R4R5; 临时运算结果使用的R2R3;
因为寄存器足够 ...

这是在large模式下.m51文件截了一部分内容,如下:
LINK MAP OF MODULE:  .\Objects\VCBB-V2_0 (?C_STARTUP)


            TYPE    BASE      LENGTH    RELOCATION   SEGMENT NAME
            -----------------------------------------------------

            * * * * * * *   D A T A   M E M O R Y   * * * * * * *
            REG     0000H     0008H     ABSOLUTE     "REG BANK 0"
            DATA    0008H     0005H     UNIT         _DATA_GROUP_
                    000DH     0013H                  *** GAP ***
            BIT     0020H.0   0001H.1   UNIT         _BIT_GROUP_
                    0021H.1   0068H.7                *** GAP ***
            IDATA   00EFH     0002H     ABSOLUTE     
            IDATA   00F1H     0001H     UNIT         ?STACK

            * * * * * * *  X D A T A   M E M O R Y  * * * * * * *
            XDATA   0000H     045EH     UNIT         _XDATA_GROUP_
            XDATA   045EH     0050H     UNIT         ?XD?TIMER
            XDATA   04AEH     0019H     UNIT         ?XD?PARAMS
            XDATA   04C7H     000CH     UNIT         ?XD?BSP_DS1302
            XDATA   04D3H     0009H     UNIT         ?XD?MENU
            XDATA   04DCH     0009H     UNIT         ?XD?BSP_KEY
            XDATA   04E5H     0008H     UNIT         ?XD?MAIN
            XDATA   04EDH     0008H     UNIT         ?XD?MENU_FUNCTION
            XDATA   04F5H     0007H     UNIT         ?XD?BSP_PUMPS
            XDATA   04FCH     0004H     UNIT         ?XD?STC15_ADC

使用特权

评论回复
10
熊猫烧香|  楼主 | 2017-1-1 13:04 | 只看该作者
yyy71cj 发表于 2017-1-1 12:07
large模式下翻译出的变量竟也是data变量?keil是不是有毛病啊?

感谢提醒,这个应该是keil自行优化的结果,我现在是默认的8级优化,如果我程序这样写,延时函数不优化如下:
#pragma OPTIMIZE(0)
void Delay_1ms(u16 x)
{  
        u16   i ,  j;
        for(j=0;j<x;j++)
        {
                for(i=0;i<100;i++);
        }
}
#pragma OPTIMIZE(8)

相应的反汇编如下:
    42: {   
    43:         u16   i ,  j;
    44:         for(j=0;j<x;j++)
C:0x2C6A    900500   MOV      DPTR,#0x0500
C:0x2C6D    E4       CLR      A
C:0x2C6E    F0       MOVX     @DPTR,A
C:0x2C6F    A3       INC      DPTR
C:0x2C70    E4       CLR      A
C:0x2C71    F0       MOVX     @DPTR,A
C:0x2C72    9004FC   MOV      DPTR,#0x04FC
C:0x2C75    E0       MOVX     A,@DPTR
C:0x2C76    FE       MOV      R6,A
C:0x2C77    A3       INC      DPTR
C:0x2C78    E0       MOVX     A,@DPTR
C:0x2C79    FF       MOV      R7,A
C:0x2C7A    900500   MOV      DPTR,#0x0500
C:0x2C7D    E0       MOVX     A,@DPTR
C:0x2C7E    FC       MOV      R4,A
C:0x2C7F    A3       INC      DPTR
C:0x2C80    E0       MOVX     A,@DPTR
C:0x2C81    FD       MOV      R5,A
C:0x2C82    C3       CLR      C
C:0x2C83    ED       MOV      A,R5
C:0x2C84    9F       SUBB     A,R7
C:0x2C85    EC       MOV      A,R4
C:0x2C86    9E       SUBB     A,R6
C:0x2C87    5039     JNC      C:2CC2
    45:         {
    46:                 for(i=0;i<100;i++);
C:0x2C89    9004FE   MOV      DPTR,#0x04FE
C:0x2C8C    E4       CLR      A
C:0x2C8D    F0       MOVX     @DPTR,A
C:0x2C8E    A3       INC      DPTR
C:0x2C8F    E4       CLR      A
C:0x2C90    F0       MOVX     @DPTR,A
C:0x2C91    9004FE   MOV      DPTR,#0x04FE
C:0x2C94    E0       MOVX     A,@DPTR
C:0x2C95    FE       MOV      R6,A
C:0x2C96    A3       INC      DPTR
C:0x2C97    E0       MOVX     A,@DPTR
C:0x2C98    FF       MOV      R7,A
C:0x2C99    C3       CLR      C
C:0x2C9A    EF       MOV      A,R7
C:0x2C9B    9464     SUBB     A,#0x64
C:0x2C9D    EE       MOV      A,R6
C:0x2C9E    9400     SUBB     A,#0x00
C:0x2CA0    5010     JNC      C:2CB2
C:0x2CA2    9004FF   MOV      DPTR,#0x04FF
C:0x2CA5    E0       MOVX     A,@DPTR
C:0x2CA6    04       INC      A
C:0x2CA7    F0       MOVX     @DPTR,A
C:0x2CA8    7006     JNZ      C:2CB0
C:0x2CAA    9004FE   MOV      DPTR,#0x04FE
C:0x2CAD    E0       MOVX     A,@DPTR
C:0x2CAE    04       INC      A
C:0x2CAF    F0       MOVX     @DPTR,A
C:0x2CB0    80DF     SJMP     C:2C91
    47:         }  
如果延时函数不优化,程序在large模式下也是正常的

使用特权

评论回复
11
熊猫烧香|  楼主 | 2017-1-2 12:35 | 只看该作者
yyy71cj 发表于 2017-1-1 15:58
确信你的单片机存在xdata,片内扩充的或外部扩充的

是片内扩充的,问题的根本原因是栈溢出了

使用特权

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

本版积分规则

5

主题

24

帖子

0

粉丝