基于tick的单片机delay写法分析
接触单片机以来,遇到过形形色色的delay写法,分析下来,不外乎以下4种写法(拆成非阻塞来分析了,阻塞的话合并在一起就行,不废话)
1.减法判断
1 uint32_t Tick_Bak0; 2 uint32_t Tick_Delay0; 3 void Test_Set_Delay0(uint32_t tick) 4 { 5 Tick_Delay0 = tick; 6 Tick_Bak0 = Sys_Get_Tick(); 7 8 db_printf("\t%s(%u) , bakTick = %u\n", __FUNCTION__, tick, Tick_Bak0); 9 } 10 11 uint32_t Test_Is_Timeout0(void) 12 { 13 uint32_t curTick = Sys_Get_Tick(); 14 if((curTick - Tick_Bak0) >= Tick_Delay0) 15 { 16 db_printf("[%010u] %s\n", curTick, __FUNCTION__); 17 return 1; 18 } 19 return 0; 20 }
2.加法判断
1 uint32_t Tick_Bak1; 2 uint32_t Tick_Delay1; 3 void Test_Set_Delay1(uint32_t tick) 4 { 5 Tick_Delay1 = tick; 6 Tick_Bak1 = Sys_Get_Tick(); 7 8 db_printf("\t%s(%u) , bakTick = %u\n", __FUNCTION__, tick, Tick_Bak1); 9 } 10 11 uint32_t Test_Is_Timeout1(void) 12 { 13 uint32_t curTick = Sys_Get_Tick(); 14 if((0xFFFFFFFFU - Tick_Bak1) < Tick_Delay1) 15 { 16 if((Tick_Bak1 > curTick) && (curTick >= (Tick_Bak1 + Tick_Delay1))) 17 { 18 db_printf("[%010u] %s\n", curTick, __FUNCTION__); 19 return 1; 20 } 21 } 22 else 23 { 24 if(curTick >= (Tick_Bak1 + Tick_Delay1)) 25 { 26 db_printf("[%010u] %s\n", curTick, __FUNCTION__); 27 return 1; 28 } 29 } 30 31 return 0; 32 }
3.大于等于目标时刻判断
1 uint32_t Tick_Bak2; 2 uint32_t Tick_Target2; 3 void Test_Set_Delay2(uint32_t tick) 4 { 5 Tick_Bak2 = Sys_Get_Tick(); 6 Tick_Target2 = Tick_Bak2 + tick; 7 8 db_printf("\t%s(%u) , bakTick = %u\n", __FUNCTION__, tick, Tick_Bak2); 9 } 10 11 uint32_t Test_Is_Timeout2(void) 12 { 13 uint32_t curTick = Sys_Get_Tick(); 14 if(Tick_Bak2 <= Tick_Target2) 15 { 16 if(curTick >= Tick_Target2) 17 { 18 db_printf("[%010u] %s\n", curTick, __FUNCTION__); 19 return 1; 20 } 21 } 22 else 23 { 24 if((curTick < Tick_Bak2) && (curTick >= Tick_Target2)) 25 { 26 db_printf("[%010u] %s\n", curTick, __FUNCTION__); 27 return 1; 28 } 29 } 30 31 return 0; 32 }
4.等于目标时刻判断
1 uint32_t Tick_Target3; 2 void Test_Set_Delay3(uint32_t tick) 3 { 4 uint32_t Tick_Bak3 = Sys_Get_Tick(); 5 Tick_Target3 = Tick_Bak3 + tick; 6 7 db_printf("\t%s(%u) , bakTick = %u\n", __FUNCTION__, tick, Tick_Bak3); 8 } 9 10 uint32_t Test_Is_Timeout3(void) 11 { 12 uint32_t curTick = Sys_Get_Tick(); 13 if(curTick == Tick_Target3) 14 { 15 db_printf("[%010u] %s\n", curTick, __FUNCTION__); 16 return 1; 17 } 18 19 return 0; 20 }
以上4种方法对比见下表:
| 代码写法 | 全局变量 | 执行效率排行1 | 风险 |
| 1.减法判断 | 8bytes | 2 | 1.要延时的值接近0xFFFFFFFFU时,程序中一旦有大于对应差值的阻塞,GG |
| 2.加法判断 | 8bytes | 4 |
1.要延时的值接近0xFFFFFFFFU时,程序中一旦有大于对应差值的阻塞,GG 2.Tick_Bak1 + Tick_Delay1接近0xFFFFFFFFU时,程序中一旦有大于对应差值的阻塞,GG |
| 3.大于等于目标时刻判断 | 8bytes | 3 |
1.要延时的值接近0xFFFFFFFFU时,程序中一旦有大于对应差值的阻塞,GG 2.Tick_Target2接近0xFFFFFFFFU时,程序中一旦有大于对应差值的阻塞,GG |
| 4.等于目标时刻判断 | 4bytes | 1 | 1.程序中一旦有大于tick的阻塞,GG |
[1]执行效率排行通过在STM32G431CB最小系统板上分别运行以上4种方式的延时代码,取消打印后,统计测试过程中Test_Is_Timeoutx的执行次数,次数越多,排行越低。具体程序:取1ms为tick的间隔,从tick为(0xFFFFFFFFU-3600000U)到3600000U期间,每1000ms设置一次时间为1000ms的延时,并一直查询是否timeout。
浙公网安备 33010602011771号