本帖最后由 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();
}
|