做網(wǎng)站的職位公司域名注冊查詢
1、問題陳述
????????今天在測試小車程序的時候使用了如下代碼,發(fā)現(xiàn)延時并沒有達到期望的4s,而是僅僅延時了0.4s左右,本來以為少加了個0,最后在我多次測試下來,發(fā)現(xiàn)在延時大約超過2s的時候就會失效。
while(1){Set_Pwm(6000,6000);printf("%d\t",Read_Encoder(2));printf("%d",Read_Encoder(3));printf("\r\n");delay_ms(4000);Set_Pwm(-5000,-5000);printf("%d\t",Read_Encoder(2));printf("%d",Read_Encoder(3));printf("\r\n");delay_ms(4000);}
2、問題解決
? ? ? ? 再我重新翻閱了一下不完全手冊后,終于發(fā)現(xiàn)了問題出在了SysTick-> VAL這個寄存器上:
????????我們先看初始化函數(shù)::
void delay_init()
{
#if SYSTEM_SUPPORT_OS //如果需要支持OS.u32 reload;
#endifSysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //選擇外部時鐘 HCLK/8fac_us=SystemCoreClock/8000000; //為系統(tǒng)時鐘的1/8
#if SYSTEM_SUPPORT_OS //如果需要支持OS.reload=SystemCoreClock/8000000; //每秒鐘的計數(shù)次數(shù) 單位為M reload*=1000000/delay_ostickspersec; //根據(jù)delay_ostickspersec設定溢出時間//reload為24位寄存器,最大值:16777216,在72M下,約合1.86s左右 fac_ms=1000/delay_ostickspersec; //代表OS可以延時的最少單位 SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //開啟SYSTICK中斷SysTick->LOAD=reload; //每1/delay_ostickspersec秒中斷一次 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //開啟SYSTICK #elsefac_ms=(u16)fac_us*1000; //非OS下,代表每個ms需要的systick時鐘數(shù)
#endif
}
? ? ? ? 我們主要看fac_us和fac_ms?,他們分別表示延時1us、1ms需要多少個SysTick 時鐘周期。通過跳轉可知,SystemCoreClock為72Mhz,SystemCoreClock/8 代表經(jīng)過1s需要多少個時鐘周期,再除以1000000則表示經(jīng)過1us需要多少個時鐘周期。通過計算可知fac_us=9,fac_ms=9000。
? ? ? ? 我們再看us的延時函數(shù):
void delay_us(u32 nus)
{ u32 temp; SysTick->LOAD=nus*fac_us; //時間加載 SysTick->VAL=0x00; //清空計數(shù)器SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //開始倒數(shù) do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16))); //等待時間到達 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //關閉計數(shù)器SysTick->VAL =0X00; //清空計數(shù)器
}
? ? ? ??SysTick是MDK自定義的一個寄存器。SysTick->CTRL主要是開關計數(shù)器,SysTick-> LOAD類似于重裝載寄存器,在倒數(shù)到0后進行重裝載,SysTick-> VAL是計數(shù)器,進行倒數(shù)。
? ? ? ? 這個函數(shù)先計算出需要倒數(shù)的時間nus*fac_us,存到LOAD中,然后清空當前寄存器 VAL 的內容,再開啟倒數(shù)功能。等到倒數(shù)結束,最后關閉 SysTick,清空 VAL 的值。
? ? ? ? 但是但是!!!重點的來了,LOAD,VAL是個24位寄存器。也就是最大值為2^24=16777216.也就是說:需要倒數(shù)的時間:nus*fac_us必須小于2^24,則nus=2^24/9=1864135.1111111.換算成ms大概就是1800秒。
? ? ? ? 所以開頭我延時4000ms的效果其實就是4000-(1800*2)=400ms,約0.4s左右。