บทความ ARM7 เขียนโปรแกรมกับ ARM7
ทดลองโปรแกรมหลอดแอลอีดี
ในบทความนี้เป็นการเรียนรู้เกี่ยวกับพอร์ตไอ/โอ (i/o port) ของอาร์ม7 แต่ก่อนอื่นผมต้องขออภัยที่เขียนบทความได้ล่าช้ากว่าที่ควรจะเป็น ทั้งนี้เนื่องจากช่วงเดือนที่ผ่านมานั้นมีหลายเรื่องราวประดังเข้ามาพร้อมๆกัน ไม่ว่าจะเป็นเรื่องการจากไปของโน๊ตบุ๊ก IBM ที่อยู่ร่วมกันมากว่า 2 ปี เรื่องของการสอนที่ผมต้องสอนถึง 5 วิชา คือ ดิสคริตและโครงสร้าง การวิจัยดำเนินงาน การจัดการความมั่นคงสารสนเทศ หลักความมั่นคงคอมพิวเตอร์และไซเบอร์ และพฤติกรรมการสอน แค่เตรียมสอนก็หัวปั่นเลยทีเดียว นอกจากนี้ผมต้องปั่นภาคนิพนธ์ให้จบการศึกษา (ปริญญาโทสาขาเทคโนโลยีและยุทธศาสตร์สารสนเทศ) ซึ่งตอนนี้ก็จัดการเรียบร้อยแล้ว เหลือเก็บตกพวกแก้ไขความผิดพลาดในการพิมพ์เอกสาร พร้อมกันนี้ก็เข้าศึกษาต่อระดับปริญญาเอกในสาขาเทคโนโลยีคุณภาพ ต่อเนื่องกันไป พอซาๆ จากเรื่องงานก็มาเขียนบทความกันต่อ และคงเขียนต่อไปเรื่อยๆ จนกว่าทางอีทีทีจะเบื่อหน้าผมกันไปข้างนึงครับ (ฮ่ะๆๆ ล้อเล่นนะครับ)
อุปกรณ์
ในบทความนี้ผมใช้อุปกรณ์ประกอบการทดลองดังนี้
1. บอร์ด ET-Base ARM7 LPC2103 (www.etteam.com/product/ARM/et-base_arm2103.htm)
2. บอร์ด ET-TEST 10P/OUT (www.etteam.com/product/13A02.html)
3. บอร์ด ET-USB/RS232 (www.etteam.com/product/12A28.html) สำหรับแปลงพอร์ต USB ให้เป็น RS232
4. คอมพิวเตอร์เอเซอร์แอสไพร์ 5051 (ควักเงินซื้ออีกแล้วครับ ฮ่ะๆ)
รูปที่ 1 (ซ้าย) ET-USB/RS232 (ขวา) ET-Base ARM7 LPC2103 และ ET-TEST 10P/OUT
ซอฟต์แวร์
โปรแกรมที่ผมใช้ประกอบการทดลองก็มีดังนี้ครับ
1. โปรแกรม LPC2000 Flash ของบริษัทฟิลิปส์ใช้สำหรับโปรแกรมชิพของอาร์ม 7
2. โปรแกรม Keil-ARM7 รุ่น 3.0a (รุ่นทดลอง) สำหรับเขียนภาษาซี ซึ่งถ้าสนใจรายละเอียดการใช้งานให้อ่านจากเอกสารต่อไปนี้ครับ
2.1 http://www.etteam.com/product/ARM/01/exKeil.pdf เป็นตัวอย่างการเขียนโปรแกรม ของอีทีที
2.2 http://www.etteam.com/product/ARM/01/qStartARM.pdf เป็นเอกสารสำหรับอาร์ม 7 เบื้องต้น ของอีทีที
3. ที่ขาดไม่ได้คือไมโครซอฟต์วินโดวส์ XP Pro SP2 (รหัสเป็นของจริง แต่ลงใหม่ไม่ได้แล้วเนื่องจากลงหลายครั้ง ไมโครซอฟต์ไม่ยอมให้ activated ผมเลยต้องใช้ของปลอมแล้วเปลี่ยนรหัสเป็นของจริง... งงไหมครับ :D)
วงจรการเชื่อมต่อ
ในการทดลองนี้ผมเชื่อมต่อบอร์ด ET-TEST 10P/OUT เข้ากับพอร์ต P0.8-P0.15 ของอาร์ม 7 ดังรูปด้านล่าง
รูปที่ 2 การเชื่อมต่อ ET-Base ARM7 LPC 2103 เข้ากับ ET-TEST 10P/OUT
พอร์ตของอาร์ม 7
อาร์ม 7 มีพอร์ตเอนกประสงค์ (GPIO: general purpose input/output) ให้ผู้เขียนโปรแกรมใช้งานได้ 2 พอร์ต คือ พอร์ต0 (P0) และพอร์ต1 (P1) ทั้งสองพอร์ตนี้จะถูกอ้างอิงด้วยเรจิสเตอร์ขนาด 32 บิต แต่ในการใช้งานจริง P0 ของบอร์ด ET-Base ARM7 LPC2103 นั้นเราสามารถใช้งานได้เพียง 30 บิต คือ ขา P0.0-P0.25 และ P0.27-P0.30 ส่วน P1 นั้นสามารถใช้ได้ 16 บิต คือ P1.16-P1.31
ในการสั่งงานนั้นจะต้องกำหนดการทำงานของแต่ละขาของพอร์ตผ่านทางเรจิสเตอร์ PINSEL0, PINSEL1 และ PINSEL2 ซึ่งมีรายละเอียดดังต่อไปนี้

สิ่งที่เราจะต้องระวังเป็นอย่างมากคือ ในการใช้ P0 นั้น เราจะต้องกำหนดค่าของ P0.0 และ P0.1 เป็น 01 กับ 01 เสมอ เนื่องจากวงจรของ ET-Base ARM7 LPC1203 นั้นต่อสองขานี้เข้ากับวงจร RS232 ซึ่งถ้ากำหนดค่าผิดพลาดอาจจะมีผลกับบอร์ดได้ครับ
ในตารางต่อไปนี้จะเป็นของ PINSEL1 ครับ
รายละเอียดของภาวการณ์ทำงานของแต่ละบิตของ P0.16-P0.30 เป็นดังต่อไปนี้ครับ
และตารางต่อไปนี้เป็นตารางของ PINSEL2 มีรายการแตกต่างจาก PINSEL0 และ PINSEL1 เนื่องจากในการกำหนดค่านั้นเราสามารถกำหนดภาวการณ์ทำงานได้ 4 ลักษณะดังตารางถัดไป
ทั้งนี้นอกจาก PINSEL0, PINSEL1 และ PINSEL2 แล้วยังมีเรจิสเตอร์สำหรับควบคุมการทำงานของ GPIO อีก นั่นคือ IOPIN, IOSET, IOCLR และ IODIR โดยมีหน้าที่ดังตารางต่อไปนี้
เรจิสเตอร์
|
การทำงาน
|
ความหมาย
|
IOPIN0
|
อ่าน
|
อ่านสภานะของพอร์ต P0
|
IOPIN1
|
อ่าน
|
อ่านสถานะของพอร์ต P1
|
IOSET0
|
เขียน/อ่าน
|
กำหนดบิตที่ระบุของพอร์ต P0 ให้เป็น 1
|
IOSET1
|
เขียน/อ่าน
|
กำหนดบิตที่ระบุของพอร์ต P1 ให้เป็น 1
|
IOCLR0
|
เขียน/อ่าน
|
กำหนดบิตที่ระบุของพอร์ต P0 ให้เป็น 0
|
IOCLR1
|
เขียน/อ่าน
|
กำหนดบิตที่ระบุของพอร์ต P1 ให้เป็น 0
|
IODIR0
|
เขียน
|
กำหนดบิตที่ระบุว่าเป็น 1 ของพอร์ต P0 เป็นส่วนนำออก
|
IODIR1
|
เขียน
|
กำหนดบิตที่ระบุว่าเป็น 1 ของพอร์ต P1 เป็นส่วนนำออก
|
จากข้อมูลทั้งหมดทำให้เราทราบว่าการติดต่อกับพอร์ตภายนอกนั้นเราจะต้องกำหนดค่าการทำงานของแต่ละบิตของ P0 กับ P1 ได้อย่างไร และเราได้รู้จักคำสั่งพื้นฐานอีก 8 คำสั่ง ที่ใช้สำหรับอ่านค่าสถานะของพอร์ต กำหนดค่าบิตของพอร์ตให้เป็น1 กำหนดค่าบิตของพอร์ตให้เป็น0 และกำหนดบิตของพอร์ตให้ทำงานเป็นส่วนนำเข้าหรือส่งออก
เพื่อความเข้าใจผมขอยกตัวอย่างง่ายๆให้พอมองเห็นภาพ เช่น ถ้าเราต้องการกำหนดให้ P0.8 ถึง P0.15 เป็นพอร์ตส่งออก (output port) เราจะต้องกำหนดค่าดังนี้
PINSEL0 = 0x00000005; /* กำหนดให้ P0.0 ทำงานเป็น TxD และ P0.1 ทำงานเป็น RxD*/
IODIR0 = 0x0000FF00; /* 0000 0000 0000 0000-1111 1111 0000 0000 */
ถ้าเราต้องการหลอดแอลอีดีให้มีการติด/ดับสลับกันไปจะสามารถเขียนขั้นตอนได้ดังนี้
IOSET0 = 0x0000FF00;
หน่วงเวลา
IOCLR0 = 0x0000FF00;
หน่วงเวลา
ตัวอย่างโปรแกรม
จากทั้งหมดเมื่อเรานำมารวมกันเป็นโปรแกรมจะสามารถเขียนออกมาได้อย่างนี้
#include <LPC21xx.h>
void delay(int nCnt)
{
int cnt, cnt2;
for (cnt=0; cnt<nCnt; cnt++) {
for (cnt2=0; cnt2<1000; cnt2++);
}
}
int main(void)
{
PINSEL0 = 0x00000005;
IODIR0 = 0x0000FF00;
for (;;) {
IOSET0 = 0x0000FF00;
delay(5000);
IOCLR0 = 0x0000FF00;
Delay(5000);
}
}
สรุป
จากบทความนี้คงพอจะเป็นข้อมูลพื้นฐานได้ว่าเราจะสามารถกำหนดสภาวะการทำงานของพอร์ต และสั่งงานการทำงานของพอร์ตได้อย่างไร ในครั้งหน้าเราจะเพิ่มการเชื่อมต่อกับสวิทช์ร่วมกับหลอดแอลอีดีเพื่อสั่งให้แอลอีดีทำงานได้หลากหลายขึ้น โดยอาศัยตัวอย่างของการเขียนในครั้งนี้เป็นพื้นฐาน
สุดท้ายต้องขอขอบคุณทางบริษัทอีทีทีที่ยังคงสนับสนุนการทำงานของผม และขอขอบคุณครอบครัวที่ให้กำลังใจผมตลอดมา วันนี้ผมก็ต้องทำงานหนักมากขึ้น แต่ผมจะเขียนบทความให้ได้ทุกเดือน เพราะสิ่งที่ผมทำอยู่นี้เป็นความใฝ่ฝันของผม เพียงแต่เมื่อเราเติบโตขึ้น อะไรต่อมิอะไรก็นำพาเราไปทางโน้นทางนี้จนเราแทบจะไม่ได้อยู่บนทางเดินที่เราชอบ แต่อย่างไรก็ดีถึงผมจะต้องเดินออกนอกทางเดินที่ผมใฝ่ฝัน ผมก็ยังมีอีทีทีเป็นแหล่งเผยแพร่ความรู้ที่ผมพยายามศึกษา ถึงมันจะไม่มากมาย ไม่ยาก ไม่ลึกลับซับซ้อน แต่คงพอจะเป็นประโยชน์บ้างสำหรับคนเริ่มต้น หรือคนที่สนใจ