Arduino Ports and Register
心血來潮看了一下Arduino底層對pin腳的控制,整理了一下並且分為兩部分:第一部分:Arduino內部pin腳的port以及register的編號,並且如何使用這些register對腳位進行控制
第二部分:使用最底層的avr-libc進行pinMode、digitalWrite函數的改寫練習,發現使用avr-libc可以有效降低script的大小
Arduino UNO R3版子所用的Atmega328晶片有三個8-bit的PORTs,分別為:
- B (digital pin 8 to 13)
- C (analog input pins)
- D (digital pin 0 to 7)
所以位於PortB的Digital Pin 8可以說是PB0,位於PortC的Analog Pin 2也可以說是PC2,而在之後要介紹的AVR-GCC中使用的便是PB0、PC2這種腳位編號方式。
另外在晶片內是透過暫存器(register)來對腳位進行設定,對於Arduino這種AVR晶片來說,每個Port都受三個暫存器控制,分別是(x可以用B, C, D代替):
- DDRx register:決定腳位是INPUT或是OUTPUT,似pinMode()
- PORTx register:控制腳位輸出訊號為HIGH或為LOW,似digitalWrite()
- PINx register:存有腳位輸入的訊號,似analogRead()
表1. Port Register bit所控制的腳位對應表
PORTx、PINx與腳位的對應都可以參考表1。關於Arduino UNO Ports and Registers,在官網上也有一些說明[2]。
Getting Started with AVR-GCC
接下來要實作將Arduino原本的程式碼改以AVR-GCC函數撰寫,下列程式碼為Arduino自帶的blink範例程式,讓位於Pin 13上的LED兩秒一次的頻率閃爍:由表1可知D13是由DDRB的bit 5(PB5)來控制,所以要用(1 << 5)做為位元遮罩(bit mask),來對特定位元進行操作。DDRx暫存器內,設定1為OUTPUT,而0是代表INPUT;PORTx暫存器內,設定1為輸出HIGH,而0為LOW。改寫後的程式碼如下:
在編譯後可以發現,原本範例的程式碼的binary sketch檔案大小(如圖2)為1082位元組,而改用AVR-GCC程式碼後的binary sketch則為680位元組,減少了將近40%的大小(如圖3)。
使用_BV()巨集修改程式
在C語言中,我們可以使用位元運算子(bit operators)處理位元的運算(bitwise operation),範例如下:在avr-libc中有_BV()巨集,透過輸入一個數值參數便可以轉成適當的位元遮罩,另外BV為bit value的縮寫。_BV()巨集的定義為:
在使用_BV()巨集時要include <avr/io.h>這支library[6],所以上面的範例程式碼可以改寫成下面這樣:
而在同時處理多個非連續位元的運算時,使用_BV()巨集可以讓程式碼保持簡單,程式碼比較如下:
最後我們可以將avr-libc中的_BV()巨集已及_delay_ms()函數替換剛剛以AVR-GCC改寫的blink範例,讓程式碼更清楚也更輕量:
參考資料:
[1] Pighixxx. Arduino UNI Pinout Diagram.
Available from: http://forum.arduino.cc/index.php/topic,146315.0.html
[2] Arduino.cc. Port Registers.
Available from: http://www.arduino.cc/en/Reference/PortManipulation
Available from: http://www.arduino.cc/en/Reference/PortManipulation
[3] Cooper Maa. 2.1) Blink part 1.
Available from: http://coopermaa2nd.blogspot.tw/2011/04/21-blink-part-1.html
Available from: http://coopermaa2nd.blogspot.tw/2011/04/21-blink-part-1.html
[4] arduino吧. Arduino 下使用 avr gcc.
Available from: http://tieba.baidu.com/p/1292575395
Available from: http://tieba.baidu.com/p/1292575395
[5] Cooper Maa. _BV() 巨集介紹.
Available from: http://coopermaa2nd.blogspot.tw/2011/04/bv.html
Available from: http://coopermaa2nd.blogspot.tw/2011/04/bv.html
[6] Atmel. Macro _BV.
Available from: http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__sfr_1ga11643f271076024c395a93800b3d9546.html
Available from: http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__sfr_1ga11643f271076024c395a93800b3d9546.html
[7] Garretlab. pinMode. Available from: http://garretlab.web.fc2.com/en/arduino/inside/arduino/wiring_digital.c/pinMode.html
Comments
Post a Comment