杰理延时方式汇总

延时方式汇总

指令数延时(浪费cpu资源)

1
2
3
4
void delay(unsigned int);

delay(100); //执行100个nop
//受系统频率影响,同样的语句,实际延时时间波动很大

按照系统时钟换算指令数延时(浪费cpu资源)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 小于10us的执行不精准,不同系统频率下需要自行调整div值
AT_VOLATILE_RAM_CODE
void delay_us_by_nop(u32 usec)
{
u32 sys = clk_get("sys");
u32 cnt, div;
if(usec == 1) { div = 30;}
else if(usec == 2){ div = 12;}
else if(usec == 3){ div = 8; }
else if(usec < 10){ div = 6; }
else { div = 5; }
cnt = usec * (sys / 1000000L / div);
while(cnt--){ asm volatile("nop"); }
}

int clk_set_sys_lock(int clk, int lock_en);
extern void clk_set_en(u8 en);
clk_set_en(0);
//可执行此函数,锁住系统频率不被修改。

定时器计算延时(浪费cpu资源)延时要大于5us

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//函数是AC632 - BD19的寄存器写法,其他芯片参考sdk对应工程的写法

//有概率会被中断打断,导致延时变大
AT_VOLATILE_RAM_CODE
void delay_us_by_timer0(u32 usec)
{
usec -= 2; //usec > 5,减掉此函数执行本身的耗时,48M->2us,24M->5us
JL_TIMER0->CON = BIT(14);
JL_TIMER0->CNT = 0;
JL_TIMER0->PRD = clk_get("lsb") / 2 / 1000000L * usec;
JL_TIMER0->CON = BIT(0) | BIT(6); //lsb clk 2分频
while ((JL_TIMER0->CON & BIT(15)) == 0);
JL_TIMER0->CON = BIT(14);
}

//关中断,临界区延时
AT_VOLATILE_RAM_CODE
void delay_us_by_timer0_irq(u32 usec)
{
usec -= 2; //usec > 5,减掉此函数执行本身的耗时,48M->2us,24M->5us
local_irq_disable();
JL_TIMER0->CON = BIT(14);
JL_TIMER0->CNT = 0;
JL_TIMER0->PRD = clk_get("lsb") / 2 / 1000000L * usec;
JL_TIMER0->CON = BIT(0) | BIT(6); //lsb clk 2分频
while ((JL_TIMER0->CON & BIT(15)) == 0);
JL_TIMER0->CON = BIT(14);
local_irq_enable();
}

//ms级延时,一般要求不需要精准,不用加关中断
AT_VOLATILE_RAM_CODE
void delay_ms_by_timer0(u32 msec)
{
JL_TIMER0->CON = BIT(14);
JL_TIMER0->CNT = 0;
JL_TIMER0->PRD = clk_get("lsb") / 64 / 1000L * msec;
JL_TIMER0->CON = BIT(0) | BIT(5) | BIT(4); //lsb clk 64分频
while ((JL_TIMER0->CON & BIT(15)) == 0);
JL_TIMER0->CON = BIT(14);
}

系统调度延时(不浪费CPU资源)单位:10ms

1
2
3
4
5
void os_time_dly(int time_tick);

os_time_dly(1); //参数1,即延时10ms,会切出当前任务,执行其他任务
//小于10ms的延时方式,都会浪费CPU资源。
//任务调度延时,只有10ms单位的,改不了 <10ms 的单位。