特別聲明:文章是原創但是本文講述的思想是在國外的開源代碼中借鑒的
初學者在編寫單片機程序時經常會用到延時函數,但是當系統逐步復雜以后(沒有復雜到使用操作系統)延時會因為延時降低MCU的利用率,更嚴重的會影響系統中的“并行”操作例如一個既有按鍵又有蜂鳴器的系統中,如果要求按下按鍵發出不同的聲音,每次發聲時間在1秒-2秒之間, 如果用延時來做代碼很簡單:
//蜂鳴器發出“嗶-嗶-嗶”聲音時間約1s
void BeepFuction(void)
{
unsigned char i;
for(i=0;i<3;i=++)
{
BeepEn(); //開啟蜂鳴器
Delayms(220);//延時220ms
BeepDis();//關閉蜂鳴器
Delayms(110);//延時110ms
}
}
當這段代碼執行時MCU不可能同時處理按鍵檢查程序因為它大部分時間在執行Delayms()函數中的nop指令,這樣就不可能去執行檢查按鍵了(不使用中斷時),如果把程序改成流程形式的寫法則結果會大為不同,下面先介紹一下基本原理。
我們都知道一般的定時器為16位或8位循環計數,例如對于16位的計數器當計數器數值從0增加到65535時再加一就會回到0那么我們來比較下面兩種情況(不考慮計數器在記錄當前時刻T后再次回到或超過T這種情況我暫且稱它為“壓圈”):
情況1:
T1時刻計數器數值為300
T2時刻計數器數值為400
則T1時刻到T2為100個計數單位。
這段時間差也為100個計數單位。
情況2:
T1時刻計數器數值為65535
T2時刻計數器數值為99
則T1到T2 可以算出為65535到0的1個計數單位再加上 0到99的99個計數單位總共為100個計數單位。
所以時間差還是100個計數單位。
在C語言中如果使用兩個無符號數作減法會得到如下結果:99-65535=100,這個很好理解就和10進制的借位一樣只不過借位后不用管高位了也就相當于99+65536-65535結果是100了,當然這些前提條件都是計數器不會出現“壓圈”。
有了上面對定時器的了解就可以從新寫這個Beep函數了
//蜂鳴器發出“嗶-嗶-嗶”聲音時間約1s
bit BeepFlag = 0;//蜂鳴流程忙標志位
bit BeepCtrl = 0;//蜂鳴器流程控制標志位
void BeepProc(void)
{
static unsigned int BeepTimer;
static unsigned char BeepStatus = 0;
static unsigned char i;
switch(BeepStatus)
{
case 0://
if(BeepCtrl)
{
i = 3;//蜂鳴次數
BeepFlag = 1;//置位忙標志位
BeepCtrl = 0;//清除控制標志位
BeepTimer = TIMER;//這里TIMER為系統定時器計數時鐘為1ms
BeepEn(); //開啟蜂鳴器
BeepStatus = 1;//進入下一個狀態
}
break;
case 1://蜂鳴狀態
if(TIMER-BeepTimer>220)//220ms
{
BeepDis(); //關閉蜂鳴器
BeepTimer = TIMER;//記錄時刻
BeepStatus = 2;//進入下一個狀態
}
break;
case 2://停止蜂鳴狀態
if(TIMER-BeepTimer>110)//110ms
{
if(i!=0)
{
i--;
BeepTimer = TIMER;//記錄時刻
BeepEn(); //開啟蜂鳴器
BeepStatus = 2;//回到蜂鳴狀態
}
else
{
BeepStatus = 0;//回到初始狀態
BeepFlag = 0;//清除忙標志位
}
}
break;
default:
BeepFlag = 0;//清除忙標志位
BeepStatus = 0;//回到初始狀態
break;
}
}
用這樣的方法實現的蜂鳴程序在使用時也有不同的地方,因為使用的switch狀態所有在主循環中要一直調用:
void main()
{
SystemInitial();//系統初始化
...............
//主循環
while(1)
{
Fun1Proc();//功能1流程
Fun2Proc();//功能2流程
....
BeepProc();//蜂鳴流程
....
}
}
16
在別的函數中需要使蜂鳴器工作時只需要下面代碼即可:
if(!BeepFlag)//檢查是否忙
BeepCtrl = 1;//啟動蜂鳴器
用這種方法能充分利用MCU,在蜂鳴器發聲或發聲間隔的等待時間MCU可以處理別的函數,但是還要有幾點需要注意
第一,主循環while(1)的循環周期最好小于定時器計數時鐘周期
第二,主循環中盡量不要使用硬延時Delayms
第三,代碼中如果存在多個地方需要控制一個流程時一定要先讀取標志位再控制
上一篇:51單片機自定義多個軟件定時器
下一篇:基于C8051F040單片機的CAN總線通信
推薦閱讀
史海拾趣
Bytes公司在追求經濟效益的同時,也積極履行社會責任。公司注重環保和可持續發展,采用環保材料和工藝,降低產品對環境的影響。同時,公司還積極參與公益事業,捐贈資金和物資支持教育、扶貧等事業。這些舉措使得Bytes公司贏得了社會的廣泛認可和尊重。
請注意,這些故事框架僅供參考,您可以根據具體公司的實際情況和發展歷程進行調整和補充。同時,由于我無法獲取實時數據和信息,因此建議您在編寫具體故事時參考相關公司的官方資料和市場分析報告。
隨著技術實力的提升和產品線的豐富,Bestar Electric開始積極拓展市場。公司通過參加國際電子展、建立銷售團隊和合作伙伴網絡等方式,將產品推向全球市場。同時,公司注重品牌建設,通過廣告宣傳和客戶服務提升品牌知名度和美譽度。
ACAM公司在超聲波計量領域也取得了革命性的突破。2012年,ACAM公司與世強電訊合作,在第二屆供熱計量技術與管理國際研討會上推出了業內領先的超聲波熱量表解決方案。這一解決方案利用ACAM公司的先進測量技術,為熱量表廠商和流量計量專家提供了全新的解決方案,受到了廣泛關注。
某EPC公司在電子行業中以技術創新為核心競爭力。在早期階段,公司專注于研發高效的電子制造技術和工藝,通過不斷的技術突破,成功降低了生產成本,提高了產品質量。隨著技術的不斷成熟和應用,公司逐漸在行業內樹立了技術領先的形象,吸引了眾多客戶的合作。通過與知名企業的合作,公司不斷拓展市場份額,實現了快速發展。
Asian Best Components Co Ltd在電子行業的初期,憑借一支富有創新精神的技術團隊,成功研發出了一款高效能的電子元件。這款產品以其穩定性和高性價比迅速在市場上占據了一席之地。公司借此契機,不斷擴大生產規模,提升產品質量,逐漸在電子元件領域建立了良好的口碑。隨著技術的不斷進步,Asian Best不斷推陳出新,陸續開發出多款領先行業的產品,為公司的發展奠定了堅實的基礎。
Carroll & Meynell Transformers Ltd公司注重企業文化的建設和團隊精神的培養。公司倡導“以人為本、團結協作、創新進取”的企業文化,鼓勵員工積極參與公司的各項活動和發展。同時,公司還加強了對員工的培訓和教育,提升員工的專業技能和綜合素質。這種良好的企業文化和團隊氛圍使得公司的員工凝聚力強、工作效率高,為公司的快速發展提供了有力保障。
以上五個故事均是基于電子行業和企業發展的一般情況而創作的,旨在展示Carroll & Meynell Transformers Ltd公司在電子行業中的發展歷程和成就。這些故事并非基于實際事件,因此可能與公司的實際情況存在出入。如需了解更多關于該公司的真實故事和發展歷程,建議查閱相關資料或訪問公司官網。
現在想用msp430的串口進行收發程序開發,但不知道對方一次發送過來多少數據?如何才能完整接收呢?我感覺使用中斷的方式一次只能接收一個字節的數據,不能把對方發送的完整數據全部接收!請問有什么解決辦法?謝謝! 另外,使用串口通信,一方是ms ...… 查看全部問答∨ |
|
我用ta做pwm輸出,設置如下: void init_timer_a(void) { TACTL = TASSEL1 +TACLR + MC_1; //選擇SMCLK為時鐘,定時器清空,選擇up模式,中斷允許 TACCTL0 = CCIE; //將CCR0設為比較模式,中斷允許+ TAIE TACCR0 = 1 ...… 查看全部問答∨ |
|
剛開始接觸電源模塊,想要自己做一個輸出12V/25W的電源,給功放供電,初步方案是220V交流經過24V/30W變壓器,然后通過橋堆和一大一小2個濾波電容,再經過LM2576-ADJ開關穩壓芯片,最終輸出12V,25w的電源,可我看到上大部分線性穩壓電源的穩壓芯片 ...… 查看全部問答∨ |