2020-02-27

燒錄 Bootloader 到 ATmega328P* 並獨立運作

最近購買了 1塊 ATmega328P-U 就是 Arduino UNO Rev3 的 核心
但在下嘗試上載 Sketch 到發現卻出現錯誤,究竟是甚麼原因?

在下為了測試這塊 ATmega328P-U ,網上建議最簡單的方法,就是將 ATmega328P* 安裝到 Arduino UNO Rev3
在下便將原來 Arduino UNO Rev3 上的 ATmega328P-PU 卸除,並安裝 ATmega328P-U 到 Arduino UNO Rev3

見下文
但在下發現當上載測試用的 Sketch 到 Arduino 卻出現錯誤
翻查資料估計是這塊 ATmega328P-U 是沒有載入 Bootloader ,需要先將 Bootloader 燒錄到 ATmega328P-U 才能上載 Sketch


外觀

見下文
見下文
ATmel 的 ATmega328P-U 晶片 的 正面

見下文
ATmel 的 ATmega328P-U 晶片 的 背面

引腳
使用 雙列直插封裝 (Dual In-line Package (DIP))ATmega328P* 共有 28支引腳
2827262524232221201918171615
用途A5A4A3A2A1A0GNDAREFAVCCD13D12D11D10D9
RSTD0/RXD1/TXD2D3D4VCCGNDC0C1D5D6D7D8
1234567891011121314

編號引腳方向用途
1RST輸入重新啟動
當訊號 為 低電壓 時會 重新啟動
2D0/RX輸入/輸出第0 數碼訊號
接收數據 (序列通訊用途)
PORTD0
3D1/TX輸入/輸出第1 數碼訊號
送出數據 (序列通訊用途)
PORTD1
4D2輸入/輸出第2 數碼訊號
PORTD2
5D3輸入/輸出第3 數碼訊號
支援 脈衝寬度調變 輸出 10位元訊號
PORTD3
6D4輸入/輸出第4 數碼訊號
PORTD4
7VCC電源 (接受 1.8V 至 5.5V)
8GND接地
9C0第0 16KHz晶體振盪器 連接
10C1第1 16KHz晶體振盪器 連接
11D5輸入/輸出第5 數碼訊號
支援 脈衝寬度調變 輸出 10位元訊號
PORTD5
12D6輸入/輸出第6 數碼訊號
支援 脈衝寬度調變 輸出 10位元訊號
PORTD6
13D7輸入/輸出第7 數碼訊號
PORTD7
14D8輸入/輸出第8 數碼訊號
PORTB0
15D9輸入/輸出第9 數碼訊號
支援 脈衝寬度調變 輸出 10位元訊號
PORTB1
16D10輸入/輸出第10 數碼訊號
支援 脈衝寬度調變 輸出 10位元訊號
Arduino UNO Rev3 預設 SPI SS引腳
PORTB2
17D11輸入/輸出第11 數碼訊號
支援 脈衝寬度調變 輸出 10位元訊號
Arduino UNO Rev3 預設 SPI MOSI引腳
PORTB3
18D12輸入/輸出第12 數碼訊號
Arduino UNO Rev3 預設 SPI MISO引腳
PORTB4
19D13輸入/輸出第13 數碼訊號
Arduino UNO Rev3 預設 SPI SCK引腳
PORTB5
20AVCC類比電源
21AREF輸入類比參考 (接受 0V 至 5V)
改變 類比訊號最大值 的 電壓參考值
類比參考 給予 4V 時,類比訊號最大值 為 1023 = 4V
此引腳沒有接駁時 為 5V
22GND接地
23A0輸入/輸出第0 類比訊號
類比訊號 時只可以作為 輸入10位元訊號
數碼訊號 時可以作為 輸入訊號 或 輸出訊號
PORTC0
24A1輸入/輸出第1 類比訊號
類比訊號 時只可以作為 輸入10位元訊號
數碼訊號 時可以作為 輸入訊號 或 輸出訊號
PORTC1
25A2輸入/輸出第2 類比訊號
類比訊號 時只可以作為 輸入10位元訊號
數碼訊號 時可以作為 輸入訊號 或 輸出訊號
PORTC2
26A3輸入/輸出第3 類比訊號
類比訊號 時只可以作為 輸入10位元訊號
數碼訊號 時可以作為 輸入訊號 或 輸出訊號
PORTC3
27A4輸入/輸出第4 類比訊號
類比訊號 時只可以作為 輸入10位元訊號
數碼訊號 時可以作為 輸入訊號 或 輸出訊號
Arduino UNO Rev3 預設 I2C SDA引腳
PORTC4
28A5輸入/輸出第5 類比訊號
類比訊號 時只可以作為 輸入10位元訊號
數碼訊號 時可以作為 輸入訊號 或 輸出訊號
Arduino UNO Rev3 預設 I2C SCL引腳
PORTC5

線路接駁

使用 ATmega328P* Host
以 ATmega328P* Host 方式最簡單
如果閣下有 2塊 Arduino底板 而其中 1塊是 THT版本 便可以使用
將 非 ATmega328P* Host 的 Arduino 寫入 Arduino ISP (Arduino In-System Programming)
再將 Bootloader 經 Arduino 燒錄到 ATmega328P* Host 的 ATmega328P*
Arduino ISP 引腳Arduino Host 引腳
5V5V
GNDGND
D13D13
D12D12
D11D11
D10RST

見下文
Arduino UNO Rev3 THT版本 上的 28 DIP 引腳座,可以簡單安裝及卸除 ATmega328P*

見下文
安裝時, ATmega328P* 的缺口為電源插孔的反方向

見下文
使用 ATmega328P* Host 線路接駁 原型

見下文
使用 ATmega328P* Host 實際線路接駁

見下文
見下文
Arduino ISP 的 5V引腳 連接到 ATmega328P* Host 的 5V引腳
Arduino ISP 的 GND引腳 連接到 ATmega328P* Host 的 GND引腳

見下文
見下文
Arduino ISP 的 D10引腳 連接到 ATmega328P* Host 的 RST引腳

見下文
Arduino ISP 的 D13引腳 連接到 ATmega328P* Host 的 D13引腳
Arduino ISP 的 D12引腳 連接到 ATmega328P* Host 的 D12引腳
Arduino ISP 的 D11引腳 連接到 ATmega328P* Host 的 D11引腳

直接連接 ATmega328P*
如果閣下只有 1塊 Arduino底板 便需要接駁電子零件

見下文
要直接連接 ATmega328P* 寫入 Bootloader 還需要 1粒16MHz晶體振盪器 及 2粒22pF電容

Arduino ISP 引腳ATmega328P* 引腳接駁電子零件
C0C116MHz晶體振盪器
GNDC022pF電容
GNDC122pF電容
5VVCC
GNDGND
D13D13
D12D12
D11D11
D10RST

見下文
直接連接 ATmega328P* 線路接駁 原型

見下文
將 ATmega328P* 安裝到 麵包板 方便接駁

見下文
16MHz晶體振盪器 連接到 ATmega328P* C0引腳 及 C1引腳

見下文
22pF電容 連接到 ATmega328P* GND引腳 及 C1引腳

見下文
另1粒 22pF電容 連接到 ATmega328P* GND引腳 及 C0引腳

見下文
接駁方式大致與原型相似

見下文
ArduinoISP VCC引腳 連接到 ATmega328P* VCC引腳
ArduinoISP GND引腳 連接到 ATmega328P* GND引腳

見下文
ArduinoISP D10引腳 連接到 ATmega328P* RST引腳

見下文
ArduinoISP D11引腳 連接到 ATmega328P* D11引腳
ArduinoISP D12引腳 連接到 ATmega328P* D12引腳
ArduinoISP D13引腳 連接到 ATmega328P* D13引腳

寫入 Arduino ISP

見下文
開啟 Arduino IDE
選擇 檔案(File) > 例子(Examples) > ArduinoISP 的範本

見下文
工具(Tools) > Programmer 選擇 AVRISP mk II

見下文
將程式上載到 Arduino

見下文
工具(Tools) > Programmer 選擇 Arduino as ISP

見下文
工具(Tools) > Burn Bootloader

燒錄 Bootloader

見下文
將 Bootloader 燒錄到空白 ATmega328P*

見下文
選擇 檔案(File) > 例子(Examples)
選擇測試範本,例如 Basics > Blink

見下文
將範本上載到已燒錄 Bootloader 的 ATmega328P* 中

見下文
將 Bootloader 燒錄至 ATmega328P* 並上載 Blink 範本測試
如果將這塊 ATmega328P* 安裝到 Arduino , Arduino 上標記著 L 的 LED 會閃動

補充資料

數碼引腳類比引腳 寫著 PORTBPORTCPORTD
在下學習 Arduino 時,網上翻查資料經常出現 PORTD = 0x00;byte value = PORTD; 程式碼,最初在下完全不知甚麼意思
翻查 ATmega328P 的說明書都提及 PORT* 時,因此仔細翻找相關資料

PORT* 是 讀取寫入 對應引腳的訊號
例如 寫入
PORTD = 0xB4;
由於 0xB4(hex) = 10110100(bin) ,位元資料為 0 = LOW , 為 1 = HIGH
等價於
digitalWrite(7, HIGH);
digitalWrite(6, LOW);
digitalWrite(5, HIGH);
digitalWrite(4, HIGH);
digitalWrite(3, LOW);
digitalWrite(2, HIGH);
digitalWrite(1, LOW);
digitalWrite(0, LOW);

例如 讀取
byte value = PORTD;
等價於
byte value = 0;
value |= ((digitalRead(7) == LOW) ? 0 : 1) << 7;
value |= ((digitalRead(6) == LOW) ? 0 : 1) << 6;
value |= ((digitalRead(5) == LOW) ? 0 : 1) << 5;
value |= ((digitalRead(4) == LOW) ? 0 : 1) << 4;
value |= ((digitalRead(3) == LOW) ? 0 : 1) << 3;
value |= ((digitalRead(2) == LOW) ? 0 : 1) << 2;
value |= ((digitalRead(1) == LOW) ? 0 : 1) << 1;
value |= ((digitalRead(0) == LOW) ? 0 : 1) << 0;

除了 PORT* 還有 DDR*PIN* (* 同樣是 B, C, D)
DDR* 為設定對應引腳的 輸入輸出 方向
例如
DDRD = 0x4B;
由於 0x4B(hex) = 01001011(bin) ,位元資料為 0 = INPUT , 為 1 = OUTPUT
等價於
pinMode(7, INPUT);
pinMode(6, OUTPUT);
pinMode(5, INPUT);
pinMode(4, INPUT);
pinMode(3, OUTPUT);
pinMode(2, INPUT);
pinMode(1, OUTPUT);
pinMode(0, OUTPUT);

PIN* 只是 讀取 對應引腳的訊號
例如
byte value = PIND;
等價於
byte value = 0;
value |= ((digitalRead(7) == LOW) ? 0 : 1) << 7;
value |= ((digitalRead(6) == LOW) ? 0 : 1) << 6;
value |= ((digitalRead(5) == LOW) ? 0 : 1) << 5;
value |= ((digitalRead(4) == LOW) ? 0 : 1) << 4;
value |= ((digitalRead(3) == LOW) ? 0 : 1) << 3;
value |= ((digitalRead(2) == LOW) ? 0 : 1) << 2;
value |= ((digitalRead(1) == LOW) ? 0 : 1) << 1;
value |= ((digitalRead(0) == LOW) ? 0 : 1) << 0;

簡單來說 PORT*, ADD*, PIN* 是一種簡化程式碼或語法的寫法
PORTD 存取 D7 至 D0 共 8位元 資料
但 PORTC 存取 D13 至 D8 及 PORTB 存取 A5 至 A0 ,分別只有 6位元 資料
都是 讀取 第5位元 至 第0位元 的 資料,而非 第7位元 至 第2位元 的 資料

PORT*第n引腳第n位元
PORTCA55
A44
A33
A22
A11
A00
PORTBD135
D124
D113
D102
D91
D80
PORTDD77
D66
D55
D44
D33
D22
D11
D00

補充資料

使用較舊版 Bootloader 的 Arduino Nano
亦可以使用這方法,將新版本的 Bootloader 燒綠到 Arduino Nano 的 QFP ATmega328P

總結

淺綠色的 Arduino UNO Rev3 是 Arduino 的官方版本
藍色是與 Arduino UNO Rev3 相容的 UNO ,形狀大小與官方版本是完全相同,不過 UNO 比官方版本提供更多引腳
Arduino UNO Rev3 數碼引腳 及 類比引腳 等 常用引腳 都是 插孔,但 UNO 還提供 插頭 方便讓 其他電子零件 連接

設計線路、接駁電子零件、編寫程式、提供電源便可以運作
例如要在 LCD顯示器上 顯示溫度、濕度資料,可以編寫好運作程式,測試正確後,設計編路甚至製作印刷電路板
當安裝所有需要使用的零件都印刷電路板後,接通電源便可以立即使用

比起購買 Arduino ,只購買 ATmega328P* 的成本更低
而且獨立運作的話, Arduino底板 的體積反而會佔據使用空間,可能不太適合小型專案
雖然 Arduino Nano 等版本的體積會細小及便宜,但仍不及單購買 ATmega328P*
如果要更細小,可以使用 SMT 版本的 ATmega328P* 可以更節慳空間及成本
沒有預載 Bootloader 的 ATmega328P* 會再稍微便宜一點
如果需要大量購買,可以選擇沒有預裝 Bootloader 的版本

另外如果上載 Sketch 到 ATmega328P* 時,突然終斷連接,排除晶片的內部受損,有機會導致寫入資料出錯而不能再上載 Sketch
這時同樣需要重新寫入 Bootloader 到 ATmega328P* 讓 ATmega328P* 能正常運作

參考資料

沒有留言 :

張貼留言