โปรแกรมแรก กับ ATmega328P
ไมโครคอนโทรลเลอร์ Atmega328P เป็นไอซีไมโครคอนโทรลเลอร์ของบริษัท Atmel มีโครงสร้างภายในเป็นแบบ RISC (Reduced instruction set Computer) มีหน่วยความจำโปรแกรมภายในเป็นแบบแฟลช สามารถเขียน-ลบโปรแกรมใหม่ได้หลายครั้ง โปรแกรมข้อมูลเป็นแบบ In-System programmable
Atmel Studio 7.0 คือ integrated พัฒนาการแพลตฟอร์ม (IDP) สำหรับการพัฒนาและดีบั๊กโปรแกรม Atmel ARM® Cortex™-M และ Atmel AVR® microcontroller-(MCU-) ซึ่งจะประกอบไปด้วย GCC C และ C++ Compiler (ที่ใช้แปลงภาษาซี ให้เป็น Machine Code), Assembly (ที่ใช้แปลงภาษาแอสแซมบลี ให้เป็น Machine Code) และ simulator บรรจุมาอยู่แล้ว
ขั้นตอนการทํางาน
โดย ไอซีไมโครคอนโทรลเลอร์ ATmega328P ต้องผ่านขั้นตอนการ เบิร์น Bootloader มาแล้ว ถ้ายังไม่ได้ เบิร์น Bootloader ให้ทำตามขั้นตอนลิงค์บทความด้านล่าง
1 : เชื่อมต่อวงจร ATmega328P
เชื่อมต่อวงจร Minimum ATmega328P Circuit ตามรูปด้านล่าง
ต่อ LED เพิ่มที่ขา PB5
2. ติดตั้งไดร์เวอร์ FT232R USB
เชื่อมต่อสาย USB ระหว่าง คอมพิวเตอร์ กับ FT232R USB
คลิกขวา ที่ Start เลือกไปที่ Device Manager
ที่ Other Devices จะพบ FT232R USB ที่ยังไม่ได้ติดตั้ง ไดร์เวอร์
ให้ทำการติดตั้ง ไดร์เวอร์ โดย ดาวน์โหลดไดร์เวอร์ ได้ที่
ไฟล์ซิปที่ดาวน์โหลดมา
คลายซิป ไฟล์ซิปที่ดาวน์โหลดมา
คลิกขวา ที่ FT232R USB UART -> Update driver
เลือก Browse my computer for drivers
คลิก Next
ไปที่ Ports (COM & LPT) จะพบ USB Serial Port ในตัวอย่างเป็น (COM11) แสดงว่าคอมพิวเตอร์ของเราสามารถ ติดต่อสื่อสารกับ FT232R USB ได้แล้ว
3 : เชื่อมต่อสาย FT232R USB ไปที่วงจร ATmega328P
เชื่อมต่อสาย FT232R USB ไปที่วงจร ATmega328P ตามรูปด้านล่าง
เชื่อมต่อสายระหว่าง Mini USB B 5pin ระหว่าง วงจร ATmega328P กับ คอมพิวเตอร์
4 : ติดตั้ง Atmel Studio 7.0
ดาวน์โหลดซอฟต์แวร์ Atmel Studio 7.0 ได้ที่ :
การติดตั้งเหมือนกับโปรแกรมทั่วๆไป
5 : สร้างโปรเจคสำหรับเขียนโค้ดภาษา C
เมื่อเปิดโปรแกรม Atmel Studio 7.0 ขึ้นมา ให้คลิกที่เมนู File -> New -> Project..
เลือกเป็น C/C++ -> GCC C Executable Project -> ตั้งชื่อโปรเจค เป็น Binky -> OK
ไมโครคอนโทรลเลอร์ ที่ใช้เป็น ATmega328P
ที่ Device Family : จึงเลือกเป็น ATmega -> ATmega328P -> OK
โปรแกรมจะสร้าง ไฟล์โค้ด main.c ให้โดยอัตโนมัติ
6 : เขียนโค้ดภาษา C
โค้ดตัวอย่างเป็นการทำให้ LED ที่อยู่เชื่อมต่ออยู่ที่ ขา PB5 ของ ATmega328P กระพริบได้ ด้วยการหน่วงเวลา หรือเว้นระยะ จะใช้วิธีที่เรียกว่า Software Delay Loop
จากรูปด้านบน การเขียนโค้ดกำหนดขาของ ATmega328P โซนสีม่วง การเรียกใช้งานขาต่างๆ ซึ่งต้องใช้คำสั่งระดับบิต (bit) ตัวอย่าง ขา PB0 ถึง PB5 ได้ดังนี้
ขา PB0 เขียนเป็น 0B000001 // PORTB0
ขา PB1 เขียนเป็น 0B000010 // PORTB1
ขา PB2 เขียนเป็น 0B000100 // PORTB2
ขา PB3 เขียนเป็น 0B001000 // PORTB3
ขา PB4 เขียนเป็น 0B010000 // PORTB4
ขา PB5 เขียนเป็น 0B100000 // PORTB5
หน่วยข้อมูลคอมพิวเตอร์ ที่เล็กที่สุด เรียกว่า บิต (bit) ซึ่งเมื่อข้อมูลรวมกันถึงขนาด 8 บิต เราจะเรียกว่า 1 ไบต์ (Byte) สังเกต : ถ้ามี 1 อยู่ตำแหน่ง บิต (bit) ไหน จะเป็นการกำหนดให้เป็นขาที่เรียกใช้งาน
ตัวอย่างโค้ด : ที่เขียนคำสั่งให้ ขา PB5 หรือ ขา 13 ของ Arduino Uno ให้เป็นขา Output 3 ตัวอย่าง ซึ่งได้ผลลัพธ์ เหมือนกัน
เขียนด้วย Arduino IDE
pinMode(13, OUTPUT);
สำหรับการเขียนโปรแกรมของ Arduino นั้นจะใช้ภาษา C++ ซึ่งเป็นรูปแบบภาษาซีประยุกต์แบบหนึ่ง ที่มีโครงสร้างการทำงานของตัวภาษาโดยรวม คล้ายกับ ภาษาซีมาตรฐาน (ANSI-C) ทั่วๆไป เพียงแต่ได้มีการปรับปรุงเพื่อลดความยุ่งยากในการใช้งานลง เพื่อให้ผู้ใช้สามารถใช้งาน เขียนโปรแกรมได้ง่าย และสะดวกมากกว่าเขียนภาษาซี แบบมาตรฐาน
เขียนด้วย Atmel Studio แบบที่ 1
DDRB |= 0B100000;
ใช้ภาษาซีมาตรฐาน โดย DDRB เป็น Direction Register ของ DDRB ใช้ประโยชน์ในการบ่งบอกแต่ละ bit ใน Direction Register ว่า เป็น input หรือ output โดย เขียน 1,0 ลงใน Direction Register ถ้า 1 ปรากฎใน Direction Register bit ใด แสดงว่า Direction Register นั้น จะเป็น Output ถ้าเป็น 0 ก็จะหมายถึงว่า เป็น Input
เขียนด้วย Atmel Studio แบบที่ 2
DDRB |= 1<<5;
1<<5 คือ เลื่อน bit ไปทางซ้าย (Shift Left) 5 ตำแหน่ง เริ่มที่ 0B000001 เมื่อเลื่อน bit ไปทางซ้าย 5 ตำแหน่ง ก็จะได้ 0B100000 เหมือนการเขียน แบบที่ 1
เมื่อพิจารณาดูแล้ว การเขียนด้วย Atmel Studio แบบที่ 2 น่าจะเป็นการเขียนและอ่านโค้ดได้ง่ายกว่า ดังนั้นบทความนี้จึงเลือก Atmel Studio แบบที่ 2 เป็นแนวทางในการเขียนโค้ด
โดย สามารถศึกษาการเขียนโค้ด กำหนดขาของ ATmega328P เพิ่มเติม ตามลิงค์บทความด้านล่าง
เขียนโปรแกรมตามโค้ดด้านล่างนี้
#define F_CPU 16000000UL // Used a 16Mhz Crystal as Clock Source
#include <avr/io.h> // Contains all the I/O Register Macros
#include <util/delay.h>
// Generates a Blocking Delay
int main(void)
{
DDRB |= 1<<5; // Configuring PB5 as Output
while (1)
{
PORTB |= 1<<5; // Writing HIGH to PB5
_delay_ms(1000); // Delay of 1 Second
PORTB &= ~(1<<5); // Writing LOW to PB5
_delay_ms(1000); // Delay of 1 Second
}
}
คอมไพล์โค้ด โดย คลิก Build -> Build Solution
Build succeeded. แสดงว่า โค้ดไม่มีปัญหาอะไร
โปรแกรมจะสร้าง ไฟล์โค้ด Binky.hex ที่โฟลเดอร์ Output Files ให้โดยอัตโนมัติ
.hex คือไฟล์รหัสภาษาเครื่อง (machine code) เป็นไฟล์ต้นฉบับเลขฐานสิบหกที่มักใช้โดยอุปกรณ์ลอจิกที่โปรแกรมได้เช่นไมโครคอนโทรลเลอร์ มันมีการตั้งค่าข้อมูลการกำหนดค่าหรือข้อมูลอื่น ๆ ที่บันทึกในรูปแบบเลขฐานสิบหก
ซึ่งสามารถนำไปใช้โปรแกรม ATmega328P เพื่อทดสอบการทำงานของโค้ดในฮาร์ดแวร์จริงได้
แสดงตำแหน่งไฟล์ Binky.hex
7 : อธิบายโค้ด
#define คือ ค่าคงที่ และ ให้ชื่อว่า F_CPU กำหนดค่าให้เป็น 16000000 คือการกำหนดให้นำค่า 16MHz ไปไปคำนวณร่วมกับฟังก์ชั่น delay.h ในการหน่วงเวลาเพราะ วงจร Minimum ATmega328P Circuit ที่เราเชื่อมต่อนั้น ใช้คริสตัล 16Mhz เป็นแหล่งสัญญาณนาฬิกา
#define F_CPU 16000000
#include คือการเรียกใช้ไฟล์ภาษาซี จากไลบรารี ซึ่งอยู่ในโฟลเดอร์ avr และ ชื่อไฟล์ io.h สำหรับใช้งานเกี่ยวกับ ฟังก์ชั่น ควบคุมอินพุท/เอาท์พุท (เช่น PORTB, DDRB)
#include <avr/io.h>
#include คือการเรียกใช้ไฟล์ภาษาซี จากไลบรารี ซึ่งอยู่ในโฟลเดอร์ util และ ชื่อไฟล์ delay.h สำหรับใช้งานเกี่ยวกับ ฟังก์ชั่น การหน่วงเวลา
#include <util/delay.h>
ฟังก์ชั่น main จะเป็นฟังก์ชั่นแรกที่โปแกรมเริ่มทำงาน ดังนั้นจึงเป็นฟังก์ชั่นบังคับ และ (void) หมายความว่า “ไม่มีการคืนค่ากลับ”
int main (void)
เริ่มต้นบล็อกฟังก์ชั่น main()
{
กำหนดให้เป็นขาดิจิตอล PฺฺB5 ของ Atmega328P ให้เป็นขาที่ทำงานแบบเอาท์พุท
DDRB |= 1<<5;
ทำงานไปเรื่อยๆ จนกว่าเงื่อนไขจะเป็นเท็จ คือจะวนลูปไปเรื่อยๆ
while (1)
เริ่มต้นบล็อกในส่วนของ while (1)
{
PORTB คือ Output Register ให้ที่ขา PB5 ของ Atmega328P ให้ส่งลอจิก 1 ออกไป เพื่อให้การทำงานเป็น HIGH
PORTB |= 1<<5;
หน่วงเวลารอ 1 วินาที
_delay_ms(1000);
ที่ขา PB5 ของ Atmega328P ให้ส่งลอจิก 0 ออกไป เพื่อให้การทำงานเป็น LOW
PORTB &= ~(1<<5);
หน่วงเวลารอ 1 วินาที
_delay_ms(1000);
สิ้นสุดบล็อกในส่วนของ while (1)
}
สิ้นสุดบล็อกฟังก์ชั่น main()
}
รายละเอียดเพิ่มเติมเกี่ยวกับโค้ด
ตัวดำเนินการระดับบิต (Bitwise operators) คือตัวดำเนินการที่ดำเนินการในระบิตของข้อมูล โดยทั่วไปแล้วตัวดำเนินการระดับบิตมักใช้ในการเขียนโปรแกรมระดับต่ำ (Low level)
| คือ BIT OR: หลักการทำงานคือ ได้ผลลัพธ์เป็น 1 ถ้าค่าบิตอย่างน้อยหนึ่งบิตเป็น 1 ไม่เช่นนั้นได้ผลลัพธ์เป็น 0
& คือ BIT AND: หลักการทำงานคือ ได้ผลลัพธ์เป็น 1 ถ้าค่าบิตทั้งสองเป็น 1 ไม่เช่นนั้นได้ผลลัพธ์เป็น 0
~ คือ BIT INVERT: หลักการทำงานคือ กลับบิตจาก 1 เป็น 0 และกลับบิตจาก 0 เป็น 1
การคอมไพล์โปรแกรมให้เป็นภาษาเครื่อง
กระบวนการแปลโปรแกรมภาษาชั้นสูงให้เป็นภาษาเครื่องนั้นเรียกว่าเป็นการคอมไพล์ (compile) ซึ่งอาศัยโปรแกรมที่เรียกว่าคอมไพเลอร์ (compiler) เป็นตัวดำเนินการ เราอาศัยโปรแกรม avr-gcc
เป็นตัวคอมไพเลอร์
8 : อัพโหลดไฟล์ .hex ไปยัง ATmega328P
การอัพโหลดที่แนะนำมี 2 วิธีคือ
8.1 : อัพโหลดโค้ดผ่าน Arduino IDE
โดยทำตามขั้นตอนลิงค์ด้านล่าง
8.2 : อัพโหลดโค้ดผ่าน XLoader
ติดตั้ง XLoader โดยดาวน์โหลดซอฟต์แวร์ XLoader ได้ที่ :
เมื่อดาว์นโหลดไฟล์เสร็จแล้ว คลายไฟล์ แล้วคลิกเปิดไฟล์ XLoader
คลิก … เลือกไฟล์ .hex ที่ได้จากขั้นตอนที่ 6
คลิก Open
Device เลือกเป็น Uno(ATmega328)
ที่ COM port เลือก ตามรูปด้านบนในตัวอย่างคือ COM11 (COM แต่ละเครื่องไม่เหมือนกันให้เลือก COM ตามที่ปรากฏ)
คลิก Upload
ถ้าอัพโหลดได้สำเร็จจะแสดง uploaded
ไฟ LED ที่เชื่อมต่อที่ขา PB5 บนบอร์ด กระพริบ ติด-ดับ แสดงว่า การทดสอบการทำงานของโค้ด ภาษา C ในฮาร์ดแวร์จริง สําเร็จแล้ว
9 : รายการอุปกรณ์
- 1. ชุดคิทต่อวงจร Minimum ATmega328P Circuit
- 2. Breadboard 700 Points SYB-120
- 3. Jumper (M2M) cable 10cm Male to Male
- 4. FT232RL FTDI USB To TTL Serial Converter Module
- 5. USB Male to Mini USB B 5pin Data Cable
<<< C0: เบิร์น Bootloader ATmega328P บทความก่อนหน้า | บทความต่อไป C2: อัพโหลดโค้ด ด้วย External Tools >>>