ก่อนอื่นก็ต้องขอออกตัวก่อนว่าผมไม่ได้เก่นอะไรมากมายไม่ได้เรียนอิเล็กทรอนิกส์ไม่ได้เรียนการเขียนโปรแกรมอะไรเลยอาศัยใจรักหาความรู้เอาเองล้วนๆตอนนี้ก็รู้แค่พอไปวัดไปวากับเค้าได้เท่านั้นฉะนั้นบทความนี้อาจจะมีจุดผิดพลาดบ้างนะครับ
Microcontroller
ไมโครคอนโทรลเลอร์เป็นอุปกรณ์อิเล็กทรอนิกส์ที่ใช้ควบคุมอุปกรณ์ไฟฟ้าหรือระบบอิเล็กทรอนิกส์ต่างๆ ไมโครคอนโทรลเลอร์นั้นเปรียบเสมือนคอมพิวเตอร์ขนาดเล็กอยากให้มันทำอะไรเราก็เขียนโปรแกรมที่เราต้องการยัดใส่ลงไป
AVR
AVR เป็นไมโครคอนโทรลเลอร์ตระกูลหนึ่งผลิตโดยบริษัท Atmel AVR มีสถาปัตยกรรมแบบ RISC มีความเร็วในการประมวลผล 1 คำสั่ง ต่อ 1 สัญญาณนาฬิกา ใช้พลังงานต่ำโดยบางรุ่นใช้ไฟเพียง 1.5 V - 5.5 V เท่านั้นและยังมีโหมดประหยัดพลังงานอีก 6 โหมด ในบทความนี้ผมจะใช้ AVR เบอร์ ATmega48 ซึ้งเป็นรุ่นเล็กสุดในกลุ่ม ATmega

คุณสมบัติของ ATmega48
-มีหน่วยความจำสำหรับเก็บโปรแกรมแบบแฟลช(ROM) ขนาด 4 กิโลไบต์ สามรถเขียน-ลบได้ประมาณ 10,000 ครั้ง
-มีหน่วยความจำข้อมูล(RAM) ขนาด 512 ไบต์
-มีหน่วยความจำข้อมูลอีอีพรอม(EEPROM) ขนาด 256 ไบต์ สามรถเขียน-ลบได้ประมาณ 100,000 ครั้ง
-มีพอร์ตอินพุตเอาต์พุตให้ใช้งานจำนวน 23 ขา (PB0 ถึง PB7, PC0 ถึง PC6, PD0 ถึง PD7)
-มีความเร็วในการประมวนผลสูงสุด 20 ล้านคำสั่งต่อ 1 วินาทีที่ความถี่ 20 MHz
-มีโมดูลแปลงสัญญาณอะนาลอกเป็นดิจิตอล(Analog-to-Digital Converter) ขนาด 10 บิต 6 ช่องสำหรับตัวถังแบบ PDIP และ 8 ช่องสำหรับตัวถังแบบ TQFP และ MLF
-มีโมดูลสร้างสัญญาณ Pulse width Modulator(PWM) 3 ชุด 6 ช่องสัญญาณ
-มี Timer/Counters ขนาด 8 บิต 2 ตัว และ 16 บิต 1 ตัว
ตำแหน่งขาของ ATmega48 ตัวถังแบบ PDIP

การต่อใช้งาน

ภาษาที่ใช้เขียนโปรแกรมไมโครคอนโทรลเลอร์
ภาษาที่ใช้เขียนโปรแกรมไมโครคอนโทรลเลอร์มีหลายภาษา เช่น ภาษาเครื่อง,Assembly, BASIC, C เป็นต้น แต่ละภาษาก็มีข้อดีข้อเสียแตกต่างกันไป ในที่นี้ผมจะใช้ภาษา C เนื่องจากเขียนง่ายแก้ไขเปลี่ยนแปลงได้ง่าย(ความจริงเขียนเป็นแต่ภาษา C 555+)
โปรแกรมเขียนภาษา C สำหรับไมโครคอนโทรลเลอร์
สำหรับโปรแกรมที่ใช้เขียนนั้นผมจะใช้ mikroC for AVR (โหลดทึ่นี่ครับ < http://www.mikroe.com/eng/products/v...c-pro-for-avr/ >) เนื่องจาเป็นโปรแกรมที่ใช้งานง่ายมีไลบรารีให้ใช้เพียบเหมาะสำหรับมือใหม่แต่มันไม่ฟรีครับ รุ่นทดลองไม่มีจำกัดวันใช้งานแต่มันจำกัดขนาดโปรแกรมไว้ไม่เกิน 4KB ซึ่งมันก็พอดีกับ ATmega48 ใครอยากได้ตัวเต็มก็ใช้ความสามารถหากันเองครับ
การเขียนภาษา C นั้นเข้าไปอ่านที่นี่เลยครับผมขี้เกียดเขียนมันยาว < http://www.vcharkarn.com/varticle/18065 > ใครที่มีพื้นฐานภาษา C อยู่แล้วคงไม่ต้องอ่านแค่เรียนรู้รีจิสเตอร์ต่างๆของไมโครคอนโทรลเลอร์เพิ่มเติมเท่านั้น
เริ่มต้นด้วยการลงโปรแกรม mikroC for AVR ก่อนคงไม่ยากสำหรับทุกคนในนี้ เมื่อเปิดโปรแกรมครั้งแรกในพื้นที่ทำงามมันจะมีตัวอย่างการเขียนโปรแกรมก็ให้ปิดไปเลยครับ เริ่มโปรเจคใหม่โดยเลือกตามรูป

คลิก Next

เลือก ATMEGA48 และคลิก Next

ตั้งสัญญาณนาฬิกาเป็น 1.000000MHz (ในกรณีทีซื้อไมโครคอนโทรลเลอร์มาใหม่ๆยังไม่ได้เซ็ต Fuse Bit) และคลิก Next

เลือกที่เก็บและตั้งชื่อโปรเจคจากนั้นก็คลิก Next ไปเรื่อยๆจนจบ

จะมีหน้าต่างโปรเจคใหม่ขึ้นมาพร้อมให้เราเขียนโปรแกรมแล้ว

หลังจากเราเขียนโปรแกรมเสร็จเราก็จะทำการคอมไพล์โดยคลิก Build ตามภาพ ถ้าโปรแกรมที่เราเขียนมีจุดผิดพลาดจะไม่สามารถคอมไพล์ได้และ mikroC จะแจ้งให้เราทราบว่าผิดพลาดตรงไหนในหน้าต่าง Messages แต่ถ้าโปรแกรมสมบูรณ์เราก็จะได้ไฟล์ HEX มา(อยู่ในโฟลเดอร์ที่เราเก็บโปรเจค) เพื่อเอาไปยัดลงตัวไมโครคอนโทรลเลอร์อีกที

การดาวโหลดไฟล์ HEX ลงสู่ไมโครคอนโทรลเลอร์
การดาวโหลดไฟล์ HEX ลงไมโครคอนโทรลเลอร์ AVR นั้นมีอยู่ 3 แบบ คือ High Voltage , ISP และ Boot Loaders ในที่นี้ผมจะใช้การโปรแกรมแบบ ISP(In-System Programming) เนื่องจากเป็นวิธีที่ง่ายสุดเครื่องโปรแกรมสามารถสร้างเองได้หรือใครจะหาซื้อเอาก็ได้ครับแต่ราคามันเฉียดๆพันเลยแต่ถ้าสร้างเองก็ร้อยกว่าๆครับ ผมขอแนะนำเครื่องโปรแกรมที่ชื่อว่า USBasp เป็นเครื่องโปรแกรมแบบ USB มีขนาดเล็กสร้างง่ายดาวโหลดไฟล์ได้เร็วใช้กับ AVR ได้หลายเบอร์ที่สำคัญเค้าแจก firmware และวงจรฟรีครับ อันนี้เว็บของเค้าครับ < http://www.fischl.de/usbasp/ >

สำหรับคนที่พึ่งเริ่มต้นอาจมีปัญหาว่าจะโปรแกรม firm wareลงไมโครคอนโทรลเลอร์ยัง มันจะมีร้านที่รับอัดโปรแกรมอยู่ครับ อย่างเช่น อิเลคทรอนิคส์ ซอร์ซ ค่าอัดโปรแกรมก็ตัวละ 20บาท ครับ
การลงไดรเวอร์นั้นให้เข้าไปที่ Computer Management > Device Manager > LibUSB-Win32 Device คลิกขวาที่ USBasp เลือก update driver แล้วเลือกไดรเวอร์ที่โหลดคงจะทำเป็นทุกคนนะครับ
การต่อ USBasp เข้ากับขาของ ATmega48 ทำตามนี้ครับ
ตำแหน่งขา Connectors ของ USBasp

ขา 1 MOSI ต่อเข้ากับขา 17 - PB3(MOSI) ของ ATmega48
ขา 5 RESET ต่อเข้ากับขา 1 - PC6(RESET) ของ ATmega48
ขา 7 SCK ต่อเข้ากับขา 19 - PB5(SCK) ของ ATmega48
ขา 9 MISO ต่อเข้ากับขา 18 - PB4(MISO) ของ ATmega48
ขา 8,10 GND ต่อเข้าลงกราวนด์
โปรแกรมที่ใช้ดาวโหลดไฟล์ HEX ลงไมโครคอนโทรลเลอร์ผมแนะนำให้ใช้ SinaProg ครับเพราะใช้งานง่ายสุดๆมีให้โหลดได้ที่นี้ครับ < http://w215.wrzuta.pl/plik/4UGkSv2LU...aprog_1.4.5.10 >
เมื่อต่อ USBasp เข้ากับ ATmega48 และคอมฯเรียบร้อยทำการเปิดโปรแกรม SinaProg ขึ้นมาครับ ตรง Programmer ให้เลือกเป็น USBasp แล้วลองกดปุ่ม Search ดูครับในช่อง Device ต้องขึ้นรุ่นไมโครคอนโทรลเลอร์ตรงกับที่เราเชื่อมต่อนั้นก็คือ ATmega48 ถ้าขึ้นไม่ตรงรุ่นต้องไล่แก้ปัญหาดูครับ ถ้าไม่มีปัญหาอะไรก็เริ่มการเลือกไฟล์ HEX โดยการกดปุ่มรูปโฟลเดอร์แล้วเลือกไฟล์ HEX ที่เราต้องการเสร็จแล้วกดปุ่ม Program ที่อยู่ในช่อง Flash ถ้าโปรแกรมสำเร็จจะขึ้นข้อความว่า "Programming Flash OK"

โปรแกรมจำลองการทำงานของวงจรอิเลคทรอนิคส์ Proteus
สำหรับที่ยังไม่มีไมโครคอนโทรลเลอร์หรือขี้เกียดทำเครื่องโปรแกรมก็ใช้โปรแกรม Proteus จำลองการทำงานของวงจรก่อนก็ได้ครับ สามารถโหลดรุ่นทดลองได้ที่นี่ครับ < http://www.labcenter.co.uk/download/...m#professional >
เมื่อลงโปรแกรมเสร็จก็เปิดโปรแกรมที่ไอค่อน ISIS 7 Professional

ผมสร้างวงจรไฟกระพริบโดยใช้ ATmega48 เป็นตัวอย่างนะครับ เริ่มโดยการกดปุ่ม P ที่อยู่ทางด้านซ้ายเพื่อเลือกอุปกรณ์ที่เราต้องใช้

จะปรากฏหน้าต่าง Pick Devices ขึ้นมา หายเราต้องการอุปกรณ์อะไรก็พิมพ์ลงไปในช่อง Keywords แล้วโปรแกรมจะทำการหาให้เราเอง เมื่อเจออุปกรณ์ที่ต้องการแล้วให้ดับเบิ้ลคลิกที่ชื่ออุปกรณ์นั้นแล้วอุปกรณ์นั้นก็จะไปอยู่ในช่อง DEVICES ทำแบบนี้ไปเรื่อยๆจนได้อุปกรณ์ที่เราต้องครบแล้วก็ปิดหน้าต่าง Pick Devices ไปเลย

เลือกอุปกรณ์ในช่อง DEVICES แล้วคลิกในพื้นที่ทำงานเพื่อวางอุปกรณ์ลงไป ในการเชื่อมอุปกรณ์เข้าด้วยกันให้เอาเมาส์ไปชี้ที่ขาของอุปกรณ์ที่ต้องการคลิกซ้ายแล้วลากไปยังขาของอุปกรณ์อีกตัวแล้วคลิกว้ายอีกที่ขาของอุปกรณ์ก็จะเชื่อมต่อกัน ในการเลือกไฟเลี้ยงบวกและกราวนด์ก็ให้กดปุ่ม Terminals Mode ในภาพ

การนำไฟล์ HEX เข้าสู่ ATmega48 ทำได้โดยการคลิกขวาที่ ATmega48 แล้วเลือก Edit Properties ตรงช่อง Program File ให้กดปุ่มรูปโฟลเดอร์แล้วเลือกไฟล์ HEX ที่เราต้องการจากนั้นกดปุ่ม OK

กดปุ่ม Play เพื่อเริ่มการทำงานของวงจร ถ้าไม่มีความผิดพลาดวงจรก็จะทำงาน LED จะกระพริบไปเรื่อยๆ ถ้ามีความผิดพลาดเกิดขึ้นโปรแกรมก็จะแจ้งให้เรารู้

พอร์ต i/o ต่างๆของ ATmega48
ตามมาตรฐานสากลจะเรียกขาอินพุตเอาต์พุต(ต่อไปผมใช้ i/o แทนอินพุตเอาต์พุต)ว่า."พอร์ต" ATmega48 นั้นมีพอร์ต i/o อิสระให้เราใช้งานทั้งหมด 23ขา โดยแบ่งออกเป็น3กลุ่มคือ พอร์ต B มี 8ขา (PB0 ถึง PB7), พอร์ต C มี 7ขา (PC0 ถึง PC6)และพอร์ต D มี 8ขา (PD0 ถึง PD7) แต่เนื่องจาก PC6 นั้นเป็นขา Reset ไม่สามารถเอามาใช้งานได้จึงเหลือพอร์ตให้ใช้งาน 22พอร์ต ความจริงก็เอา PC6 มาใช้เป็นพอร์ต i/o ได้เหมือนกันแต่มันจะไม่สามารถโปรแกรมแบบ ISP ได้อีกต้องโปรแกรมแบบ High Voltage เท่านั้น
การกำหนดทิศทางของพอร์ต
เมื่อเริ่มโปรแกรม main สิ่งแรกที่ต้องทำก็คือการกำหนดทิศทางของแต่ละพอร์ต พอร์ตต่างๆนั้นเราสามรถที่จะให้มันเป็นอินพุตหรือเอาต์พุตก็ได้โดยการใส่ค่าคงที่ให้กับรีจิสเตอร์ DDRB สำหรับพอร์ต B ทั้งหมด, DDRC สำหรับพอร์ต C ทั้งหมดและ DDRD สำหรับพอร์ต D ทั้งหมด ค่าคงที่นั้นเราจะใช้เลขฐาน2, ฐาน10หรือฐาน16ก็ได้ ถ้ากำหนดให้เป็น "0" พอร์ตนั้นก็จะเป็นอินพุตแต่ถ้าเป็น "1" พอร์ตนั้นก็จะเป็นเอาต์พุต ยกตัวเช่น เราต้องการให้พอร์ต D ทั้งหมดเป็นอินพุตเราก็พิมพ์ DDRD = 0x00; ลงไป 00 นั้นเป็นเลขฐาน16เมื่อแปลเป็นเลขฐาน2ก็จะได้ 00000000 โดยที่ 0 ตัวแรกนั้นจะกำหนดทิศทางของพอร์ต D7 และไล่ไปทางขวาเรื่อยๆจนถึง 0 ตัวสุดท้ายก็คือพอร์ต D0 นอกจากนี้เรายังสามารถกำหนดแบบเจาะจงพอร์ตได้โดยเติม .Bx(xคือหมายเลขพอร์ต) เช่นต้องการให้พอร์ต B1 เป็นเอาต์พุตเราก็พิมพ์ DDRB.B1 = 1; ลงไป
การกำหนดสถานะของพอร์ตเอาต์พุต
เมื่อกำหนดพอร์ตนั้นๆให้เป็นเอาต์พุตแล้วเราก็จะมากำหนดสถานะของพอร์ตนั้นๆอีกที เราสามารถกำหนดสถานะของพอร์ตได้2แบบคือ 1(ไฟบวก)และ 0(ไฟลบ) โดยกำหนดได้จากรีจิสเตอร์ PORTB สำหรับพอร์ต B ทั้งหมด, PORTC สำหรับพอร์ต C ทั้งหมดและ PORTD สำหรับพอร์ต D ทั้งหมด ค่าคงที่นั้นเราจะใช้เลขฐาน2, ฐาน10หรือฐาน16ก็ได้ ถ้ากำหนดให้เป็น "0" พอร์ตนั้นก็จะมีสถานะเป็น 0(ไฟลบ) แต่ถ้าเป็น "1" พอร์ตนั้นก็จะมีสถานะเป็น 1(ไฟบวก) ยกตัวเช่น เราต้องการให้พอร์ต D ทั้งหมดมีสถานะเป็น 0 เราก็พิมพ์ PORTD = 0x00; ลงไป นอกจากนี้เรายังสามารถกำหนดแบบเจาะจงพอร์ตได้โดยเติม .Bx(xคือหมายเลขพอร์ต) เช่นต้องการให้พอร์ต B1 มีสถานะเป็น 0 เราก็พิมพ์ PORTB.B1 = 0; ลงไป
การอ่านค่าจากพอร์ตอินพุต
เมื่อเรากำหนดให้พอร์ตใดๆเป็นพอร์ตอินพุตเราจะสามารถมารถให้พอร์ตนั้นรับสัญญาณจากอุปกรณ์อื่นได้ อย่างเช่นสวิตช์เป็น แล้วก็ทำการอ่านค่าจากพอร์ตนั้นเพื่อเอามาเป็นเงื่อนไขในการทำงาน ค่าที่เราอ่านพอร์ต1พอร์ตจะมี 1 กับ 0 เท่านั้นแต่ถ้าอ่านทั้ง 8 พอร์ตก็จะอ่านได้ทั้งหมด 256 ค่า เราสามารถอ่านค่าจากพอร์ตอินพุตได้จากรีจิสเตอร์ PINB สำหรับพอร์ต B ทั้งหมด, PINC สำหรับพอร์ต C ทั้งหมดและ PIND สำหรับพอร์ต D ทั้งหมด นอกจากนี้เรายังสามารถอ่านค่าแบบเจาะจงพอร์ตได้โดยเติม .Bx(xคือหมายเลขพอร์ต) เช่นต้องการอ่านค่าจากพอร์ต B1 ก็พิมพ์ PINB.B1
ตัวอย่างโปรแกรมพื้นฐานต่างๆ
โปรแกรมไฟกระพริบ 1 ดวง
การต่อวงจร

โปรแกรมนี้เป็นโปรแกรมไฟกระพริบ 1 ดวง โดยการใช้พอร์ต B0 ควบคุม LED ให้ดับ 1 วินาทีและติดสว่าง 1 วินาทีด้วยการใช้คำสั่ง Delay_ms(1000) ซึ่งเป็นคำสั่งหน่วงเวลาของ mikroC มีหน่วยเป็นมิลลิวินาทีเราสามารถกำหนดการหน่วงเวลาโดยการเปลี่ยนแปลงตัวเลขในวงเล็บ โปรแกรมจะทำงานวนแบบนี้ไปเรื่องๆเนื่องจากเราใช้คำสั่ง while(1) วนลูปแบบไม่รู้จบ
นอกจากการเขียนโปรแกรมด้วยวิธีพื้นๆแบบข้างบนแล้วเรายังสามารถใช้คำสั่งกลับสถานะ(~)เขียนโปรแกรมไฟกระพริบได้ด้วย
จะเห็นได้ว่าแบบที่2นั้นสั้นกว่าแบบแรกจึงทำให้ขนาดของโปรแกรมเล็กลงด้วยแต่ให้ผลลับที่เหมือนกัน แบบที่2นี้ใช้คำสั่งกลับสถานะ(~)พอร์ต B0 ให้ตรงข้ามกับสถานะเดิม จาก 0 เป็น 1 จาก 1 เป็น 0 การเขียนโปรแกรมไมโครคอนโทรลเลอร์นั้นไม่ได้มีรูปแบบที่ตายตัวเราสามารถพลิกแพลงได้หลายแบบ พยายามหาวิธีที่สั้นที่สุดจะทำให้ขนาดโปรแกรมเล็กและประหยัดเนื้อที่ ROM ของไมโครคอนโทรลเลอร์
โปรแกรมไฟกระพริบ 2 ดวงติดสลับกัน
การต่อวงจร

อันนี้เป็นโปรแกรมไฟกระพริบติดสลับกันไปมาโดยใช้พอร์ต B0 และ B1 ควบคุม LED
โปรแกรมไฟวิ่ง 8 ดวง

โปรแกรมนี้เป็นโปรแกรมไฟวิ่ง 8 ดวงวิ่งเรียงกันไปเรื่อยๆจนถึงดวงที่ 8 แล้วจะกลับมาดวงที่ 1 อีกทีและจะเป็นแบบนี้ไปเรื่องๆ โปรแกรมนี้จะมีการใช้งานตัวแปลด้วย ก่อนเริ่มโปรแกรม main จะมีการตั้งชื่อและกำหนดชนิดของตัวแปลก่อนนั้นก็คือตัวแปล i และ j
คำสั่ง for(i=0;i<8;i++) เป็นคำสั่งวนลูปแบบตั้งเงื่อนไขเพื่อกำหนดจำนวนรอบที่ต้องให้มีการวนคำสั่งซ้ำ (i=0;i<8;i++) หมายถึงในขณะเริ่มต้นให้ตัวแปล i มีค่าเท่ากับ 1 จากนั้นทำการตรวจสอบว่าตัวแปล I มีค่าน้อยกว่า 8 หรือไม่ หากตัวแปล i มีค่าน้อยกว่า 8 ให้เพิ่มค่าตัวแปล i ขึ้น 1 ค่าจนกว่าตัวแปล i จะมีค่าไม่น้อยกว่า 8 เงื่อนไขในวงเล็บก็จะเป็นเท็จคำสั่งวนลูป for(){} ก็จะหยุดทำงาน จากตัวอย่างกำหนดให้มีการวนลูปจำนวน 8 รอบ
คำสั่ง j = j<<1; เป็นคำสั่งให้มีการเลื่อนบิทข้อมูลของตัวแปล j ไปทางซ้าย 1 ตำแหน่ง คำสั่ง PORTB = j; ให้พอร์ต B มีค่าเท่ากับตัวแปล j
ใครผ่านไปผ่านมาช่วยดันหน่อย
Microcontroller
ไมโครคอนโทรลเลอร์เป็นอุปกรณ์อิเล็กทรอนิกส์ที่ใช้ควบคุมอุปกรณ์ไฟฟ้าหรือระบบอิเล็กทรอนิกส์ต่างๆ ไมโครคอนโทรลเลอร์นั้นเปรียบเสมือนคอมพิวเตอร์ขนาดเล็กอยากให้มันทำอะไรเราก็เขียนโปรแกรมที่เราต้องการยัดใส่ลงไป
AVR
AVR เป็นไมโครคอนโทรลเลอร์ตระกูลหนึ่งผลิตโดยบริษัท Atmel AVR มีสถาปัตยกรรมแบบ RISC มีความเร็วในการประมวลผล 1 คำสั่ง ต่อ 1 สัญญาณนาฬิกา ใช้พลังงานต่ำโดยบางรุ่นใช้ไฟเพียง 1.5 V - 5.5 V เท่านั้นและยังมีโหมดประหยัดพลังงานอีก 6 โหมด ในบทความนี้ผมจะใช้ AVR เบอร์ ATmega48 ซึ้งเป็นรุ่นเล็กสุดในกลุ่ม ATmega

คุณสมบัติของ ATmega48
-มีหน่วยความจำสำหรับเก็บโปรแกรมแบบแฟลช(ROM) ขนาด 4 กิโลไบต์ สามรถเขียน-ลบได้ประมาณ 10,000 ครั้ง
-มีหน่วยความจำข้อมูล(RAM) ขนาด 512 ไบต์
-มีหน่วยความจำข้อมูลอีอีพรอม(EEPROM) ขนาด 256 ไบต์ สามรถเขียน-ลบได้ประมาณ 100,000 ครั้ง
-มีพอร์ตอินพุตเอาต์พุตให้ใช้งานจำนวน 23 ขา (PB0 ถึง PB7, PC0 ถึง PC6, PD0 ถึง PD7)
-มีความเร็วในการประมวนผลสูงสุด 20 ล้านคำสั่งต่อ 1 วินาทีที่ความถี่ 20 MHz
-มีโมดูลแปลงสัญญาณอะนาลอกเป็นดิจิตอล(Analog-to-Digital Converter) ขนาด 10 บิต 6 ช่องสำหรับตัวถังแบบ PDIP และ 8 ช่องสำหรับตัวถังแบบ TQFP และ MLF
-มีโมดูลสร้างสัญญาณ Pulse width Modulator(PWM) 3 ชุด 6 ช่องสัญญาณ
-มี Timer/Counters ขนาด 8 บิต 2 ตัว และ 16 บิต 1 ตัว
ตำแหน่งขาของ ATmega48 ตัวถังแบบ PDIP

การต่อใช้งาน

ภาษาที่ใช้เขียนโปรแกรมไมโครคอนโทรลเลอร์
ภาษาที่ใช้เขียนโปรแกรมไมโครคอนโทรลเลอร์มีหลายภาษา เช่น ภาษาเครื่อง,Assembly, BASIC, C เป็นต้น แต่ละภาษาก็มีข้อดีข้อเสียแตกต่างกันไป ในที่นี้ผมจะใช้ภาษา C เนื่องจากเขียนง่ายแก้ไขเปลี่ยนแปลงได้ง่าย(ความจริงเขียนเป็นแต่ภาษา C 555+)
โปรแกรมเขียนภาษา C สำหรับไมโครคอนโทรลเลอร์
สำหรับโปรแกรมที่ใช้เขียนนั้นผมจะใช้ mikroC for AVR (โหลดทึ่นี่ครับ < http://www.mikroe.com/eng/products/v...c-pro-for-avr/ >) เนื่องจาเป็นโปรแกรมที่ใช้งานง่ายมีไลบรารีให้ใช้เพียบเหมาะสำหรับมือใหม่แต่มันไม่ฟรีครับ รุ่นทดลองไม่มีจำกัดวันใช้งานแต่มันจำกัดขนาดโปรแกรมไว้ไม่เกิน 4KB ซึ่งมันก็พอดีกับ ATmega48 ใครอยากได้ตัวเต็มก็ใช้ความสามารถหากันเองครับ
การเขียนภาษา C นั้นเข้าไปอ่านที่นี่เลยครับผมขี้เกียดเขียนมันยาว < http://www.vcharkarn.com/varticle/18065 > ใครที่มีพื้นฐานภาษา C อยู่แล้วคงไม่ต้องอ่านแค่เรียนรู้รีจิสเตอร์ต่างๆของไมโครคอนโทรลเลอร์เพิ่มเติมเท่านั้น
เริ่มต้นด้วยการลงโปรแกรม mikroC for AVR ก่อนคงไม่ยากสำหรับทุกคนในนี้ เมื่อเปิดโปรแกรมครั้งแรกในพื้นที่ทำงามมันจะมีตัวอย่างการเขียนโปรแกรมก็ให้ปิดไปเลยครับ เริ่มโปรเจคใหม่โดยเลือกตามรูป

คลิก Next

เลือก ATMEGA48 และคลิก Next

ตั้งสัญญาณนาฬิกาเป็น 1.000000MHz (ในกรณีทีซื้อไมโครคอนโทรลเลอร์มาใหม่ๆยังไม่ได้เซ็ต Fuse Bit) และคลิก Next

เลือกที่เก็บและตั้งชื่อโปรเจคจากนั้นก็คลิก Next ไปเรื่อยๆจนจบ

จะมีหน้าต่างโปรเจคใหม่ขึ้นมาพร้อมให้เราเขียนโปรแกรมแล้ว

หลังจากเราเขียนโปรแกรมเสร็จเราก็จะทำการคอมไพล์โดยคลิก Build ตามภาพ ถ้าโปรแกรมที่เราเขียนมีจุดผิดพลาดจะไม่สามารถคอมไพล์ได้และ mikroC จะแจ้งให้เราทราบว่าผิดพลาดตรงไหนในหน้าต่าง Messages แต่ถ้าโปรแกรมสมบูรณ์เราก็จะได้ไฟล์ HEX มา(อยู่ในโฟลเดอร์ที่เราเก็บโปรเจค) เพื่อเอาไปยัดลงตัวไมโครคอนโทรลเลอร์อีกที

การดาวโหลดไฟล์ HEX ลงสู่ไมโครคอนโทรลเลอร์
การดาวโหลดไฟล์ HEX ลงไมโครคอนโทรลเลอร์ AVR นั้นมีอยู่ 3 แบบ คือ High Voltage , ISP และ Boot Loaders ในที่นี้ผมจะใช้การโปรแกรมแบบ ISP(In-System Programming) เนื่องจากเป็นวิธีที่ง่ายสุดเครื่องโปรแกรมสามารถสร้างเองได้หรือใครจะหาซื้อเอาก็ได้ครับแต่ราคามันเฉียดๆพันเลยแต่ถ้าสร้างเองก็ร้อยกว่าๆครับ ผมขอแนะนำเครื่องโปรแกรมที่ชื่อว่า USBasp เป็นเครื่องโปรแกรมแบบ USB มีขนาดเล็กสร้างง่ายดาวโหลดไฟล์ได้เร็วใช้กับ AVR ได้หลายเบอร์ที่สำคัญเค้าแจก firmware และวงจรฟรีครับ อันนี้เว็บของเค้าครับ < http://www.fischl.de/usbasp/ >

สำหรับคนที่พึ่งเริ่มต้นอาจมีปัญหาว่าจะโปรแกรม firm wareลงไมโครคอนโทรลเลอร์ยัง มันจะมีร้านที่รับอัดโปรแกรมอยู่ครับ อย่างเช่น อิเลคทรอนิคส์ ซอร์ซ ค่าอัดโปรแกรมก็ตัวละ 20บาท ครับ
การลงไดรเวอร์นั้นให้เข้าไปที่ Computer Management > Device Manager > LibUSB-Win32 Device คลิกขวาที่ USBasp เลือก update driver แล้วเลือกไดรเวอร์ที่โหลดคงจะทำเป็นทุกคนนะครับ
การต่อ USBasp เข้ากับขาของ ATmega48 ทำตามนี้ครับ
ตำแหน่งขา Connectors ของ USBasp

ขา 1 MOSI ต่อเข้ากับขา 17 - PB3(MOSI) ของ ATmega48
ขา 5 RESET ต่อเข้ากับขา 1 - PC6(RESET) ของ ATmega48
ขา 7 SCK ต่อเข้ากับขา 19 - PB5(SCK) ของ ATmega48
ขา 9 MISO ต่อเข้ากับขา 18 - PB4(MISO) ของ ATmega48
ขา 8,10 GND ต่อเข้าลงกราวนด์
โปรแกรมที่ใช้ดาวโหลดไฟล์ HEX ลงไมโครคอนโทรลเลอร์ผมแนะนำให้ใช้ SinaProg ครับเพราะใช้งานง่ายสุดๆมีให้โหลดได้ที่นี้ครับ < http://w215.wrzuta.pl/plik/4UGkSv2LU...aprog_1.4.5.10 >
เมื่อต่อ USBasp เข้ากับ ATmega48 และคอมฯเรียบร้อยทำการเปิดโปรแกรม SinaProg ขึ้นมาครับ ตรง Programmer ให้เลือกเป็น USBasp แล้วลองกดปุ่ม Search ดูครับในช่อง Device ต้องขึ้นรุ่นไมโครคอนโทรลเลอร์ตรงกับที่เราเชื่อมต่อนั้นก็คือ ATmega48 ถ้าขึ้นไม่ตรงรุ่นต้องไล่แก้ปัญหาดูครับ ถ้าไม่มีปัญหาอะไรก็เริ่มการเลือกไฟล์ HEX โดยการกดปุ่มรูปโฟลเดอร์แล้วเลือกไฟล์ HEX ที่เราต้องการเสร็จแล้วกดปุ่ม Program ที่อยู่ในช่อง Flash ถ้าโปรแกรมสำเร็จจะขึ้นข้อความว่า "Programming Flash OK"

โปรแกรมจำลองการทำงานของวงจรอิเลคทรอนิคส์ Proteus
สำหรับที่ยังไม่มีไมโครคอนโทรลเลอร์หรือขี้เกียดทำเครื่องโปรแกรมก็ใช้โปรแกรม Proteus จำลองการทำงานของวงจรก่อนก็ได้ครับ สามารถโหลดรุ่นทดลองได้ที่นี่ครับ < http://www.labcenter.co.uk/download/...m#professional >
เมื่อลงโปรแกรมเสร็จก็เปิดโปรแกรมที่ไอค่อน ISIS 7 Professional

ผมสร้างวงจรไฟกระพริบโดยใช้ ATmega48 เป็นตัวอย่างนะครับ เริ่มโดยการกดปุ่ม P ที่อยู่ทางด้านซ้ายเพื่อเลือกอุปกรณ์ที่เราต้องใช้

จะปรากฏหน้าต่าง Pick Devices ขึ้นมา หายเราต้องการอุปกรณ์อะไรก็พิมพ์ลงไปในช่อง Keywords แล้วโปรแกรมจะทำการหาให้เราเอง เมื่อเจออุปกรณ์ที่ต้องการแล้วให้ดับเบิ้ลคลิกที่ชื่ออุปกรณ์นั้นแล้วอุปกรณ์นั้นก็จะไปอยู่ในช่อง DEVICES ทำแบบนี้ไปเรื่อยๆจนได้อุปกรณ์ที่เราต้องครบแล้วก็ปิดหน้าต่าง Pick Devices ไปเลย

เลือกอุปกรณ์ในช่อง DEVICES แล้วคลิกในพื้นที่ทำงานเพื่อวางอุปกรณ์ลงไป ในการเชื่อมอุปกรณ์เข้าด้วยกันให้เอาเมาส์ไปชี้ที่ขาของอุปกรณ์ที่ต้องการคลิกซ้ายแล้วลากไปยังขาของอุปกรณ์อีกตัวแล้วคลิกว้ายอีกที่ขาของอุปกรณ์ก็จะเชื่อมต่อกัน ในการเลือกไฟเลี้ยงบวกและกราวนด์ก็ให้กดปุ่ม Terminals Mode ในภาพ

การนำไฟล์ HEX เข้าสู่ ATmega48 ทำได้โดยการคลิกขวาที่ ATmega48 แล้วเลือก Edit Properties ตรงช่อง Program File ให้กดปุ่มรูปโฟลเดอร์แล้วเลือกไฟล์ HEX ที่เราต้องการจากนั้นกดปุ่ม OK

กดปุ่ม Play เพื่อเริ่มการทำงานของวงจร ถ้าไม่มีความผิดพลาดวงจรก็จะทำงาน LED จะกระพริบไปเรื่อยๆ ถ้ามีความผิดพลาดเกิดขึ้นโปรแกรมก็จะแจ้งให้เรารู้

พอร์ต i/o ต่างๆของ ATmega48
ตามมาตรฐานสากลจะเรียกขาอินพุตเอาต์พุต(ต่อไปผมใช้ i/o แทนอินพุตเอาต์พุต)ว่า."พอร์ต" ATmega48 นั้นมีพอร์ต i/o อิสระให้เราใช้งานทั้งหมด 23ขา โดยแบ่งออกเป็น3กลุ่มคือ พอร์ต B มี 8ขา (PB0 ถึง PB7), พอร์ต C มี 7ขา (PC0 ถึง PC6)และพอร์ต D มี 8ขา (PD0 ถึง PD7) แต่เนื่องจาก PC6 นั้นเป็นขา Reset ไม่สามารถเอามาใช้งานได้จึงเหลือพอร์ตให้ใช้งาน 22พอร์ต ความจริงก็เอา PC6 มาใช้เป็นพอร์ต i/o ได้เหมือนกันแต่มันจะไม่สามารถโปรแกรมแบบ ISP ได้อีกต้องโปรแกรมแบบ High Voltage เท่านั้น
การกำหนดทิศทางของพอร์ต
เมื่อเริ่มโปรแกรม main สิ่งแรกที่ต้องทำก็คือการกำหนดทิศทางของแต่ละพอร์ต พอร์ตต่างๆนั้นเราสามรถที่จะให้มันเป็นอินพุตหรือเอาต์พุตก็ได้โดยการใส่ค่าคงที่ให้กับรีจิสเตอร์ DDRB สำหรับพอร์ต B ทั้งหมด, DDRC สำหรับพอร์ต C ทั้งหมดและ DDRD สำหรับพอร์ต D ทั้งหมด ค่าคงที่นั้นเราจะใช้เลขฐาน2, ฐาน10หรือฐาน16ก็ได้ ถ้ากำหนดให้เป็น "0" พอร์ตนั้นก็จะเป็นอินพุตแต่ถ้าเป็น "1" พอร์ตนั้นก็จะเป็นเอาต์พุต ยกตัวเช่น เราต้องการให้พอร์ต D ทั้งหมดเป็นอินพุตเราก็พิมพ์ DDRD = 0x00; ลงไป 00 นั้นเป็นเลขฐาน16เมื่อแปลเป็นเลขฐาน2ก็จะได้ 00000000 โดยที่ 0 ตัวแรกนั้นจะกำหนดทิศทางของพอร์ต D7 และไล่ไปทางขวาเรื่อยๆจนถึง 0 ตัวสุดท้ายก็คือพอร์ต D0 นอกจากนี้เรายังสามารถกำหนดแบบเจาะจงพอร์ตได้โดยเติม .Bx(xคือหมายเลขพอร์ต) เช่นต้องการให้พอร์ต B1 เป็นเอาต์พุตเราก็พิมพ์ DDRB.B1 = 1; ลงไป
การกำหนดสถานะของพอร์ตเอาต์พุต
เมื่อกำหนดพอร์ตนั้นๆให้เป็นเอาต์พุตแล้วเราก็จะมากำหนดสถานะของพอร์ตนั้นๆอีกที เราสามารถกำหนดสถานะของพอร์ตได้2แบบคือ 1(ไฟบวก)และ 0(ไฟลบ) โดยกำหนดได้จากรีจิสเตอร์ PORTB สำหรับพอร์ต B ทั้งหมด, PORTC สำหรับพอร์ต C ทั้งหมดและ PORTD สำหรับพอร์ต D ทั้งหมด ค่าคงที่นั้นเราจะใช้เลขฐาน2, ฐาน10หรือฐาน16ก็ได้ ถ้ากำหนดให้เป็น "0" พอร์ตนั้นก็จะมีสถานะเป็น 0(ไฟลบ) แต่ถ้าเป็น "1" พอร์ตนั้นก็จะมีสถานะเป็น 1(ไฟบวก) ยกตัวเช่น เราต้องการให้พอร์ต D ทั้งหมดมีสถานะเป็น 0 เราก็พิมพ์ PORTD = 0x00; ลงไป นอกจากนี้เรายังสามารถกำหนดแบบเจาะจงพอร์ตได้โดยเติม .Bx(xคือหมายเลขพอร์ต) เช่นต้องการให้พอร์ต B1 มีสถานะเป็น 0 เราก็พิมพ์ PORTB.B1 = 0; ลงไป
การอ่านค่าจากพอร์ตอินพุต
เมื่อเรากำหนดให้พอร์ตใดๆเป็นพอร์ตอินพุตเราจะสามารถมารถให้พอร์ตนั้นรับสัญญาณจากอุปกรณ์อื่นได้ อย่างเช่นสวิตช์เป็น แล้วก็ทำการอ่านค่าจากพอร์ตนั้นเพื่อเอามาเป็นเงื่อนไขในการทำงาน ค่าที่เราอ่านพอร์ต1พอร์ตจะมี 1 กับ 0 เท่านั้นแต่ถ้าอ่านทั้ง 8 พอร์ตก็จะอ่านได้ทั้งหมด 256 ค่า เราสามารถอ่านค่าจากพอร์ตอินพุตได้จากรีจิสเตอร์ PINB สำหรับพอร์ต B ทั้งหมด, PINC สำหรับพอร์ต C ทั้งหมดและ PIND สำหรับพอร์ต D ทั้งหมด นอกจากนี้เรายังสามารถอ่านค่าแบบเจาะจงพอร์ตได้โดยเติม .Bx(xคือหมายเลขพอร์ต) เช่นต้องการอ่านค่าจากพอร์ต B1 ก็พิมพ์ PINB.B1
ตัวอย่างโปรแกรมพื้นฐานต่างๆ
โปรแกรมไฟกระพริบ 1 ดวง
void main() //เริ่มโปรแกรมหลัก
{
DDRB.B0 = 1; //ให้พอร์ต B0 เป็นเอาต์พุต
while(1) //วนลูปแบบไม่รู้จบ
{
PORTB.B0 = 0; //ให้พอร์ต B0 มีสถานะเป็น 0 LED ดับ
Delay_ms(1000); //หน่วงเวลาให้ LED ดับ 1 วินาที
PORTB.B0 = 1; //ให้พอร์ต B0 มีสถานะเป็น 1 LED ติดสว่าง
Delay_ms(1000); //หน่วงเวลาให้ LED ติดสว่าง 1 วินาที
}
}
{
DDRB.B0 = 1; //ให้พอร์ต B0 เป็นเอาต์พุต
while(1) //วนลูปแบบไม่รู้จบ
{
PORTB.B0 = 0; //ให้พอร์ต B0 มีสถานะเป็น 0 LED ดับ
Delay_ms(1000); //หน่วงเวลาให้ LED ดับ 1 วินาที
PORTB.B0 = 1; //ให้พอร์ต B0 มีสถานะเป็น 1 LED ติดสว่าง
Delay_ms(1000); //หน่วงเวลาให้ LED ติดสว่าง 1 วินาที
}
}

โปรแกรมนี้เป็นโปรแกรมไฟกระพริบ 1 ดวง โดยการใช้พอร์ต B0 ควบคุม LED ให้ดับ 1 วินาทีและติดสว่าง 1 วินาทีด้วยการใช้คำสั่ง Delay_ms(1000) ซึ่งเป็นคำสั่งหน่วงเวลาของ mikroC มีหน่วยเป็นมิลลิวินาทีเราสามารถกำหนดการหน่วงเวลาโดยการเปลี่ยนแปลงตัวเลขในวงเล็บ โปรแกรมจะทำงานวนแบบนี้ไปเรื่องๆเนื่องจากเราใช้คำสั่ง while(1) วนลูปแบบไม่รู้จบ
นอกจากการเขียนโปรแกรมด้วยวิธีพื้นๆแบบข้างบนแล้วเรายังสามารถใช้คำสั่งกลับสถานะ(~)เขียนโปรแกรมไฟกระพริบได้ด้วย
void main() //เริ่มโปรแกรมหลัก
{
DDRB.B0 = 1; //ให้พอร์ต B0 เป็นเอาต์พุต
PORTB.B0 = 0; //ให้พอร์ต B0 มีสถานะเป็น 0
while(1) //วนลูปแบบไม่รู้จบ
{
PORTB.B0 = ~PORTB.B0; //กลับสถานะพอร์ต B0 ให้ตรงข้ามกับสถานะเดิม
Delay_ms(1000); //หน่วงเวลา 1 วินาที
}
}
{
DDRB.B0 = 1; //ให้พอร์ต B0 เป็นเอาต์พุต
PORTB.B0 = 0; //ให้พอร์ต B0 มีสถานะเป็น 0
while(1) //วนลูปแบบไม่รู้จบ
{
PORTB.B0 = ~PORTB.B0; //กลับสถานะพอร์ต B0 ให้ตรงข้ามกับสถานะเดิม
Delay_ms(1000); //หน่วงเวลา 1 วินาที
}
}
โปรแกรมไฟกระพริบ 2 ดวงติดสลับกัน
void main() //เริ่มโปรแกรมหลัก
{
DDRB = 0x03; //ให้พอร์ต B0 และ B1 เป็นเอาต์พุต
PORTB.B0 = 0; //ให้พอร์ต B0 มีสถานะเป็น 0
PORTB.B1 = 1; //ให้พอร์ต B1 มีสถานะเป็น 1
while(1) //วนลูปแบบไม่รู้จบ
{
PORTB.B0 = ~PORTB.B0; //กลับสถานะพอร์ต B0 ให้ตรงข้ามกับสถานะเดิม
PORTB.B1 = ~PORTB.B1; //กลับสถานะพอร์ต B1 ให้ตรงข้ามกับสถานะเดิม
Delay_ms(1000); //หน่วงเวลา 1 วินาที
}
}
{
DDRB = 0x03; //ให้พอร์ต B0 และ B1 เป็นเอาต์พุต
PORTB.B0 = 0; //ให้พอร์ต B0 มีสถานะเป็น 0
PORTB.B1 = 1; //ให้พอร์ต B1 มีสถานะเป็น 1
while(1) //วนลูปแบบไม่รู้จบ
{
PORTB.B0 = ~PORTB.B0; //กลับสถานะพอร์ต B0 ให้ตรงข้ามกับสถานะเดิม
PORTB.B1 = ~PORTB.B1; //กลับสถานะพอร์ต B1 ให้ตรงข้ามกับสถานะเดิม
Delay_ms(1000); //หน่วงเวลา 1 วินาที
}
}

อันนี้เป็นโปรแกรมไฟกระพริบติดสลับกันไปมาโดยใช้พอร์ต B0 และ B1 ควบคุม LED
โปรแกรมไฟวิ่ง 8 ดวง
void main() //เริ่มโปรแกรมหลัก
{
DDRB = 0xFF; //ให้พอร์ต B ทั้งหมดเป็นเอาต์พุต
while(1) //คำสั่งวนลูปแบบไม่รู้จบ
{
j = 1; //ให้ตัวแปล j มีค่าเท่ากับ 1
for(i=0;i<8;i++) //คำสั่งวนลูปนี้ 8 รอบ
{
PORTB = j; //ให้พอร์ต B เท่ากับตัวแปล j
j = j<<1; //เลื่อนข้อมูลของตัวแปล j ไปทางซ้าย 1 บิท
Delay_ms(100); //หน่วงเวลา 0.1วินาที
}
}
}
{
DDRB = 0xFF; //ให้พอร์ต B ทั้งหมดเป็นเอาต์พุต
while(1) //คำสั่งวนลูปแบบไม่รู้จบ
{
j = 1; //ให้ตัวแปล j มีค่าเท่ากับ 1
for(i=0;i<8;i++) //คำสั่งวนลูปนี้ 8 รอบ
{
PORTB = j; //ให้พอร์ต B เท่ากับตัวแปล j
j = j<<1; //เลื่อนข้อมูลของตัวแปล j ไปทางซ้าย 1 บิท
Delay_ms(100); //หน่วงเวลา 0.1วินาที
}
}
}

โปรแกรมนี้เป็นโปรแกรมไฟวิ่ง 8 ดวงวิ่งเรียงกันไปเรื่อยๆจนถึงดวงที่ 8 แล้วจะกลับมาดวงที่ 1 อีกทีและจะเป็นแบบนี้ไปเรื่องๆ โปรแกรมนี้จะมีการใช้งานตัวแปลด้วย ก่อนเริ่มโปรแกรม main จะมีการตั้งชื่อและกำหนดชนิดของตัวแปลก่อนนั้นก็คือตัวแปล i และ j
คำสั่ง for(i=0;i<8;i++) เป็นคำสั่งวนลูปแบบตั้งเงื่อนไขเพื่อกำหนดจำนวนรอบที่ต้องให้มีการวนคำสั่งซ้ำ (i=0;i<8;i++) หมายถึงในขณะเริ่มต้นให้ตัวแปล i มีค่าเท่ากับ 1 จากนั้นทำการตรวจสอบว่าตัวแปล I มีค่าน้อยกว่า 8 หรือไม่ หากตัวแปล i มีค่าน้อยกว่า 8 ให้เพิ่มค่าตัวแปล i ขึ้น 1 ค่าจนกว่าตัวแปล i จะมีค่าไม่น้อยกว่า 8 เงื่อนไขในวงเล็บก็จะเป็นเท็จคำสั่งวนลูป for(){} ก็จะหยุดทำงาน จากตัวอย่างกำหนดให้มีการวนลูปจำนวน 8 รอบ
คำสั่ง j = j<<1; เป็นคำสั่งให้มีการเลื่อนบิทข้อมูลของตัวแปล j ไปทางซ้าย 1 ตำแหน่ง คำสั่ง PORTB = j; ให้พอร์ต B มีค่าเท่ากับตัวแปล j
ใครผ่านไปผ่านมาช่วยดันหน่อย
Comment