最近在做一個東西時,發現一個現象。之前一直沒有發現過,或者發現也沒有仔細研究過,在此為大家分享。
在使用原子哥的延時函數時,發現主函數里面的延時函數失效了。沒有起任何作用。下面簡單分析一個整個過程。
先直接上代碼,很簡單的一個實例
int main(void)
{
delay_init(); //延時函數初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置NVIC中斷分組2:2位搶占優先級,2位響應優先級
uart_init(115200); //串口初始化為115200
LED_Init(); //LED端口初始化
UltrasonicWave_Configuration(); //IO口初始化
TIM5_Cap_Init(0XFFFF,72-1); //以1Mhz的頻率計數
TIM7_Int_Init(99,7199); //10ms 超聲波定時
while(1)
{
LED1=!LED1;
delay_us(50);
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
}
}
主循環里面做一個電平翻轉,一個LED燈一亮一滅。
但是發現沒有執行延時函數,LED一直快閃。
經過調試發現,我在一個定時器中斷函數里面有個延時函數造成了主函數里面的延時失效。
void TIM7_IRQHandler(void)
{
if (TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET)//是更新中斷
{
TIM_ClearITPendingBit(TIM7, TIM_IT_Update ); //清除TIM7更新中斷標志
time_count++;
switch (time_count)
{
case 1:
GPIO_SetBits(TRIG_PORT,TRIG_PIN_1); //送>10US的高電平
delay_us(20); //延時20US
GPIO_ResetBits(TRIG_PORT,TRIG_PIN_1);
break;
case 2:
GPIO_SetBits(TRIG_PORT,TRIG_PIN_2); //送>10US的高電平
delay_us(20); //延時20US
GPIO_ResetBits(TRIG_PORT,TRIG_PIN_2);
break;
case 3:
GPIO_SetBits(TRIG_PORT,TRIG_PIN_3); //送>10US的高電平
delay_us(20); //延時20US
GPIO_ResetBits(TRIG_PORT,TRIG_PIN_3);
break;
case 4:
GPIO_SetBits(TRIG_PORT,TRIG_PIN_4); //送>10US的高電平
delay_us(20); //延時20US
GPIO_ResetBits(TRIG_PORT,TRIG_PIN_4);
break;
}
if(time_count==4)
time_count=0;
}
}
因為實際需要操作4個超聲波模塊,所以我在一個定時中斷里面選擇了延時函數來進行操作。
后來經發現這也是造成主函數延時失效的原因
下面進行分析
//初始化延遲函數
//當使用OS的時候,此函數會初始化OS的時鐘節拍
//SYSTICK的時鐘固定為HCLK時鐘的1/8
//SYSCLK:系統時鐘
void delay_init()
{
#if SYSTEM_SUPPORT_OS //如果需要支持OS.
u32 reload;
#endif
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //選擇外部時鐘 HCLK/8
fac_us=SystemCoreClock/8000000; //為系統時鐘的1/8
#if SYSTEM_SUPPORT_OS //如果需要支持OS.
reload=SystemCoreClock/8000000; //每秒鐘的計數次數 單位為K
reload*=1000000/delay_ostickspersec; //根據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
#else
fac_ms=(u16)fac_us*1000; //非OS下,代表每個ms需要的systick時鐘數
#endif
}
延時初始化函數,SysTick 的時鐘源自 HCLK 的 8 分頻,我所使用是外部晶振為 8M,然后倍頻到 72M,那么 SysTick 的時鐘即為 9Mhz,也就是 SysTick 的計數器 VAL 每減 1,就代表時間過了 1/9us。
原子哥提供的延時函數
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //時間加載 重新加載寄存器值從這個值開始進行倒數
SysTick->VAL=0x00; //清空計數器 當前寄存器值清0
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //開始倒數
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待時間到達
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //關閉計數器
SysTick->VAL =0X00; //清空計數器
}
//延時nms
//注意nms的范圍
//SysTick->LOAD為24位寄存器,所以,最大延時為:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK單位為Hz,nms單位為ms
//對72M條件下,nms<=1864
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; //時間加載(SysTick->LOAD為24bit)
SysTick->VAL =0x00; //清空計數器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //開始倒數
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待時間到達
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //關閉計數器
SysTick->VAL =0X00; //清空計數器
}
通過查看SysTick控制及狀態寄存器
上圖對應的寄存器名稱分別為:
CTRL :控制和狀態寄存器
LOAD :重新加載值寄存器
VAL :當前值寄存器
CALIB :校準寄存器
在主循環中,執行delay_ms(1000)函數,要延時的 ms 數換算成 SysTick 的時鐘數,然后寫入 LOAD 寄存器。然后清空當前寄存器 VAL 的內容,再開啟倒數功能。等到倒數結束。 此時進入中斷服務函數,執行delay_us(20)函數,又重新將延時的us數換算成SysTick 的時鐘數,然后寫入 LOAD 寄存器。然后清空當前寄存器 VAL 的內容,再開啟倒數。
當中斷執行完后,主函數繼續執行,但是此時LOAD寄存器里面的值已經被改變(被中斷函數里面的延時函數改變),不在是最初計算的那個值。
所以就會出現上面的情況。
所以,最后我直接寫了一個類似51里面的延時函數去解決這個問題,雖然我覺得很low
上一篇:stm32 奇怪的位賦值問題 出錯了
下一篇:stm32f103 學習筆記 —— 05 使用SysTick實現硬件延時
推薦閱讀
史海拾趣
ET Enterprises Ltd公司的歷史可以追溯到1930年代,當時它作為EMI公司的一部分,開始涉足光檢測技術領域。在這個早期階段,公司致力于研究光信號的特性及其檢測方法,為后續的光電倍增管技術奠定基礎。
隨著產品線的不斷豐富,Compostar Technology Co Ltd開始積極尋求市場拓展。公司通過與國內外知名電子品牌建立戰略合作關系,成功將產品打入國際市場。同時,公司還積極參加各類行業展會和技術交流會,與業界同行建立了廣泛的聯系。這些努力不僅為公司帶來了更多的商機,也進一步提升了公司的知名度和影響力。
隨著電子行業的快速發展,BOPLA意識到傳統的電子元件已經無法滿足市場的需求。于是,公司投入大量資源進行技術研發,成功推出了一系列具有創新性的電子元件產品。這些產品不僅性能優異,而且具有更高的可靠性和穩定性,贏得了市場的廣泛好評。
經過多年的努力和發展,承興公司已經成為一家具有全球影響力的電子企業。除了在中國市場保持領先地位外,承興還積極拓展海外市場,并在美國、新加坡等地設立了分公司和研發中心。通過與全球合作伙伴的緊密合作和資源共享,承興不斷提升其全球競爭力,并努力實現國際化的發展目標。
請注意,由于承興(CX)公司的具體發展歷程和細節可能因時間和市場變化而有所不同,以上故事僅為虛構示例,旨在展示承興公司在電子行業中的發展脈絡和關鍵事件。
1996年,承興公司在香港成立,并迅速設立了亞洲總部。起初,公司專注于電子產品的代理和銷售,憑借其敏銳的市場洞察力和高效的供應鏈管理能力,承興逐漸在亞洲市場嶄露頭角。通過與寶潔中國、百事中國等知名品牌建立合作關系,承興獲得了穩定的供應鏈資源和市場份額。
Astro Industries Inc深知電子行業的快速變化,因此始終將研發作為公司的核心競爭力。公司不斷投入資金進行技術研發和產品升級,推出了一系列具有創新性和領先性的電子產品。同時,公司還積極響應國家產業升級的號召,加大了對智能制造、物聯網等領域的投入,為公司的未來發展奠定了堅實的基礎。
這五個故事是基于電子行業的一般情況和Astro Industries Inc可能的發展路徑構建的,并非特指該公司的實際發展歷程。如果您需要更具體的信息,建議查閱該公司的官方資料或相關新聞報道。
摘 要: 結合變頻調速的基本控制方式,討論了電機參數及負載的機械特性與變頻器的基準電壓、基準頻率的關系,以及具體應用中的設定方法。 關鍵詞: 壓頻比、基準電壓、基準頻率。 一、前 言: 隨著變頻調速技術的發展,變頻器調速已成為交流調速的 ...… 查看全部問答∨ |
|
新手用ICC編程的時候,經常會出現一些錯誤,現在將常見的錯誤報告整理如下。這里的一些錯誤是我為了展示而故意制造的,歡迎你提供你遇到的錯誤。排名不分先后: 一、正常編譯通過CODE: C:\icc\bin\imakew -f main.mak icc ...… 查看全部問答∨ |
|
我用的是UBUNTU 9.10,已經在電腦上建立好了編譯環境,開發板上也按說明燒好了內核和BOOTLOADER了的,下面是串口終端的打印結果: U-Boot 1.2.0-utulinux_s3c2440_bootloader (Oct 7 2008 - 23:05:31) DRAM: 64 MB Flash: ...… 查看全部問答∨ |
|
RT,可以舉些例子么? 偶一直認為芯片想拉低一個釋放的總線電平時,就是內部一個三級管導通使總線接地,這樣最多有個0.幾V的導通飽和電壓吧,但為什么有時最低只能 拉到1、2V那么高?… 查看全部問答∨ |
|
目標:想要實現USB設備拔插的模擬。也就是說,物理上USB設備并沒有拔出再插入的動作,但是在邏輯上,USB設備掉了,然后又重新連接上了。現在這個功能基本能實現,但是不穩定,容易出現USB設備掉。 我自己寫了一個小的字符驅動(usbPortdisplay.c) ...… 查看全部問答∨ |
把c換成匯編(asm)程序,謝謝!在附件中各位兄弟姐妹,在下沒學過C,但是呢,又急需這份程序,謝謝啊,挺急用的,能幫幫忙不?謝謝! [ 本帖最后由 qwert99 于 2010-12-12 11:45 編輯 ]… 查看全部問答∨ |
設計資源 培訓 開發板 精華推薦
- 高通攜手中國“汽車朋友圈”亮相2025上海車展: 加速駕駛輔助普惠,推動艙駕創新升級
- 工業市場正在快速回暖,德州儀器如何重塑電力電子市場?
- 特斯拉:美國交付的Model Y/3電池包已實現100%美國生產
- 地平線與博世深化合作,攜手為多家車企提供輔助駕駛產品
- 強化中國市場戰略布局,德州儀器正靈活應對全球關稅挑戰
- Molex莫仕通過本地合作和創新加強支持中國汽車行業
- 貿澤開售Texas Instruments適用于高分辨率AR HUD的 全新DLP4620S-Q1 0.46"汽車數字微鏡器件
- ROHM推出高功率密度的新型SiC模塊,將實現車載充電器小型化!
- 用上車規級UFS 4.0,讓出行變得高效且可靠
- 車載測試技術解析:聚焦高帶寬、多通道同步采集與協議分析