99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>電子資料>如何設(shè)置基于定時(shí)器的中斷

如何設(shè)置基于定時(shí)器的中斷

2023-02-06 | zip | 0.04 MB | 次下載 | 免費(fèi)

資料介紹

描述

概括

教程介紹如何設(shè)置基于定時(shí)器的中斷。具體來(lái)說,它使用定時(shí)器比較中斷定期閃爍 LED,這與流行的 Blink sketch 使用 delay() 形成對(duì)比。編程特定于 Arduino Uno、5V Nano 3.x 和克隆中使用的 16MHz ATmega328P。

我的動(dòng)力

我有一個(gè)瘋狂的想法,即構(gòu)建一個(gè)三單元 Raspberry Pi 集群,并使用自定義 8MHz、3.3V ATMega328P(與 Arduino Uno 相同的芯片,但速度和電壓較低)在 Raspberry Pi 控制臺(tái)端口之間切換,同時(shí)還做其他有用的東西,如測(cè)量溫度和電源狀態(tài)。我的第一步是找出控制臺(tái)端口,這涉及到 SoftwareSerial 庫(kù)。

我有一個(gè) 5V Arduino Uno,而 Raspberry Pi 當(dāng)然是 3.3V。因此,為了避免燒壞我的 Pi,我剪了一根電線將軟件串行傳輸和接收引腳連接在一起,創(chuàng)建了一個(gè)環(huán)回。這個(gè)理論是合理的,無(wú)論我在傳輸引腳上發(fā)出什么,都應(yīng)該在接收引腳上返回。但是,它沒有用。由于中斷,它沒有工作。

loopback_MJMnH9MQX7.png?auto=compress%2Cformat&w=740&h=555&fit=max
簡(jiǎn)單環(huán)回(黃線)。可能會(huì)出現(xiàn)什么問題?
?

需要中斷才能知道串行數(shù)據(jù)何時(shí)進(jìn)入特定引腳,但由于關(guān)鍵時(shí)序,傳輸時(shí)中斷被禁用。這種安排使得無(wú)法同時(shí)發(fā)送和接收。不用說,這對(duì)我連接到多個(gè) Raspberry Pi 控制臺(tái)端口的想法來(lái)說不是好兆頭。

但是,從好的方面來(lái)說,它讓我對(duì) Arduino Uno 上的中斷產(chǎn)生了興趣。

從小做起

眨眼草圖。這可能是每個(gè)人的第一個(gè) Arduino 項(xiàng)目。好吧,這里再次作為復(fù)習(xí)。

#define LED 9
void setup() {
 pinMode(LED, OUTPUT);
}
void loop() {
 digitalWrite(LED, LOW);
 delay(500);
 digitalWrite(LED, HIGH);
 delay(500);
}

請(qǐng)注意熟悉的 delay() 子例程來(lái)控制打開和關(guān)閉時(shí)間。每個(gè)狀態(tài)有 500mS,LED 將以穩(wěn)定的 1Hz 脈沖。

在我的草圖中,我將引腳 9 用于 LED。這需要在引腳 9 和地之間連接一個(gè) LED 和限流電阻。我要大膽猜測(cè),如果您正在閱讀有關(guān)定時(shí)器中斷的教程,那么您已經(jīng)連接了幾個(gè) LED,我不會(huì)詳細(xì)介紹。不過,使用外部 LED 很重要,因?yàn)樯院髸?huì)同時(shí)使用內(nèi)置 LED 來(lái)比較中斷閃爍和 delay() 閃爍。

如果你想做的只是對(duì)著閃光燈發(fā)出嗚嗚聲,那么這幅素描就很完美了。但是,如果您想同時(shí)做其他事情怎么辦?也許測(cè)量熱敏電阻兩端的電壓并計(jì)算溫度。那樣就好了。

問題是那兩個(gè) delay() 函數(shù)調(diào)用。每個(gè)人都花半秒鐘什么都不做。您可以在其中一個(gè)延遲之前或之后插入代碼。但是,如果該代碼需要足夠長(zhǎng)的時(shí)間來(lái)執(zhí)行,以至于它會(huì)錯(cuò)過眨眼的時(shí)間怎么辦?

你可以縮短延遲。也許將其設(shè)為 490 而不是 500。也許這太短了,495 是更好的選擇。在某些時(shí)候,您可能會(huì)舉手說,“一定有更好的方法!”

有一個(gè)更好的辦法。它被稱為定時(shí)器中斷。

什么是中斷?

查看本教程標(biāo)題卡中的插圖。

pardonme_small_lq69wHHaPU.png?auto=compress%2Cformat&w=740&h=555&fit=max
還記得這些家伙嗎?
?

戴大禮帽的花花公子——他是個(gè)干擾者。你幾乎可以想象他在一個(gè)古老的維多利亞火車站附近閑逛,說著類似“對(duì)不起,我的好先生們”之類的話。

現(xiàn)在長(zhǎng)凳上的三位先生——他們是您的 loop() 函數(shù)中的進(jìn)程。左邊那個(gè)坐下,當(dāng) LED 熄滅時(shí),他就是 LED。下一個(gè)人是 LED 燈。第三個(gè)人,那個(gè)戴著帽子遮住眼睛的人,他一定是延遲功能。

“請(qǐng)?jiān)?,我的好先生們,”打斷說。突然,他引起了替補(bǔ)席上三個(gè)人的注意。就連昏昏欲睡的家伙也豎起了耳朵。不管他們之前在做什么,他們都停下來(lái)讓戴大禮帽的花花公子上臺(tái)。

這正是中斷所做的。它會(huì)停止 loop() 的正常執(zhí)行并運(yùn)行它自己的代碼一段時(shí)間。

簡(jiǎn)潔重要

如果戴禮帽的人是個(gè)體面的人,他會(huì)保持簡(jiǎn)短的打斷。他可能會(huì)說一些重要的話,比如,‘老兄,你的火車就要出發(fā)了,’然后就上路了。或者他可能會(huì)一連幾個(gè)小時(shí)在龐氏騙局的最新趨勢(shì)上喋喋不休地自以為是。

前者是好中斷的例子,后者是壞中斷。當(dāng)中斷花費(fèi)太多時(shí)間時(shí),它會(huì)使所有其他進(jìn)程等待。中斷應(yīng)該只做絕對(duì)必要的事情,并將控制權(quán)交還給主循環(huán)。

在 LED 閃爍的情況下,最少量的處理歸結(jié)為改變輸出引腳的狀態(tài),以便連接的 LED 打開或關(guān)閉。因此,在我們繼續(xù)之前,請(qǐng)看一下以下代碼行:

PORTB ^= B00100000;  // Toggle bit 5, which maps to pin13.

它有什么作用?好吧,閱讀評(píng)論,它說它切換了一個(gè)映射到引腳的位。該引腳恰好是引腳 13,這是 Arduino Uno 上的內(nèi)置 LED。PORTB是 Uno 上控制引腳 8 到 13 的寄存器位 0 控制引腳 8,位 1 控制引腳 9,依此類推。第 5 位控制引腳 13,即內(nèi)置 LED。

^=運(yùn)算符是一個(gè)異或 (XOR)。XOR 可用于反轉(zhuǎn)操作數(shù)之一為 1 的任何位。XOR 就像一個(gè)帶有扭曲的常規(guī) OR。兩個(gè)零位作為輸入給出一個(gè)零作為輸出。零和一或一和零給出一的輸出。但是,這里有一個(gè)轉(zhuǎn)折……如果你有一個(gè)和一個(gè),結(jié)果是零。

這就是為什么上面的代碼行只會(huì)翻轉(zhuǎn) one 所在的位。如果寄存器 PORTB 的第 5 位的當(dāng)前值為零,則該零與二進(jìn)制值第 5 位中的 1 進(jìn)行異或后B00100000結(jié)果為 1。如果 PORTB 的第 5 位是 1,則 1 與 1 的異或結(jié)果為 0。每次應(yīng)用 XOR 時(shí),該位都會(huì)翻轉(zhuǎn)。PORTB 中的任何其他位將與零進(jìn)行異或,從而返回原始值并且不受影響。

使用 digitalRead() 確定引腳的當(dāng)前狀態(tài)然后使用 digitalWrite() 應(yīng)用相反狀態(tài)的練習(xí)現(xiàn)在在單個(gè) XOR 中完成。快速高效,就像任何優(yōu)秀的、正直的中斷一樣。

我被賣了,我從哪里得到一個(gè)?

有了基礎(chǔ)知識(shí),就該開始設(shè)置中斷了。這涉及兩個(gè)部分。

第一個(gè)是中斷服務(wù)程序(ISR)。它只是一個(gè)執(zhí)行位翻轉(zhuǎn)代碼的子程序。ISR() 子例程存在于 setup() 和 loop() 例程之外,它看起來(lái)像這樣:

ISR(TIMER1_COMPA_vect)
{
  PORTB ^= B00100000;  // Toggle bit 5, which maps to pin13.
}

在最簡(jiǎn)單的形式中,ISR() 接受一個(gè)參數(shù)。該參數(shù)TIMER1_COMPA_vect是中斷的向量(或源)。使用像 TIMER1_COMPA_vect 這樣的名稱,您可能會(huì)猜到它與 timer1 有關(guān),并且可能正在進(jìn)行一些比較。你是對(duì)的。

但我們還沒有完成。到目前為止,我們所做的只是告訴 ATmega328P 當(dāng)定時(shí)器比較中斷發(fā)生時(shí)該做什么。我們實(shí)際上還沒有設(shè)置任何定時(shí)器來(lái)產(chǎn)生中斷,所以什么都不會(huì)發(fā)生。

設(shè)置的第二部分涉及告訴計(jì)時(shí)器何時(shí)引發(fā)中斷。這涉及更多的控制寄存器和二進(jìn)制值,但如果你已經(jīng)做到了這一點(diǎn),你會(huì)沒事的。這是代碼:

cli();
TCCR1A = B00000000;
TCCR1B = B00001100;
TIMSK1 = B00000010;
OCR1A = 31250;
sei();

cli() 和 sei() 指令是相關(guān)的。第一個(gè)清除中斷標(biāo)志,第二個(gè)設(shè)置它。中斷標(biāo)志允許中斷發(fā)生。使用 cli() 忽略所有中斷,本質(zhì)上它是一個(gè)很大的請(qǐng)勿打擾標(biāo)志。sei() 做相反的事情并允許中斷。

最初使用 cli() 阻止中斷的原因是因?yàn)樾枰O(shè)置四個(gè)寄存器并且所有四個(gè)都是相關(guān)的。在中斷開始滾動(dòng)之前只設(shè)置一兩個(gè)將導(dǎo)致一些不可預(yù)測(cè)的行為。最好在設(shè)置過程中熄滅請(qǐng)勿打擾標(biāo)志。

寄存器(TCCR1A、TCCR1B 和 TIMSK1)是指示 timer1 如何工作的標(biāo)志的集合。在代碼中,所有設(shè)置都使用二進(jìn)制值,以便更容易查看正在設(shè)置的位以及它是 1 還是 0。

OCR1A 是要與定時(shí)器的當(dāng)前計(jì)數(shù)進(jìn)行比較的值。它以十進(jìn)制表示法顯示,以便于閱讀。按照配置,計(jì)時(shí)器將從 0 開始并向上計(jì)數(shù)。當(dāng)它達(dá)到存儲(chǔ)在 OCR1A 中的值時(shí),就會(huì)發(fā)生一些事情。如果您猜到某事是中斷,您將贏得獎(jiǎng)品。

定時(shí)器計(jì)數(shù)的速度以及當(dāng)它達(dá)到 OCR1A 中的值時(shí)它做什么由 TCCR1A 和 TCCR1B 中的標(biāo)志決定。這些定時(shí)器控制寄存器在 ATmega328P 數(shù)據(jù)表的第 15.1 節(jié)中有詳細(xì)說明。但這里有一個(gè)簡(jiǎn)短的描述:

  • TCCR1A = B00000000是最簡(jiǎn)單的。它設(shè)置全零,或所謂的“正?!蹦J?。
  • TCCR1B = B00001100指示計(jì)數(shù)器用位 0..2 的值計(jì)數(shù)的速度。在這種情況下,那些較低位中的二進(jìn)制 100 會(huì)將預(yù)分頻器設(shè)置為 256(稍后會(huì)詳細(xì)介紹)。
  • 還包括在 中TCCR1B = B00001100,第 3 位中的 1 表示當(dāng)達(dá)到 OCR1A 中存儲(chǔ)的值時(shí),計(jì)數(shù)器將重置為零。
  • TIMSK1 = B00000010確保當(dāng)計(jì)數(shù)器達(dá)到存儲(chǔ)在 OCR1A 中的值時(shí)將產(chǎn)生中斷。

最后設(shè)置的寄存器是OCR1A,比較寄存器,但是為什么設(shè)置為31250呢?答案在于以下等式:

interrupts_per_second = clock_speed / 預(yù)分頻器 / OCR1A

也可以表示為

OCR1A = clock_speed / 預(yù)分頻器 / interrupts_per_second

使用 16MHz Arduino Uno 和預(yù)分頻器值為 256(記住 TCCRB1 的最低 3 位設(shè)置該值),等式變得更簡(jiǎn)單:

OCR1A = 16MHz / 256 / interrupts_per_second
OCR1A = 62500 / interrupts_per_second

我想每秒切換 LED 兩次以獲得 1Hz 閃爍率,因此我將 62500 除以 2 得到 31250。這就是 OCR1A 值的來(lái)源。

讓我們眨眼!

到目前為止,這都是一堆理論。讓我們將所有代碼放在草圖中并證明它確實(shí)有效。這是它的樣子:

#define LED 9
void setup() {
 pinMode(LED_BUILTIN, OUTPUT);
 pinMode(LED, OUTPUT);
 cli();
 TCCR1A = B00000000;
 TCCR1B = B00001100;
 TIMSK1 = B00000010;
 OCR1A = 31250;
 sei();
}
void loop() {
 digitalWrite(LED, LOW);
 delay(500);
 digitalWrite(LED, HIGH);
 delay(500);
}
ISR(TIMER1_COMPA_vect)
{
 PORTB ^= B00100000;
}

請(qǐng)注意 delay() 閃爍的舊方法如何仍然包括在內(nèi),但現(xiàn)在草圖的新中斷代碼部分也是如此。這就是使用兩個(gè) LED 的原因。外部 LED(引腳 9)將由 loop() 內(nèi)的 digitalWrite() 和 delay() 控制,而內(nèi)置 LED(引腳 13)由 ISR() 和 setup() 內(nèi)的配置控制.

將草圖加載到 Uno,您應(yīng)該會(huì)看到兩個(gè) LED 燈同時(shí)閃爍。

現(xiàn)在,做一些改變。嘗試以下任何或所有操作:

  • 將 OCR1A 的值加倍,使其成為 62500。
  • 將預(yù)分頻器位的值設(shè)置為 64 而不是 256。 (TCCR1B = B00001101)
  • 將兩個(gè) delay() 值更改為 250 而不是 500。
  • 刪除 loop() 中的所有內(nèi)容。

預(yù)測(cè)每種情況下會(huì)發(fā)生什么,然后上傳草圖以查看您是否正確。在您思考的同時(shí),想象一下使用 8MHz 時(shí)鐘晶體代替標(biāo)準(zhǔn) 16MHz 的 Arduino Uno 會(huì)產(chǎn)生什么效果。

作為最后的練習(xí),這個(gè)練習(xí)需要一些時(shí)間,讓原始草圖運(yùn)行幾個(gè)小時(shí)甚至一整夜,以查看對(duì) LED 同步的影響。(劇透:它們將明顯不同步。)想出一些關(guān)于為什么會(huì)發(fā)生這種情況的理論。哪個(gè)LED的時(shí)序更準(zhǔn)確?

下一步

一開始,閃爍的 LED 很有趣,但中斷可以用于更多用途。例如,有些中斷可以由輸入引腳的變化觸發(fā)。現(xiàn)在您已經(jīng)知道如何編寫用于打開或關(guān)閉 LED 的中斷服務(wù)例程,請(qǐng)嘗試使用分配給輸入引腳的按鈕而不是定時(shí)器來(lái)觸發(fā)它。

作為介紹,本教程僅展示了一種在 ATmega328p 上配置中斷的方法。還有更高級(jí)別的函數(shù),如:attachInterrupt() 和 detachInterrupt,它們涵蓋更廣泛的 Arduino 模型并處理細(xì)節(jié),因此您不一定需要閱讀數(shù)據(jù)表和設(shè)置寄存器位。

無(wú)論您打算在哪里學(xué)習(xí)新知識(shí),了解中斷的工作原理都將使您能夠構(gòu)建更好、更高效的草圖。因此,放棄 delay() 并開始使用更多中斷。


下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評(píng)論

查看更多

下載排行

本周

  1. 1山景DSP芯片AP8248A2數(shù)據(jù)手冊(cè)
  2. 1.06 MB  |  532次下載  |  免費(fèi)
  3. 2RK3399完整板原理圖(支持平板,盒子VR)
  4. 3.28 MB  |  339次下載  |  免費(fèi)
  5. 3TC358743XBG評(píng)估板參考手冊(cè)
  6. 1.36 MB  |  330次下載  |  免費(fèi)
  7. 4DFM軟件使用教程
  8. 0.84 MB  |  295次下載  |  免費(fèi)
  9. 5元宇宙深度解析—未來(lái)的未來(lái)-風(fēng)口還是泡沫
  10. 6.40 MB  |  227次下載  |  免費(fèi)
  11. 6迪文DGUS開發(fā)指南
  12. 31.67 MB  |  194次下載  |  免費(fèi)
  13. 7元宇宙底層硬件系列報(bào)告
  14. 13.42 MB  |  182次下載  |  免費(fèi)
  15. 8FP5207XR-G1中文應(yīng)用手冊(cè)
  16. 1.09 MB  |  178次下載  |  免費(fèi)

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費(fèi)
  3. 2555集成電路應(yīng)用800例(新編版)
  4. 0.00 MB  |  33566次下載  |  免費(fèi)
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費(fèi)
  7. 4開關(guān)電源設(shè)計(jì)實(shí)例指南
  8. 未知  |  21549次下載  |  免費(fèi)
  9. 5電氣工程師手冊(cè)免費(fèi)下載(新編第二版pdf電子書)
  10. 0.00 MB  |  15349次下載  |  免費(fèi)
  11. 6數(shù)字電路基礎(chǔ)pdf(下載)
  12. 未知  |  13750次下載  |  免費(fèi)
  13. 7電子制作實(shí)例集錦 下載
  14. 未知  |  8113次下載  |  免費(fèi)
  15. 8《LED驅(qū)動(dòng)電路設(shè)計(jì)》 溫德爾著
  16. 0.00 MB  |  6656次下載  |  免費(fèi)

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費(fèi)
  3. 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
  4. 78.1 MB  |  537798次下載  |  免費(fèi)
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420027次下載  |  免費(fèi)
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費(fèi)
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費(fèi)
  11. 6電路仿真軟件multisim 10.0免費(fèi)下載
  12. 340992  |  191187次下載  |  免費(fèi)
  13. 7十天學(xué)會(huì)AVR單片機(jī)與C語(yǔ)言視頻教程 下載
  14. 158M  |  183279次下載  |  免費(fèi)
  15. 8proe5.0野火版下載(中文版免費(fèi)下載)
  16. 未知  |  138040次下載  |  免費(fèi)