|
端口寄存器允許在Arduino板上更低級(jí)和更快地操縱微控制器的i / o引腳。Arduino板上使用的芯片(ATmega8和ATmega168)有三個(gè)端口: - B(數(shù)字引腳8到13)
- C(模擬輸入引腳)
- D(數(shù)字引腳0到7)
每個(gè)端口由三個(gè)寄存器控制,這三個(gè)寄存器也是arduino語言中定義的變量。DDR寄存器確定引腳是INPUT還是OUTPUT。PORT寄存器控制引腳是高電平還是低電平,PIN寄存器通過pinMode()讀取設(shè)置為輸入的INPUT引腳的狀態(tài)。ATmega8 和ATmega168芯片的地圖顯示了端口。較新的Atmega328p芯片完全遵循Atmega168的引腳排列。 DDR和PORT寄存器可以寫入和讀取。PIN寄存器對(duì)應(yīng)于輸入狀態(tài),只能讀取。 PORTD映射到Arduino數(shù)字引腳0到7 DDRD - 端口D數(shù)據(jù)方向寄存器 - 讀/寫 PORTD - 端口D數(shù)據(jù)寄存器 - 讀/寫 PIND - 端口D輸入引腳寄存器 - 只讀
PORTB映射到Arduino數(shù)字引腳8到13兩個(gè)高位(6和7)映射到晶體引腳,不可用 DDRB - 端口B數(shù)據(jù)方向寄存器 - 讀/寫 PORTB - 端口B數(shù)據(jù)寄存器 - 讀/寫 PINB - 端口B輸入引腳寄存器 - 只讀
PORTC映射到Arduino模擬引腳0到5.引腳6和7只能在Arduino Mini上訪問 DDRC - 端口C數(shù)據(jù)方向寄存器 - 讀/寫 PORTC - 端口C數(shù)據(jù)寄存器 - 讀/寫 PINC - 端口C輸入引腳寄存器 - 只讀
這些寄存器的每一位對(duì)應(yīng)一個(gè)引腳; 例如,DDRB,PORTB和PINB的低位指的是引腳PB0(數(shù)字引腳8)。有關(guān)Arduino引腳編號(hào)到端口和位的完整映射,請(qǐng)參見芯片圖:ATmega8,ATmega168。(注意,端口的某些位可用于除i / o之外的其他位;請(qǐng)注意不要更改與它們對(duì)應(yīng)的寄存器位的值。) 例子參考上面的引腳圖,PortD寄存器控制Arduino數(shù)字引腳0到7。 但是,您應(yīng)該注意,引腳0和1用于串行通信以編程和調(diào)試Arduino,因此通常應(yīng)避免更改這些引腳,除非需要串行輸入或輸出功能。請(qǐng)注意,這可能會(huì)干擾程序下載或調(diào)試。 DDRD是端口D的方向寄存器(Arduino數(shù)字引腳0-7)。該寄存器中的位控制PORTD中的引腳是否配置為輸入或輸出,例如: DDRD = B11111110; //將Arduino引腳1至7設(shè)置為輸出,將引腳0設(shè)置為輸入
DDRD = DDRD | B11111100; //這樣更安全,因?yàn)樗鼘⒁_2到7設(shè)置為輸出
//不改變引腳0和1的值,即RX和TX
//See the bitwise operators reference pages and 游樂場(chǎng)中 的比特馬斯教程
PORTD是輸出狀態(tài)的寄存器。例如; PORTD = B10101000; // sets digital pins 7,5,3 HIGH
如果使用DDRD寄存器或pinMode()將引腳設(shè)置為輸出,則只能在這些引腳上看到5伏電壓。 PIND是輸入寄存器變量它將同時(shí)讀取所有數(shù)字輸入引腳。 為何使用端口操作?來自Bitmath教程 一般來說,做這類事并不是一個(gè)好主意。為什么不?原因如下: - 代碼對(duì)于調(diào)試和維護(hù)來說要困難得多,并且對(duì)于其他人來說理解起來要困難得多。處理器執(zhí)行代碼只需幾微秒,但您可能需要幾個(gè)小時(shí)才能弄清楚它為什么不能正常工作并修復(fù)它!你的時(shí)間很寶貴,對(duì)嗎?但計(jì)算機(jī)的時(shí)間非常便宜,以你喂它的電費(fèi)來衡量。通常以最明顯的方式編寫代碼要好得多。
- 代碼不太便攜。如果使用digitalRead()和digitalWrite(),編寫將在所有Atmel微控制器上運(yùn)行的代碼要容易得多,而控制端口寄存器和端口寄存器在每種微控制器上都可以不同。
- 通過直接端口訪問可以更容易地導(dǎo)致意外故障。注意線DDRD = B11111110; 上面提到必須將引腳0作為輸入引腳。引腳0是串行端口上的接收線(RX)。通過將引腳0更改為輸出引腳,很容易意外地導(dǎo)致串口停止工作!現(xiàn)在當(dāng)你突然無法接收串行數(shù)據(jù)時(shí)會(huì)非常混亂,不是嗎?
所以你可能會(huì)對(duì)自己說,很好,為什么我會(huì)想要使用這些東西呢?以下是直接端口訪問的一些積極方面: - 您可能需要能夠非??焖俚卮蜷_和關(guān)閉引腳,這意味著在幾微秒內(nèi)。如果你看一下lib / targets / arduino / wiring.c中的源代碼,你會(huì)看到digitalRead()和digitalWrite()都是大約十幾行代碼,它們被編譯成很多機(jī)器指令。每個(gè)機(jī)器指令需要一個(gè)16MHz的時(shí)鐘周期,這可以累積在時(shí)間敏感的應(yīng)用中。直接端口訪問可以在更少的時(shí)鐘周期內(nèi)完成相同的工作。
- 有時(shí)您可能需要在同一時(shí)間設(shè)置多個(gè)輸出引腳。調(diào)用digitalWrite(10,HIGH); 接著是digitalWrite(11,HIGH); 這將導(dǎo)致引腳10在引腳11之前幾微秒變?yōu)楦唠娖?,這可能會(huì)混淆您連接的某些對(duì)時(shí)間敏感的外部數(shù)字電路。或者,您可以使用PORTB | = B1100將兩個(gè)引腳設(shè)置為完全相同的時(shí)刻;
- 如果程序內(nèi)存不足,可以使用這些技巧使代碼更小。它需要更少的編譯代碼字節(jié)來同時(shí)通過端口寄存器同時(shí)寫入一堆硬件引腳,而不是使用for循環(huán)分別設(shè)置每個(gè)引腳。在某些情況下,這可能會(huì)使您的程序適合閃存或不兼容!
|