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