打印
[KungFu8位 MCU]

如何使用软延迟来比较准确获得us为单位的延迟?[计算汇编的方式行不通}

[复制链接]
1285|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lvben5d|  楼主 | 2022-10-19 08:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ov, vr, AN, se, US, 使用
本帖最后由 lvben5d 于 2022-10-20 14:40 编辑

在一些项目中,特别容易用到us级别的软延迟来阻塞代码 完成一些时序控制,对于32位机可以仿真看到汇编指令执行,而KF8,我记得之前仿真的时候看到过汇编窗口,但最近这几天找遍菜单没发现。
实际使用中,会需要用到这个函数             主频基本大家肯定都用16M  机器周期是1/4   也就是4M  . 单周期指令是1/4us !
void delay_us(unsigned int ctr)
{
   unsigned int m=0;
    for(; ctr>0; ctr--)
    {
        _NOP();
    }
}
对应汇编代码中  有的看不懂  请大家多多执教,我备注上去
BANKSEL        r0x10A0  这个 是指定编译器使用 R0寄存器的地址  需要占机器周期 还是不用?
_delay_us        ;Function start
; 2 exit points
;        ::->op : RECEIVE
        .line        58; "../user_periph.c"        void delay_us(unsigned char ctr)
        BANKSEL        r0x10A0
        MOV        r0x10A0, R0          //寄存器直接寻址 ?             1T
;        ::->op : =
        .line        60; "../user_periph.c"        unsigned char n=0;
        BANKSEL        r0x10A1            
        CLR        r0x10A1               //              1T
;        ::->op : =
;        ::->op : LABEL
;        ::->op : IFX
_00026_DS_
        .line        61; "../user_periph.c"        for(; ctr>0; ctr--)
        MOV        R0,# 0x00             // 1T
        BANKSEL        r0x10A0               //
        ORL        R0, r0x10A0         //  1T
        JNB        PSW, 2                //  1/2
        JMP        _00032_DS_         //  2T
;        ::->op : =
        MOV        R0,# 0x01           // 1T
        BANKSEL        r0x10A2
        MOV        r0x10A2, R0       // 1T   
;        ::->op : GOTO
        JMP        _00033_DS_       // 2T
;        ::->op : LABEL
;        ::->op : =
_00032_DS_
        BANKSEL        r0x10A2
        CLR        r0x10A2             // 1T   
;        ::->op : LABEL
;        ::->op : IFX
_00033_DS_
        MOV        R0,# 0x00           // 1T   
        BANKSEL        r0x10A2
        ORL        R0, r0x10A2       // 1T   
        JNB        PSW, 2              //  1/2
        JMP        _00030_DS_        // 1T
;        ::->op : +
        .line        63; "../user_periph.c"        n++;
        BANKSEL        r0x10A1
        INC        r0x10A1            // 1T
;        ::->op : -
        .line        61; "../user_periph.c"        for(; ctr>0; ctr--)
        BANKSEL        r0x10A0
        DEC        r0x10A0               //1T
;        ::->op : GOTO
        JMP        _00026_DS_          //2T
;        ::->op : LABEL
;        ::->op : ENDFUNCTION
_00030_DS_
        CRET                                   //2T
        .def _delay_us_function_end, debug, value=$
; exit point of _delay_us
经过今天验证发现上述办法 无法按照预定计划来: 目前我修改如下   @主频是16M
void delay_50us(void)        //这个经过示波器看 实际大概是51us
{
        u8 n1;
        for(n1=0; n1<22; n1++)
        {
                _NOP();
        }
}

void delay_500us(void)     //这个经过示波器看 实际大概是501us
{
        u8 n1;
        for(n1=0; n1<220; n1++)
        {
                _NOP();
        }
}   其他的延迟数值 自己按照500us 循环220数值  来比例修改, 甚至 循环体外面可以  _NOP(); _NOP(); _NOP();
void delay_7us(void)
{
        u8 n1;
        for(n1=0; n1<3; n1++)
        {
                _NOP();
        }
}

void delay_8us(void)
{
        u8 n1;
        for(n1=0; n1<3; n1++)
        {
                _NOP();
        }
        _NOP();
        _NOP();
        _NOP();
        _NOP();
}


使用特权

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

本版积分规则

95

主题

746

帖子

12

粉丝