Hướng dẫn sử dụng trình biên dịch CCS cho lập trình PIC
Sự ra đời của một loại vi điều khiển đi kèm với việc phát triển phần mềm ứng dụng cho
việc lập trình cho con vi điều khiển đó. Vi điều khiển chỉ hiểu và làm việc với hai con số 0
và 1. Ban đầu để việc lập trình cho VĐK là làm việc với dãy các con số 0 và 1. Sau này khi
kiến trúc của Vi điều khiển ngày càng phức tạp, số luợng thanh ghi lệnh nhiều lên, việc lập
trình với dãy các số 0 và 1 không còn phù hợp nữa, đòi hỏi ra đời một ngôn ngữ mới thay
thế. Và ngôn ngữ lập trình Assembly. Ở đây ta không nói nhiều đến Assmebly. Sau này khi
ngôn ngữ C ra đời, nhu cầu dùng ngôn ngữ C đề thay cho ASM trong việc mô tả các lệnh
lập trình cho Vi điều khiển một cách ngắn gọn và dễ hiểu hơn đã dẫn đến sự ra đời của
nhiều chương trình soạn thảo và biên dịch C cho Vi điều khiển : Keil C, HT‐PIC, MikroC,
CCS
Tôi chọn CCS cho bài giới thiệu này vì CCS là một công cụ lập trình C mạnh cho Vi
điều khiển PIC. Những ưu và nhược điểm của CCS sẽ được đề cập đến trong các phần
dưới đây.
5/PSP5 RB0/INT
30 RD6/PSP6
33pF RD7/PSP7 4
RA2/AN2 5
RA3/AN3 6
RA4 7 Q3
Crystal 13 RA5/AN4 8 4K7
14 OSC1/CLKI RE0/AN5 9
OSC2/CLKO RE1/AN6
15 10 SPEAKER
33pF 16 RC0/T1CKI RE2/AN7
17 RC1/CCP2
HI
18 RC2/CCP1
4K7 19 RC3/SCK/SCL
20 RD0/PSP0 32
4K7 RD1/PSP1 VDD1 31
VSS1 2
HI
3 3
11 RA1/AN1 2 VR10K
VDD RA0/AN0 1 LM335Z
12 VPP 10K
VSS
1K 1
HI
HI HI
Hình 3.4. Mạch đo nhiệt độ hiển thi trên LED 7 thanh
Trong mạch trên ta dùng chính con PIC cho việc giải mã LED 7 thanh. Nguyên tắc quét
cho từng LED 7 thanh là gửi giá trị cần hiển thị ‐> bật LED ‐> Tạo thời gian trễ ‐> tắt LED.
Quá trình cứ lặp lại như vậy cho đến khi quét hết LED. Ta tính toán thời gian trễ sao cho
đảm bảo các số hiển thị liên tục.
Người báo cáo: Nguyễn Chí Linh Tài liệu: TUT01.01.PVN
Ngày: 9/8/2006 Trang: 24/32
3.3. Giao tiếp máy tính RS232
Việc giao tiếp giữa Vi điều khiển và máy tính là bài lập trình khá quan trọng khi ta làm
việc với các dòng Vi điều khiển khác nhau. Với Vi điều khiển PIC cũng vậy, trong mỗi IC
PIC đều có tích hợp một khối giao tiếp máy tính USART. Ta sử dụng khối giao tiếp này để
truyền dữ liệu lên máy tính và xử lý dữ liệu đó tùy vào mục đích của người lập trình. Để
nhận dữ liệu do Vi điều khiển truyền lên máy tính ta có thể sử dụng các phần mềm giao
tiếp COM có sẵn hay viết một chương trình mới, sử dụng các ngôn ngữ lập trình như C++,
VB hay Delphi… Trong chương trình ví dụ dưới đây tôi sử dụng công cụ sẵn có của CCS là
Serial Port Monitor để truyền và nhận dữ liệu từ PIC.
Sơ đồ mạch điện ORCAD. Mạch sử dụng IC MAX232 để kết nối đến cổng COM của
máy tính. Mạch đơn giản chỉ nhằm mục đích giới thiệu khối giao tiếp máy tính của PIC và
cách lập trình cho nó trong CCS.
LCD - 16x2 - DM1602A
K A D7 D6 D5 D4 D3 D2 D1 D0 E R/W RS VEE VCC VSS
LCD_1602A
16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
D4
D5
D6 RW
D7 E RS
VCC
RS 21 40
RW
U14 E 22 RD2/PSP2 RB7/PGD 39
23 RD3/PSP3 RB6/PGC 38
TX_PC 13 12 RX_PIC 24 RC4/SDI/SDA RB5 37
8 R1IN R1OUT 9 TX_PIC 25 RC5/SDO RB4 36
R2IN R2OUT RX_PIC 26 RC6/TX/CK RB3/PGM 35
TX_PIC 11 14 RX_PC D4 27 RC7/RX/DT RB2 34
10 T1IN T1OUT 7 D5 28 RD4/PSP4 RB1 33
C9 1uF T2IN T2OUT D6 29 RD5/PSP5 RB0/INT
1 D7 30 RD6/PSP6
1uF C8 3 C1+ 33pF RD7/PSP7 4
4 C1- RA2/AN2 5
VCC 5 C2+ RA3/AN3 6
C10 2 C2- 20MHz RA4 7
6 V+ 13 RA5/AN4 8
C7 V- 14 OSC1/CLKI RE0/AN5 9
1uF 15 OSC2/CLKO RE1/AN6 10
MAX232 33pF 16 RC0/T1CKI RE2/AN7
17 RC1/CCP2
1uF 18 RC2/CCP1
19 RC3/SCK/SCL
20 RD0/PSP0 32
RD1/PSP1 VDD1 31
VSS1
HI
3
11 RA1/AN1 2
VDD RA0/AN0 1
12 VPP 10K
VSS
HI
HI
Hình 3.5. Mạch giao tiếp máy tính, hiển thị LCD
Người báo cáo: Nguyễn Chí Linh Tài liệu: TUT01.01.PVN
Ngày: 9/8/2006 Trang: 25/32
Mã nguồn chương trình:
#include
#include
#use delay(clock=20000000)
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT,
NOLVP, NOCPD, NOWRT
// Khai báo sử dụng giao tiếp nối tiếp RS232
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
#include
int8 count=0;
char string_in[16];
#INT_RDA // Hàm xử lý ngắt nối tiếp
Receive_isr() {
char c;
int8 i;
count++;
c = getc();
putc(c);
if (c==ʹcʹ | c==ʹCʹ)
{
LCD_putcmd(0x01); //Clear Screen
c=ʹcʹ;
count=0;
}
if ((count<=16) && (c!=ʹcʹ)) LCD_putchar(c);
if (count > 16)
{
count=0;
LCD_putcmd(0xC0);
}
}
void main()
{
Người báo cáo: Nguyễn Chí Linh Tài liệu: TUT01.01.PVN
Ngày: 9/8/2006 Trang: 26/32
enable_interrupts(int_rda);
enable_interrupts(GLOBAL);
lcd_init(); // Khởi tạo cho LCD
lcd_putcmd(0x01);
lcd_putcmd(line_1);
printf(ʺEnter a String.ʺ);
printf(ʺOr anything you want!ʺ);
while (1) {}
}
Mô tả chương trình: Trên đây là chương trình giao tiếp với máy tính, ta thấy trong CCS để
sử dụng giao tiếp nối tiếp ta chỉ cần khai báo #use rs232(). Các hàm giao tiếp với máy tính mà
CCS hỗ trợ là:
‐ putc(char ky_tu) : Gửi một ký tự ASCII lên máy tính
‐ getc() : Hàm trả về một ký tự nhận được từ máy tính
‐ printf(string): hàm gửi một chuỗi ký tự lên máy tính
Trong chương trình ta có sử dụng hàm xử lý ngắt nối tiếp để xử lý ký tự nhân được từ máy
tính. Khi có ngắt xảy ra, ta gọi hàm getc() sẽ trả về ký tự vừa nhận được. Trên màn hình LCD
sẽ hiển thị ký tự mà ta gõ từ bàn phím máy tính.
Người báo cáo: Nguyễn Chí Linh Tài liệu: TUT01.01.PVN
Ngày: 9/8/2006 Trang: 27/32
3.4. Ngắt của PIC và cách sử dụng
Trong Vi điều khiển PIC có nhiều nguồn ngắt. Để biết cụ thể ta có thể vào mục
View >> Valid Interrupts . Khi đó một của sổ sẽ hiện ra liệt kê đầy đủ các nguồn
ngắt của từng con PIC.
Hình 3.6 Các nguồn ngắt trong PIC
Để viết một hàm phục vụ ngắt ta chỉ việc thêm khai báo #INT_tên_ngắt vào
trước hàm phục vụ cho ngắt đó. Khi đó trình dich sẽ hiểu đó là địa chỉ hàm cho
ngắt, khi có ngắt tương ứng xảy ra thì nó sẽ nhảy đến vị trí đó
Lấy ví dụ khi ta muốn xử lý ngắt ngoài, hàm sẽ được viết như sau:
#INT_EXT
Ext_isr()
{
// Nhập mã tại đây
}
Dưới đây là chương trình nháy led theo nhiều kiểu khác nhau, sử dụng 1 phím
bấm nối với chân ngắt ngoài RB0 để chọn kiểu nháy. Có 8 kiểu nháy LED khác nhau,
Khi đến kiểu nháy thứ 8, nếu ta nhấn thì sẽ trở về chế độ ban đẩu. Ban đầu biến mode = 0
Người báo cáo: Nguyễn Chí Linh Tài liệu: TUT01.01.PVN
Ngày: 9/8/2006 Trang: 28/32
và tất cả các LED đều tắt Mỗi khi nhấn phím bấm, biến mode sẽ tăng lên 1 đơn vị. Giá trị
biến mode tương ứng với chương trình nháy được thực hiện. Khi mode = 9 thì sẽ được gán
về mode = 0. Các kiểu nháy khác nhau là do ta bật tắt các LED trên cổng D theo các cách
khác nhau. Lấy ví dụ khi ta muôn các LED nháy xen kẽ nhau ta chỉ việc gửi ra cổng D giá
trị AAh (10101010) và 55h (01010101).
Sơ đồ mạch điện:
VCC
R10
R
SW1
Phim chon
33 15
34 RB0/INT RC0/T1OSO/T1CKI 16
35 RB1 RC1/T1OSI/CCP2 17 D8 R8
R9 36 RB2 RC2/CCP1 18 LED1
RESET 37 RB3/PGM RC3/SCK/SCL 23 D7 R7
VCC
38 RB4 RC4/SDI/SDA 24 LED2
10K 39 RB5 RC5/SDO 25 LEDD6 220R6
40 RB6/PGC RC6/TX/CK 26 LED3
RB7/PGD RC7/RX/DT LEDD5 RR5
Cong tac 2 19 LED1 LED4
3 RA0/AN0 RD0/PSP0 20 LED2 LEDD4 RR4
4 RA1/AN1 RD1/PSP1 21 LED3 LED5
5 RA2/AN2/VREF-/CVREF RD2/PSP2 22 LED4 LEDD3 RR3
6 RA3/AN3/VREF+ RD3/PSP3 27 LED5 LED6
7 RA4/T0CKI/C1OUT RD4/PSP4 28 LED6 LEDD2 RR2
RA5/AN4/SS/C2OUT RD5/PSP5 29 LED7 LED7
OSC1 13 RD6/PSP6 30 LED8 LEDD1 RR1
OSC2 14 OSC1/CLKI RD7/PSP7 LED8
OSC2/CLKO 8 LED R
OSC1 OSC2 RESET 1 RE0/RD/AN5 9
Y1 MCLR/VPP RE1/WR/AN6 10 LED R VCC
RE2/CS/AN7
12 11
VCC
31 VSS VDD 32
VSS VDD
20MHz
C1 C2
22p 22p
Hình 3.7. Nháy LED nhiều chế độ
Phần mã nguồn chương trình:
#include
#include
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT,
NOLVP, NOCPD, NOWRT
#use delay(clock=20000000)
int8 mode,i;
byte temp;
Người báo cáo: Nguyễn Chí Linh Tài liệu: TUT01.01.PVN
Ngày: 9/8/2006 Trang: 29/32
#INT_EXT
EXT_ISR() {
mode++;
if (mode==9) mode = 0;
}
// End of INT
void program1();
void program2();
void program3();
void program4();
void program5();
void program6();
void program7();
void program8();
void main() {
trisd = 0x00;
trisb = 0xFF;
portd=0xff;
enable_interrupts(int_EXT);
ext_int_edge(H_TO_L); // Chọn ngắt theo sườn âm
enable_interrupts(GLOBAL);
mode = 0;
while (1) {
switch(mode) {
case 1: program1(); break;
case 2: program2(); break;
case 3: program3(); break;
case 4: program4(); break;
case 5: program5(); break;
case 6: program6(); break;
case 7: program7(); break;
case 8: program8(); break;
}
}
}
void program1() {
Người báo cáo: Nguyễn Chí Linh Tài liệu: TUT01.01.PVN
Ngày: 9/8/2006 Trang: 30/32
PortD = 0x00;
delay_ms(250);
Portd = 0xFF;
delay_ms(250);
}
void program2() { // LED sáng chạy từ trái qua phải
temp = 0xFF;
for (i=0;i<=8;i++) {
portd = temp;
delay_ms(250);
temp >>= 1;
}
}
void program3() { // LED sáng chạy từ phải qua trái
temp = 0xFF;
for (i=0;i<=8;i++) {
portd = temp;
delay_ms(250);
temp <<= 1;
}
}
void program4() {
portd = 0xAA;
delay_ms(500);
portd = 0x55;
delay_ms(500);
}
void program5() {
Portd = 0x7E; delay_ms(150);
Portd = 0xBD; delay_ms(250);
Portd = 0xDB; delay_ms(150);
Portd = 0xE7; delay_ms(150);
Portd = 0xDB; delay_ms(150);
Portd = 0xBD; delay_ms(150);
Portd = 0x7E; delay_ms(150);
}
void program6() {
temp = 0xFF;
for (i=0;i<=8;i++) {
portd = temp;
delay_ms(250);
Người báo cáo: Nguyễn Chí Linh Tài liệu: TUT01.01.PVN
Ngày: 9/8/2006 Trang: 31/32
temp = temp >> 1;
}
}
void program7() {
Portd = 0xFE; delay_ms(150);
Portd = 0xFD; delay_ms(150);
Portd = 0xFB; delay_ms(150);
Portd = 0xF7; delay_ms(150);
Portd = 0xEF; delay_ms(150);
PortD = 0xDF; delay_ms(150);
Portd = 0xBF; delay_ms(150);
Portd = 0x7F; delay_ms(150);
}
void program8() {
Portd = 0x7F; delay_ms(150);
Portd = 0xBF; delay_ms(150);
PortD = 0xDF; delay_ms(150);
Portd = 0xEF; delay_ms(150);
Portd = 0xF7; delay_ms(150);
Portd = 0xFB; delay_ms(150);
Portd = 0xFD; delay_ms(150);
Portd = 0xFE; delay_ms(150);
}
Người báo cáo: Nguyễn Chí Linh Tài liệu: TUT01.01.PVN
Ngày: 9/8/2006 Trang: 32/32
3.5. Bộ Đếm/Định thời (Timer)
3.6. Giao tiếp I2C, SPI
3.7. PWM, Capture, Comparator File đính kèm:
hướng dẫn sử dụng trình biên dịch CCS cho lập trình PIC.pdf

