请51汇编或者编译器使用的高手解决问题,keil @ C8051系列MCU

2020-01-27 11:50发布

问题描述如下:
由于需要精确的时序,在C工程中嵌入了汇编代码,当然这样的事情也经常做,但是这次发现了问题,而且一时半会没办法解决。

具体的情况是我需要操作一个IO口输出特定的时序,使用汇编语句精确计算了执行的时钟数,最终输出也‘基本符合’要求的时序,不过出现了及其细微的误差,这个误差不是显性的能看出来(比如通过代码),而且用示波器看的时候才出现。
时序是,将输入的字节内容(累加器A)按位进行曼切斯特编码输出到IO口,问题现象是,例如ACC.0是50us正确,ACC.1就是52us,ACC.2又是50us,ACC.3又是52us如此比较有规律的出现(偶尔也会出现51us的时候),代码如下:


        MOVX A,@DPTR;        3     //得到需要传输的内容
           EA=0;                             //关闭全局中断,防止打乱时序
        rlc a;                1
        jc B0;                2/4
        nop;                1
        nop;                1
        lcall BIT_0;        5
        ajmp $+8;        4
B0:        lcall BIT_1;        5
        NOP;
        NOP;
        NOP;
;        NOP;
        rlc a;
        jc B1;
        nop;
        nop;
        lcall BIT_0;
        ajmp $+8;
B1:        lcall BIT_1;
        NOP;
        NOP;
        NOP;
;        NOP;
        rlc a;
        jc B2;
        nop;
        nop;
        lcall BIT_0;
        ajmp $+8;
B2:        lcall BIT_1;
        NOP;
        NOP;
        NOP;
;        NOP;
        rlc a;
        jc B3;
        nop;
        nop;
        lcall BIT_0;
        ajmp $+8;
B3:        lcall BIT_1;
        NOP;
        NOP;
        NOP;
;        NOP;
        rlc a;
        jc B4;
        nop;
        nop;
        lcall BIT_0;
        ajmp $+8;
B4:        lcall BIT_1;
        NOP;
        NOP;
        NOP;
;        NOP;
        rlc a;
        jc B5;
        nop;
        nop;
        lcall BIT_0;
        ajmp $+8;
B5:        lcall BIT_1;
        NOP;
        NOP;
        NOP;
;        NOP;
        rlc a;
        jc B6;
        nop;
        nop;
        lcall BIT_0;
        ajmp $+8;
B6:        lcall BIT_1;
。。。
以下的位都是一样的了。。。略去。
////////////////////////////////////////

这里是BIT_1和BIT_0

//------//
BIT_1:
        setb ASK;   //IO 口
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        clr ASK;
        ret;                                //total:30 clk

BIT_0:
        clr ASK;     //IO口
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        nop;
        NOP;
        nop;
        ;nop;
        setb ASK;
        ret;                                //total:30 clk
//------//

上面的BIT_1和BIT_0函数部分其具体的执行细节可以不管具体是多少个周期,问题关键是例如将累加器的值固定为全1(0xff)或者全0(0x00)后,后续的B3:,以及B4:就会出现前面描述的执行时钟会偏差1、2个时钟周期的现象。而且随着BIT_1和BIT_0函数的摆放位置不同(比如现在是放在调用主体后面的,当放在调用主体前面就是不同)后,执行结果居然就有差异。
特别说明一下,上述代码在执行过程中绝对没有被中断等干扰 现象,因为使用前关闭了全局中断EA=0



汇编后的代码如下,可见完全有规律,根本没有哪里多一条指令或者少一条指令的现象,连跳转的间隔都是一样的。

C:0x19F0    12193E   LCALL    BIT_1(C:193E)
C:0x19F3    00       NOP      
C:0x19F4    00       NOP      
C:0x19F5    00       NOP      
C:0x19F6    33       RLC      A
C:0x19F7    4007     JC       B1(C:1A00)
C:0x19F9    00       NOP      
C:0x19FA    00       NOP      
C:0x19FB    12195A   LCALL    BIT_0(C:195A)
C:0x19FE    4106     AJMP     C:1A06
                 B1:
C:0x1A00    12193E   LCALL    BIT_1(C:193E)
C:0x1A03    00       NOP      
C:0x1A04    00       NOP      
C:0x1A05    00       NOP      
C:0x1A06    33       RLC      A
C:0x1A07    4007     JC       B2(C:1A10)
C:0x1A09    00       NOP      
C:0x1A0A    00       NOP      
C:0x1A0B    12195A   LCALL    BIT_0(C:195A)
C:0x1A0E    4116     AJMP     C:1A16
                 B2:
C:0x1A10    12193E   LCALL    BIT_1(C:193E)
C:0x1A13    00       NOP      
C:0x1A14    00       NOP      
C:0x1A15    00       NOP      
C:0x1A16    33       RLC      A
C:0x1A17    4007     JC       B3(C:1A20)
C:0x1A19    00       NOP      
C:0x1A1A    00       NOP      
C:0x1A1B    12195A   LCALL    BIT_0(C:195A)
C:0x1A1E    4126     AJMP     C:1A26
                 B3:
C:0x1A20    12193E   LCALL    BIT_1(C:193E)
C:0x1A23    00       NOP      
C:0x1A24    00       NOP      
C:0x1A25    00       NOP      
C:0x1A26    33       RLC      A
C:0x1A27    4007     JC       B4(C:1A30)
C:0x1A29    00       NOP      
C:0x1A2A    00       NOP      
C:0x1A2B    12195A   LCALL    BIT_0(C:195A)
C:0x1A2E    4136     AJMP     C:1A36
                 B4:
C:0x1A30    12193E   LCALL    BIT_1(C:193E)
C:0x1A33    00       NOP      
C:0x1A34    00       NOP      
C:0x1A35    00       NOP      
C:0x1A36    33       RLC      A
C:0x1A37    4007     JC       B5(C:1A40)
C:0x1A39    00       NOP      
C:0x1A3A    00       NOP      
C:0x1A3B    12195A   LCALL    BIT_0(C:195A)
C:0x1A3E    4146     AJMP     C:1A46
                 B5:
C:0x1A40    12193E   LCALL    BIT_1(C:193E)
C:0x1A43    00       NOP      
C:0x1A44    00       NOP      
C:0x1A45    00       NOP      
C:0x1A46    33       RLC      A
C:0x1A47    4007     JC       B6(C:1A50)
C:0x1A49    00       NOP      
C:0x1A4A    00       NOP      
C:0x1A4B    12195A   LCALL    BIT_0(C:195A)
C:0x1A4E    4156     AJMP     C:1A56
                 B6:
C:0x1A50    12193E   LCALL    BIT_1(C:193E)


太长太多,求高手
0条回答

一周热门 更多>