830 likes | 1.25k Views
บทที่ 2 แนะนำไมโครคอนโทรลเลอร์บอร์ด การเขียนโปรแกรมและเครื่องมือที่ใช้ในการพัฒนา. เทอดศักดิ์ ลิ่วหาทอง สาขาวิชาอิเล็กทรอนิกส์ สถาบันเทคโนโลยีพระจอมเกล้าเจ้าคุณทหารลาดกระบัง. สถาปัตยกรรมและการออกแบบ PIC. PIC ถูกออกแบบให้มีคุณสมบัติดังต่อไปนี้ Harvard Architecture
E N D
บทที่ 2แนะนำไมโครคอนโทรลเลอร์บอร์ด การเขียนโปรแกรมและเครื่องมือที่ใช้ในการพัฒนา เทอดศักดิ์ ลิ่วหาทอง สาขาวิชาอิเล็กทรอนิกส์ สถาบันเทคโนโลยีพระจอมเกล้าเจ้าคุณทหารลาดกระบัง
สถาปัตยกรรมและการออกแบบ PIC • PIC ถูกออกแบบให้มีคุณสมบัติดังต่อไปนี้ • Harvard Architecture • Reduce Instruction Set Computing (RISC) • Single Word Instruction • Pipeline
Harvard Architecture • สถาปัตยกรรมแบบวอนนอยแมน เป็นการออกแบบไมโครโปรเซสเซอร์ที่มี Bus และหน่วยความจำสำหรับโปรแกรมและข้อมูลร่วมกัน ทำให้ไม่สามารถเฟทช์คำสั่งและข้อมูลพร้อมกันได้ • สถาปัตยกรรมแบบฮาร์วาร์ด เป็นการออกแบบไมโครโปรเซสเซอร์ที่มี Bus และหน่วยความจำสำหรับโปรแกรมและข้อมูลแยกออกจากกัน ทำให้อ่านคำสั่งและข้อมูลพร้อมกันทำให้ทำงานได้เร็วขึ้น
Single Word Instruction • คำสั่งทุกคำสั่งของ PIC มีขนาด 14 bit หรือใช้ 2 byte(Single Word) ในการเก็บคำสั่ง 1 คำสั่ง • ตัวอย่างเช่น PIC ที่มี Program Memory ขนาด 65536 byte (64 kByte) จะเก็บคำสั่งได้ทั้งหมด 32768 คำสั่ง • คำสั่งแต่ละคำสั่งจะใช้เวลาในการทำงาน 4 สัญญาณนาฬิกา หรือเรียกว่า รอบคำสั่ง (Instruction Cycle) • ถ้าป้อนสัญญาณนาฬิกาความถี่ 4 MHz ดังนั้นใน 1 วินาที PIC จะทำงานได้ทั้งหมด 1 ล้านคำสั่ง
Instruction Cycle • 1 รอบคำสั่งประกอบด้วยสัญญาณนาฬิกา 4 สัญญาณ หรือ Q1,Q2,Q3,Q4 • ค่า Address ของ PC จะเพิ่มขึ้นที่ Q1 • คำสั่งจะถูก Fetch จาก Program Memory และเก็บไว้ใน Instruction Register ที่ Q4
Instruction Cycle • จากนั้นคำสั่งจะถูก Decode และ Execute ที่ Q1-Q4 ของ รอบคำสั่งรอบต่อไป • PIC มีการทำงานแบบ Pipeline นั่นคือในขณะที่ PIC ทำการ Decode และ Execute คำสั่งแรก ก็จะทำการ Fetch คำสั่งถัดไปมาเก็บไว้ใน Instruction Register • ดังนั้นจึงสามารถพูดได้ว่า PIC ใช้เวลาในการทำงานคำสั่งละ 4 สัญญาณนาฬิกา
ขนาดล้อ 66 cm ความเร็วเฉลี่ย 40km/Hr • 16.84 รอบต่อวินาที • 1 รอบทำงานได้ 59400 คำสั่ง • 200 สเต็ปต่อ 1 รอบ • 297 คำสั่งต่อ 1 สเต็ป
Program Memory Mode • PIC18F8722 มีโหมดการทำงานของ Program Memory อยู่ 4 โหมดคือ • Microprocessor Mode คำสั่งทั้งหมดจะถูกเก็บไว้ใน Program Memory ภายนอก PIC • Microprocessor with Boot Block Mode คำสั่งส่วนหนึ่งจะถูกเก็บไว้ใน Boot Block ที่อยู่ภายใน PIC คำสั่งที่อยู่นอกพื้นที่ Boot Block จะถูกเก็บไว้ใน Program Memory ภายนอก PIC
Program Memory Mode • Microcontroller Mode คำสั่งทั้งหมดจะต้องถูกเก็บไว้ใน Program Memory ภายใน PIC เท่านั้น • Extended Microcontroller Mode คำสั่งสามารถเก็บไว้ใน Program Memory ภายใน PIC และที่อยู่ภายนอก PIC
เปรียบเทียบคุณสมบัติ PIC ตระกูล PIC18F8722
PICDEM™ PIC18 EXPLORER DEMONSTRATION BOARD ใส่ PIC18F8722 (ไฟ 5V) PICkit™ Starter Kit Plug-In Module ใส่ PIC18F87J11 (ไฟ 3.3V)
PICDEM™ PIC18 EXPLORER DEMONSTRATION BOARD PIC18F8722 Connector สำหรับPlug In Module PIC18F87J11 In Circuit Debugger PICkit Connector
PICDEM™ PIC18 EXPLORER DEMONSTRATION BOARD R ปรับค่าได้ 10kW สำหรับป้อนสัญญาณ Analog ปุ่ม Reset USB Connector สำหรับการสื่อสารแบบ RS232 PIC18LF2450 สำหรับใช้เปลี่ยนการสื่อสารแบบ RS-232 ให้เป็นโปรโตคอลแบบ USB เพื่อใช้เชื่อมต่อกับ PC
PICDEM™ PIC18 EXPLORER DEMONSTRATION BOARD คริสตัล 12 MHz สำหรับ PIC18LF2450 Connector แบบ RS-232 DB9 จัมเปอร์ J13 สำหรับเลือกว่าจะรับส่งแบบ RS-232 หรือ USB จัมเปอร์ J4 ใช้เลือกว่าจะเขียนโปรแกรมลงใน PIC หลัก หรือ PIC18LF2450
PICDEM™ PIC18 EXPLORER DEMONSTRATION BOARD สวิทซ์ s4 สำหรับเลือกใช้ PIC ของบนบอร์ด (PIC18F8722) หรือบน PIM(PIC18F87J11) PIC18F8722 PIC18F87J11 LED ใช้แสดงว่าเปิดเครื่อง จัมเปอร์ JP1 สำหรับตัดการทำงานของ LED 8 ดวง LED 8 ดวง
PICDEM™ PIC18 EXPLORER DEMONSTRATION BOARD คริสตัลความถี่ 32.768 kHz สำหรับการใช้งาน Timer1 ปุ่มกด สำหรับใช้ทดลอง เซนเซอร์วัดอุณหภูมิ MPC9701A 25LC256 SPI EEPROM JP2 Enable/Disable EEPROM
PICDEM™ PIC18 EXPLORER DEMONSTRATION BOARD JP3 Enable/Disable LCD คริสตอล 10 MHz สำหรับ PIC หลัก PICtail Connector สำหรับบอร์ดลูก Expander แบบ SPI (MCP23S17) สำหรับ LCD J4 คอนเน็คเตอร์สำหรับ PIM เลือกแรงดัน 3.3V หรือ 5.0V และ /MCLR J2 คอนเน็คเตอร์สำหรับเลือกแรงดัน 3.3V หรือ 5.0V
วิธีใช้งานบอร์ด PICDemo • เสียบจัมเปอร์ JP1, JP2 และ JP3 เพื่อใช้งาน LED, EEPROM และ LCD ตามลำดับ
วิธีใช้งาน PIC18F8722 • เลื่อนสวิทซ์ s4 ไปที่ตำแหน่ง PIC MCU เพื่อใช้งาน PIC18F8722
วิธีใช้งาน PIC18F87J11 • เสียบ PIM ลงไปบอร์ด PIC Demo โดยต้องหันด้านของ PIM ให้ตรงกับด้านของ Connector • เลื่อนสวิทซ์ s4 ไปที่ตำแหน่ง ICE เพื่อใช้งาน PIM
วิธีใช้งาน PIC18LF2450 • เสียบจัมเปอร์ J4 ไปที่ตำแหน่ง USB
การพัฒนาโปรแกรมโดยใช้ PIC Demo • โปรแกรมที่ต้องใช้ • MPLAB IDE (เขียนภาษา Assembly ได้เพียงอย่างเดียว) • MPLab C18 (เป็นโปรแกรมเสริมของ MPLab IDE สำหรับใช้เขียนภาษา C) • เปิดโปรแกรม MPLAB IDE เลือกเมนู Project->Project wizard • Step one : Device เลือก PIC18F8722 • Step two : Active Toolsuiteเลือก Microchip C18 Toolsuite
การพัฒนาโปรแกรมโดยใช้ PIC Demo • Step three : Create New Project File กด Browse เลือก Folder และชื่อ Project File ที่ต้องการ
การพัฒนาโปรแกรมโดยใช้ PIC Demo • Step Four : • กด Next • หรือเลือกไฟล์ที่ต้องการใส่และกด Add ในกรณีที่ต้องการใส่ไฟล์โปรแกรมที่มีอยู่แล้วเข้าไปใน Project • กด Finish
ตัวอย่างโปรแกรมไฟวิ่ง Demo1.c #include <p18f8722.h> #include <adc.h> #include <delays.h> #include <timers.h> #define NUMBER_OF_LEDS 8 #pragma code int result; int shift; void main(void) { TRISAbits.TRISA0=1; TRISD = 0; PORTD = 0; ADCON1 = 0b00001110; ADCON2 = 0b10001010; • ADCON0bits.ADON = 1; • while(1) • { • ADCON0bits.GO=1; • while(ADCON0bits.GO); • result = ADRES; • result >>=2; • if(result==0) result = 1; • // PORTD = result; • PORTD=1<<shift; • shift++; • shift %=8; • Delay10KTCYx(result); • } • }
การพัฒนาโปรแกรม • โปรแกรมอาจจะแบ่งออกเป็นหลายๆไฟล์ โดยมีวัตถุประสงค์ • แยกไฟล์ในกรณีที่โปรแกรมมีการทำงานหลายส่วน เพื่อความสะดวกในการเขียนโปรแกรม • แยกไฟล์ในกรณีที่มีโปรแกรมเมอร์หลายคน เพื่อความสะดวกในการทำงาน • แยกไฟล์ในกรณีที่ต้องใช้หลายภาษาร่วมกัน
การพัฒนาโปรแกรม • ไฟล์โปรแกรมแต่ละไฟล์จะถูกคอมไพล์หรือแอสแซมเบลอร์ให้เป็น Object file • ไฟล์โปรแกรมใดที่คิดว่าสามารถนำกลับมาใช้ใหม่ได้หลายครั้ง จะถูกทำให้เป็น Library เพื่อให้โปรแกรมอื่นสามารถนำไปใช้งานได้
การพัฒนาโปรแกรม • Object file และ Library file จะถูกนำมารวมกันหรือ Link เข้าด้วยกันเป็นโปรแกรมเดียว ซึ่งจะได้เป็น Hex file, Cof file และ Map file
Library ของ MPLab C18 • ฟังก์ชันที่มากับ Library ของ MPLabC18 มีทั้งหมด 4 กลุ่มคือ • Hardware Peripheral Function • A/D Converter • Input Capture • I2C • I/O Port • Microwire • Pulse-Width Modulation • SPI • Timer • USART
Library ของ MPLab C18 • Software Peripheral Function • External LCD Function • External CAN2510 Function • Software I2C Function • Software SPI Function • Software UART Function
Library ของ MPLab C18 • General Software Library • Character Classification Functions • Data Conversion Functions • Memory and String Manipulation Functions • Delay Functions • Reset Functions • Character Output Functions • Math Libraries • 32-Bit Floating Point Library • The C Standard Library Math Functions
โครงสร้างการเขียนโปรแกรมภาษา C /* Include Files */ #include <p18xxxxx.h> #include … ….. /* Symbol Definitions */ #define MAX 100 #define … …. #pragmaconfig WDTEN = OFF /* Global Variables */ intx,y,z,….. char a, b, c,…… ….. /* Function Declarations */ intFunc(char r) { intx,y; …………. …………. return … } …. …. /* Start of MAIN Program */ void main(void) { ………….. ………….. ………….. ………….. }
โครงสร้างการเขียนโปรแกรมภาษา C /* Include Files */ #include <p18xxxxx.h> #include … ….. /* Symbol Definitions */ #define MAX 100 #define … …. #pragmaconfig WDTEN = OFF /* Global Variables */ intx,y,z,….. char a, b, c,…… ….. /* Function Declarations */ intFunc(char r) { intx,y; …………. …………. return … } …. …. /* Start of MAIN Program */ void main(void) { ………….. ………….. ………….. ………….. } • Preprocessor Directive • ไม่ได้เป็นคำสั่งที่สั่งให้ PIC ทำงาน แต่เป็นคำสั่งที่ใช้ MPLab C18 ทำงานบางอย่างเช่นคำสั่ง • #include <p18xxxxx.h> เป็นคำสั่งให้ใส่ข้อมูลที่อยู่ใน p18xxxxx.h ไว้ที่ตำแหน่งของคำสั่ง include • #define MAX 100 เป็นคำสั่งให้นำ 100 ไปแทน MAX ทุกครั้งที่เจอ • #pragmaconfig … เป็นคำสั่งใช้เลือกชนิดของสัญญาณนาฬิกา หรือใช้สั่งเปิดหรือปิด(Enable/Disable)Watchdog Timer เป็นต้น
โครงสร้างการเขียนโปรแกรมภาษา C /* Include Files */ #include <p18xxxxx.h> #include … ….. /* Symbol Definitions */ #define MAX 100 #define … …. #pragmaconfig WDTEN = OFF /* Global Variables */ intx,y,z,….. char a, b, c,…… ….. Function ฟังก์ชันในภาษา C แบ่งออกเป็น 2 ชนิดคือ ฟังก์ชัน main เป็นฟังก์ชันที่ถูกเรียกเป็นฟังก์ชันแรกในโปรแกรมภาษา C ทุกโปรแกรมจำเป็นจะต้องมีฟังก์ชัน main เสมอและต้องมีเพียงตัวเดียว ฟังก์ชันย่อยคือฟังก์ชันที่ถูกเรียกโดยฟังก์ชัน main หรือถูกเรียกโดยฟังก์ชันย่อยอื่นๆ การใช้ฟังก์ชันย่อยจะทำให้เขียนโปรแกรมได้ง่ายขึ้น /* Function Declarations */ intFunc(char r) { intx,y; …………. …………. return … } …. …. /* Start of MAIN Program */ void main(void) { ………….. ………….. ………….. ………….. }
โครงสร้างการเขียนโปรแกรมภาษา C /* Include Files */ #include <p18xxxxx.h> #include … ….. /* Symbol Definitions */ #define MAX 100 #define … …. #pragmaconfig WDTEN = OFF /* Global Variables */ intx,y,z,….. char a, b, c,…… ….. /* Function Declarations */ intFunc(char r) { intx,y; …………. …………. return … } …. …. /* Start of MAIN Program */ void main(void) { ………….. ………….. ………….. ………….. } Local Variable ตัวแปรทุกตัวที่ถูกสร้างอยู่ภายในฟังก์ชัน จะเรียกว่าตัวแปรชนิด Local ตัวแปรชนิด Local ถูกเรียกใช้ได้เฉพาะภายในฟังก์ชันที่มันถูกสร้างเท่านั้น Global Variable ตัวแปรทุกตัวที่ถูกสร้างอยู่ภายนอกฟังก์ชัน จะเรียกว่าตัวแปรชนิด Global ตัวแปรชนิด Global สามารถเรียกใช้โดยฟังก์ชันใดก็ได้ในโปรแกรม
การใช้คำสั่ง #include • การเขียนภาษา C เราสามารถแยกเขียน ฟังก์ชัน, ค่าคงที่, หรือตัวแปรต่างๆ ไว้ใน Library หรือในไฟล์ภาษา C อื่นๆ เพื่อความสะดวกในการเขียนโปรแกรม • การแยกเขียนโปรแกรมออกเป็นหลาย Library หรือไฟล์ จำเป็นจะต้องประกาศ (Declaration) ชื่อฟังก์ชัน, ค่าคงที่และตัวแปรเหล่านี้ไว้ใน Header File • เราจำเป็นต้องประกาศใช้ header file ที่ต้องใช้ไว้ในโปรแกรมที่เขียน ตัวอย่างเช่น #include <ชื่อ Header file> หรือ #include “c:\\folder\\header.h” /*demo1.c*/ #include <p18f8722.h> // Header file สำหรับ PIC 18F8722 #include <adc.h> // Header file สำหรับฟังก์ชัน ADC #include <delays.h> // Header file สำหรับฟังก์ชัน Delay #include <timers.h> // Header file สำหรับฟังก์ชัน Timer
การใช้คำสั่ง #define • เพื่อให้เขียนโปรแกรมได้ง่าย ในบางครั้งเราอาจจะแทนตัวเลขที่เป็นค่าคงที่ ด้วยชื่อที่มีความหมาย • ในภาษา C เราใช้คำสั่ง #define เพื่อแทนค่าคงที่ด้วยชื่อที่เราต้องการ #define NUMBER_OF_LEDS 8 …. void main(void) { …. • shift %=8; • …. • } #define NUMBER_OF_LEDS 8 …. void main(void) { …. • shift %=NUMBER_OF_LEDS; • …. • }
การใช้คำสั่ง #pragma • #pragmaconfigเป็นคำสั่งที่สั่งให้ MPLabC18 ตั้งค่าต่างๆของ PIC • #pragma code เป็นคำสั่งที่สั่งให้ MPLab C18 นำโปรแกรมหรือตัวแปรไปเก็บไว้ในหน่วยความจำโปรแกรม #pragmaconfig FOSC = INTIO67 #pragmaconfig WDTEN = OFF, LVP = OFF, MCLRE = OFF #pragma code int result; int shift; void main(void) { …. }
การเขียนโปรแกรมที่ดีจะต้องแบ่งหน้าที่การทำงานของโปรแกรมออกเป็นการทำงานย่อยหลายๆงาน โดยที่แต่ละงานจะถูกเขียนในฟังก์ชัน • ฟังก์ชันสามารถถูกเรียกโดยฟังก์ชัน main หรือฟังก์ชันย่อยอื่นๆได้ float SinWave(float x); Void SendWave(char x); void main(void) { float t,Output; for(t=0;t<1.0;t+=0.1) { Output = SinWave(255.0,t); SendWave(Output); } } • float SinWave(float A,float t) • { • return A*sin(2.0*3.14*t); • } • void SendWave(float x) • { • PORTA = (char) x; • }
การสร้างฟังก์ชัน • returntypeคือชนิดของตัวแปรที่จะส่งคืนจากฟังก์ชัน • name ชื่อฟังก์ชัน • type var1 ชนิดและชื่อของตัวแปรอินพุทของฟังก์ชัน • ชื่อในภาษา C เป็นแบบ case sensitive คือฟังก์ชันหรือตัวแปรที่มีชื่อเหมือนกันแต่มีตัวอักษรเล็กใหญ่ไม่เหมือนกันจะหมายถึงคนละฟังก์ชันหรือคนละตัวแปรเช่น funca, FuncA, funcA • returntype name(type var1,type var2,…) • { • body • return A*sin(2.0*3.14*t); • }
การสร้างฟังก์ชัน • โปรแกรมของฟังก์ชันจะต้องเขียนอยู่ในเครื่องหมายปีกกาเสมอ • return เป็นคำสั่งที่ใช้คืนค่าออกจากฟังก์ชัน จะต้องถูกเรียกก่อนออกจากฟังก์ชันเสมอ • ฟังก์ชันที่ไม่มีการคืนค่า ไม่จำเป็นต้องมีคำสั่ง return และกำหนดให้ returntypeเป็น void • returntype name(type var1,type var2,…) • { • body • return A*sin(2.0*3.14*t); • }
ต้องประกาศฟังก์ชันก่อนทุกครั้งที่จะถูกเรียกใช้ต้องประกาศฟังก์ชันก่อนทุกครั้งที่จะถูกเรียกใช้ float SinWave(float x); Void SendWave(char x); void main(void) { float t,Output; for(t=0;t<1.0;t+=0.1) { Output = SinWave(255.0,t); SendWave(Output); } }
การเปลี่ยนชนิดของตัวแปรการเปลี่ยนชนิดของตัวแปร • ถ้าต้องการเปลี่ยนชนิดของตัวแปรจะต้องทำการ cast เสมอ เช่น void SendWave(float x) { PORTA = (char) x; }
Local & Global Variable • Local Variable คือตัวแปรที่สามารถใช้ได้ในฟังก์ชันที่มีการประกาศไว้เท่านั้น • Global Variable คือตัวแปรที่สามารถเรียกใช้ในฟังก์ชันใดๆก็ได้ float SinWave(float x); Void SendWave(void); float x;// x is global variable void main(void) { float x; // x is local variable for(x=0;x<1.0;x+=0.1) { Output = SinWave(255.0,x); SendWave(); } } • void SinWave(float A,float t) • { • x = A*sin(2.0*3.14*t); // x is global variable • } • void SendWave(void) • { • PORTA = (char) x; // x is global variable • }
ตัวแปร Array void main(void) { int LED[] ={ 0b00000001, 0b00000010, 0b00000100, 0b00001000, 0b00010000, 0b00100000, 0b01000000, 0b10000000}; TRISAbits.TRISA0=1; TRISD = 0; PORTD = 0; ADCON1 = 0b00001110; ADCON2 = 0b10001010; ADCON0bits.ADON = 1; while(1) { ADCON0bits.GO=1; while(ADCON0bits.GO); result = ADRES; result >>=2; if(result==0) result = 1; PORTD=LED[shift]; shift++; shift %=8; Delay10KTCYx(result); } }
การจบคำสั่งและการเขียน comment • คำสั่งแต่ละคำสั่งจะต้องต่อด้วยเครื่องหมาย ; เสมอเช่น intx,y; x = A*sin(2.0*3.14*t); • การเขียน comment ทำได้ 2 วิธีคือ // comment ใช้ในกรณีที่ต้องการเขียนเพียงบรรทัดเดียว /* comment ใช้ในกรณีที่ต้องการเขียนหลายบรรทัด */