2014-10-27 62 views
0

硬件:Arduino的烏諾與ATMEGA328P生成1秒延時定時器使用Arduino的上野與ATMEGA328P(C語言)

軟件:愛特梅爾Studio的1153年6月2日,Arduino的1.0.6

計算需要1秒

  • ATMEGA328P的時鐘頻率= 16M赫茲01循環
  • 預分頻器CLK時鐘頻率/ 1024 = 16M/1024 = 15625赫茲
  • 時鐘週期預分頻器CLK/1024 =(15625)^ - 1 = 6.4 * 10^-5S
  • 週期1S = 1/6.4 * 10^-5 = 15625個週期
  • 所需1S = 15625循環 - 1 = 15624個週期= 0x3D08

我的代碼

OCR1AH = 0x3D;      //Load higher byte of 15624 into output compare register 
OCR1AL = 0x08;      //Load lower byte of 15624 into output compare register 
TCCR1A = 0b00000000; 
TCCR1B = 0b00001101;    //Turn on CTC mode and prescaler of CLK/1024 
while((TIFR1 & (1<<OCF1A)) == 0); //If OCF1A is set (TCNT1 = OCR1A), break 
TCCR1A = 0; 
TCCR1B = 0;       //Stop the timer 
TIFR1 &= ~(1<<OCF1A);    //Clear OCF1A for the next time delay 

當我點擊「開始調試和休息」和「步過」上面的代碼爲函數。它總是讓我「不停地奔跑」。爲什麼?如何解決它?


謝謝您的幫助。

+0

https://github.com/dwelch67/avr_samples應該有一些二秒或多秒led指示燈... – 2014-10-27 14:30:59

+0

一個問題是,你沒有清除最後一行的'OCF1A'標誌。它應該是'TIFR1 = 1 << OCF1A;'。 – UncleO 2014-10-27 16:06:11

回答

1

您的配置看起來不錯。

當您在調試器中暫停執行您的代碼時,外設(獨立於CPU)不會停止。某些體系結構/微控制器具有額外的硬件寄存器,用於在調試器停止執行代碼時停止外設(如DMA或定時器)。無論如何,AVR不會。

如果您在仿真中運行您的代碼,您應該能夠逐步查看由指令設置的所有寄存器。我建議您關閉代碼優化以進行調試。

對於硬件調試代碼(在AVR架構的情況下),您需要額外的調試器。 Arduino提供的調試只使用運行在MPU中的代碼的軟件,在某些情況下,您不能依賴它。

無論如何,你的代碼看起來不錯。只有錯誤:將TIFR1的邏輯1寫入清除位。

您應該運行你的代碼迴路檢查,如果定時器工作:

OCR1AH = 0x3D;      //Load higher byte of 15624 into output compare register 
OCR1AL = 0x08;      //Load lower byte of 15624 into output compare register 
TCCR1A = 0b00000000; 
TCCR1B = 0b00001101;    //Turn on CTC mode and prescaler of CLK/1024 
while(1) 
{ 
    while((TIFR1 & (1<<OCF1A)) == 0); //If OCF1A is set (TCNT1 = OCR1A), break 
    //Blink LED here 
    TIFR1 = (1<<OCF1A);    //Writing logic 1 to that register clears it 
} 

當然,如果你不想運行循環代碼,只是將其刪除。該代碼僅用於測試目的。

編輯:

採取看看Atmega328數據表:http://www.atmel.com/Images/doc8161.pdf,頁139-140,註冊TIFR1,位1 - OCF1A:

OCF1A由硬件執行相應的中斷清零。 OCF1A也可以通過向該位寫入一個邏輯來清除。

某些位的硬件寄存器(通常,這僅可以通過用戶,通過從未用戶設定清零)可以通過寫入1.硬件與寄存器連接被清除設定0到比特值時寫入1到它。寫0被忽略,不影響寄存器/位值。這可以防止從軟件設置位,只有硬件(該情況 - 計時器)才能設置位。考慮一下 - 代碼中沒有意義設置輸出比較寄存器。其他操作(讀取值,清除位)有意義並且被允許。

還有一些寄存器只能被寫入而不能讀取(即讀取總是返回相同的值)。

當使用硬件寄存器時,請務必檢查數據表中的數據表如何設置/清零位。

+0

爲什麼我必須將OCF1A設置爲1而不是0來清零該位?你能解釋一下嗎?謝謝。 – Casper 2014-10-30 17:20:53

+0

'TIFR1 | =(1 << OCF1A);'清除所有標誌,而不僅僅是'OCF1A'。它應該是'TIFR1 =(1 << OCF1A);'。 – UncleO 2014-10-31 23:12:18

+0

@UncleO:謝謝 - 固定代碼併爲清除位添加解釋。 – Mazi 2014-11-02 11:14:43