Giao tiếp LCD 16x2 chế độ 4 bit dữ liệu GIAO TIẾP MAX7219LED MA TRẬN ĐƠN SẮC 8x8 LẬP TRÌNH ĐIỀU KHIỂN LED 7 ĐOẠN 1 SỐ Điều khiển 6 led dùng 3 IO. BÀN PHÍM MA TRẬN 4x4 Đo điện áp 05000mV dùng bộ ADC, hiển thị LCD. NHIỆT KẾ ĐIỆN TỬ ADC 12 BIT MCP3204 TIMER BỘ ĐỊNH THỜI
Trang 1[HƯỚNG DẪN LẬP TRÌNH PIC CĂN BẢN]
BÀI 1: DIGITAL OUTPUT
GIAO TIẾP MAX7219-LED MA TRẬN ĐƠN SẮC 8x8
1 Phần cứng:
-Max7219 giao tiếp MCU bằng 3 IO:
DIN(1): Dữ liệu vào nối tiếp
LOAD(12): Chốt dữ liệu, cho phép hiển thị
CLK(13): Xung nhịp clock
-Đặc tính:
Quét led độc lập - không phụ thuộc vào vi điều khiển
Vi điều khiển chỉ việc đưa dữ liệu vào các thanh ghi nhớ ứng với từng digit (1 led 7 đoạn/ 1 hàng trong led ma trận)
Dữ liệu không bị mất khi chưa có dữ liệu mới được đưa vào
Tương tự như 74HC595, các IC Max7219 nối dữ liệu với nhau bằng cách nối Dout của IC trước với Din của IC sau
2 Phần mềm:
Khai báo tiền xử lý:
#define LOAD PIN_A1
#define CLK PIN_A2
#define DIN PIN_A0
#define NUM 3 //Số IC được sử dụng, cũng ứng với số led ma trận
Trang 3II CẤU TRÚC CƠ BẢN CỦA MỘT CHƯƠNG TRÌNH VIẾT TRÊN CCS:
1 Cấu trúc chung:
- Khai báo tiền xử lý:
- Các chương trình con
- Chương trình chính
> Ta đặt chương trình chính cuối cùng để tránh phải khai báo nhiều trong khai báo tiền xử lý
> Chương trình đứng phía dưới được phép gọi chương trình phía trên mà không cần khai báo chương trình cần gọi ở tiền xử lý
2 Khai báo tiền xử lý:
#include<device.h> //Khai báo thư viện biên dịch của PIC đang sử dụng ví dụ: #include<16F877A.h>
//Thư viện các dòng PIC chứa trong C:\Program Files\PICC\Devices
#device ADC=10 //Chỉ khai báo khi Chip có bộ chuyển đổi ADC 10bit
#fuses HS, NOWDT //Khai báo "cầu chì", cần chú ý khai báo HS là dùng dao động cao tần bên ngoài như thạch anh
//Nếu dùng dao động tần số thấp (<=4MHz), ta khai báo như sau: #fuses XT
//Nếu sử dụng dao động nội (chỉ Chip nào có hỗ trợ): #fuses XT, INTRC_IO
//Khai báo NOWDT không sử dụng "đồng hồ chó" WDT - chống treo Chip khi rơi vào vòng lặp chết
#use delay(clock=xM) //Khai báo tần số xung nhịp cấp cho core xử lý, x là tần số dao động (MHz) Ví dụ: #use delay(clock=20M)
//Nếu dùng dao động nội thì clock=4M
#define A B //Thay thế B bằng A, A sẽ mang mọi đặc tính của B Ví dụ #define LED PIN_A0 thay thế PIN_A0 bằng LED
BÀI 1: DIGITAL OUTPUT [TT]
I GIỚI THIỆU CÔNG CỤ LẬP TRÌNH, MÔ PHỎNG:
III CÁC LỆNH XỬ LÝ:
set_tris_x(8 bit value); //Nếu I.O cố định thì gọi hàm này 1 lần trong config
//Cài đặt các port x là ngõ vào/ra value ở binary, bit nào giá trị 1 là ngỏ vào, 0 là ngỏ ra
//VD: set_tris_a(0b00111001); port A có bit 0,3,4,5 là ngỏ vào, 1,2,6,7 là ngỏ ra
output_x(8 bit value); //Sử dụng khi có khai báo set_tris_x(); Có thể gọi nhiều lần
//Xuất ngỏ ra cho port x VD: ouput_a(0b01010101);
//bit mang giá trị 1 là mức cao (5V), mức thấp là 0V
output_high(PIN_name); //Xuất mức cao chân PIN_name VD: output_high(PIN_A0);
output_low(PIN_name); //Xuất mức thấp chân PIN_name VD: output_low(PIN_A0);
output_bit(PIN_name, x); //Xuất mức x ở chân PIN_name Mức thấp x=0, cao x=1
output_float(PIN_name); //Trạng thái ngỏ ra cao trở
> Khi ta set trạng thái thì trạng thái được giữ nguyên cho đến khi ta set trạng thái khác hoặc mất điện
delay_us(16 bit value); //Delay micro giây
delay_ms(16 bit value); //Delay mili giây
IV VÍ DỤ:
Trang 5BÀI 1: DIGITAL OUTPUT [TT]
I LẬP TRÌNH ĐIỀU KHIỂN LED 7 ĐOẠN 1 SỐ:
1 Xác định phần cứng:
- Xác định loại led 7 đoạn: âm cực chung (CC), dương cực chung (CA)
- Kết nối với IO vi điều khiển tuỳ ý sao cho dễ thi công mạch Chú ý sử dụng 1 port 8 IO để dễ điều khiển
2 VD mẫu:
Điều khiển 1 led 7 đoạn CA kết nối port B của PIC16F877A, hiển thị từ 0 đến 9 Các bước thực hiện như sau: Qui định IO:
Bit 0: A Bit 1: B Bit 2: C Bit 3: D
Bit 4: A Bit 5: E Bit 6: F Bit 7: DP
Bit 0: A Bit 1: B Bit 2: C Bit 3: D
Bit 4: A Bit 5: E Bit 6: F Bit 7: DP
PIN_C0: CA0 PIN_C1: CA1
Quét led thực tế là cho lần lượt từng led 7 đoạn sáng - tại 1 thời điểm chỉ có 1 led 7 đoạn sáng, thời gian thay đổi giữa các
led rất nhỏ (vài us/ms) nên mắt không phân biệt được và thấy chúng sáng đồng thời
Mắt chỉ phân biệt được dao động <22Hz, trên 22Hz ta thấy vật dao động đứng im
Trang 6set_tris_b(0x00);
unsigned char i=0, count=0, chuc, dv; //Các biến
while(true)
{
chuc=i/10; // i là số nguyên, phép "/" là chia lấy phần nguyên
dv=i%10; // i là số nguyên, phép "%" là chia lấy phần dƣ
output_low(PIN_C1); //Tắt led hàng đơn vị
output_b(ma_7doan[chuc]); //Xuất mã hàng chục
output_high(PIN_C0); //Cho phép led hàng chục sáng
delay_ms(1); //Tạo trễ để nhìn thấy led sáng
output_low(PIN_C0); //Tắt led hàng chục
output_b(ma_7doan[dv]); //Xuất mã hàng đơn vị
output_high(PIN_C1); //Cho phép hàng đv sáng
delay_ms(1); //Tạo trễ để hiển thị
count++; //Cho biến đếm tự tăng 1 đơn vị
if(count==250) //Khi biến đếm =250 ứng với 500ms do 2 lệnh delay_ms(1) phía trên hết 2 ms {
i++; //Tăng i lên 1 đơn vị
if(i>=100) i=0; //Khi i>=100 thì reset về 0 Tức mạch đếm từ 00-99
count=0; //Reset biến đếm sau 250 lần đếm
}
}
}
BÀI 1: DIGITAL OUTPUT [TT2]
I Giao tiếp LCD 16x2 chế độ 4 bit dữ liệu:
1 Kết nối phần cứng:
Trang 7unsigned char string[17];
Các config trong void main():
sprintf(string,"chuỗi cần hiển thị %kiểu dữ liệu",biến dữ liệu);
LCD_Gotoxy(vị trí, hàng);//Chữ được in ra từ vị trí 0-15, hàng(trên là 0, dưới là 1)
LCD_Puts(string);//Gửi dữ liệu trong mảng string lên LCD để hiển thị ra
Hiển thị chữ "DEE-TDTu" ở chính giữ, hàng trên
Hiển thị chữ "CLB Dien Tu TEC" ở hàng dưới trong vòng 2s
Đếm từ 0-99 ở hàng dưới, hàng trên giữ nguyên
Trang 874HC595 kết nối với vi điều khiển qua 3 chân:
SH_CP(11): Chân xung nhịp clock
ST_CP(12): Chân chốt dữ liệu - cho phép xuất dữ liệu trong thanh ghi tạm ra các chân
DS(13): Chân nhận dữ liệu nối tiếp
> Giúp mở rộng ngỏ ra số cho vi điều khiển
> Đồng bộ hoá dữ liệu đầu ra Vào nối tiếp, ra song song
2 Phần mềm:
Khai báo tiền xử lý:
#define EXP_OUT_ENABLE PIN_A2 //Chân ST_CP
#define EXP_OUT_CLOCK PIN_A0 //Chân SH_CP
#define EXP_OUT_DO PIN_A1 //Chân DS
#define NUMBER_OF_74595 2 //Số IC sử dụng IC nào có chân DS nối với MCU là IC thứ 0, kế tiếp
Trang 9#include <12F629.h>
#fuses XT, INTRC_IO, NOMCLR, NOWDT
#use delay(clock=4M)
#define EXP_OUT_ENABLE PIN_A2
#define EXP_OUT_CLOCK PIN_A0
#define EXP_OUT_DO PIN_A1
Trang 10Trạng thái này hỗ trợ cho việc quét led, các giao tiếp cần trạng thái thứ 3, chuyển mạch
Sử dụng tối ƣu các IO hơn
Khi sử dụng, không cần khai báo gì khác, chỉ việc gọi hàm output_float(IO_name);
VD: output_float(PIN_A0);// Cho ngỏ ra chân A0 ở trạng thái cao trở
VD: Điều khiển 6 led dùng 3 IO
BÀI 2: DIGITAL INPUT
Khai báo tiền xử lý:
/*Sử dụng cho ngỏ vào là 1 port*/
Trang 11#use fast_io(port) //Khai báo sử dụng port vừa vào vừa ra
#bit name=pin_address // Đặt tên 1 bit cụ thể của port
> port A,B,C,D,E có địa chỉ lần lượt là: 0x05,0x06,0x07,0x08,0x09
> pin của port có địa chỉ từ 0-7
VD: Ta muốn đặt tên in5 cho chân số 5 của port C ta khai báo như sau:
#bit in5=0x07.5
/*Sử dụng ngỏ vào là IO bất kì*/
Không khai báo gì
Khai báo config:
set_tris_port(8 bit value);//Sử dụng cho ngỏ vào port hoặc bit của port
> Thanh ghi tris sẽ qui định IO tương ứng là vào khi nhận bit giá trị 1 và ra khi nhận bit giá trị 0 VD: Qui định C là port vào 8 bit: set_tris_c(0xff);
Qui định C là port vào 3 bit đầu: set_tris_c(0x07);
> Sử dụng ngỏ vào là IO bất kỳ ta không cần khai báo config
Các lệnh xử lý:
/*Sử dụng cho ngỏ vào là 1 port*/
byte value=ingput_port(); //Lưu giá trị ngỏ vào port vào biến value có kiểu dữ liệu là byte int1 value=pin_address; //Lưu giá trị của pin cụ thể của port vào viến value có kiểu dữ liệu 1 bit /*Sử dụng ngỏ vào là IO bất kì*/
int1 value=input(PIN_name); //Lưu giá trị của IO vào biến value kiểu 1 bit
VD mẫu: Sử dụng PIC16F877A
Dùng 1 IO E1 để bật tắt 1 đèn nối với PIN_B0 của port B
Dùng port C để bật tắt các đèn tương ứng của port D
Dùng pin 3,4,5 để bật tắt đèn nối với pin 0,1,2 của port A
Trang 13BÀI 2: DIGITAL INPUT [TT1]
BÀN PHÍM MA TRẬN 4x4
1 Phần cứng:
- Bàn phím ma trận là 1 giải pháp giúp tiết kiệm IO vi điều khiển
- Cấu tạo phím ma trận 4x4 gồm: 4 IO hàng và 4 IO cột và kết nối như hình vẽ
- Với 8 IO ta có thể tạo ra 16 phím bấm, nếu sử dụng IO riêng lẻ ta phải dùng 16 IO
2 Phần mềm:
Chép và ghi đè file key_4x4.c đính kèm file PDF này vào "C:\Program Files\PICC\Drivers"
- Phương pháp điều khiển:
Ở ví dụ này, ta dùng 4 hàng phát xung và 4 cột nhận xung
Các IO hàng đặt ở chế độ output, 4 IO cột cở chế độ input
Ta lần lượt cho các IO hàng lên mức cao Cứ mỗi lần như thế ta lại kiểm tra 4 IO cột Nếu cột nào có mức logic cao, tức nút
được nhấn thì trả về giá trị cột và giá trị hàng tại thời điểm đó
Dựa vào thông số trả về, ta quy định giá trị phím nhấn
- Khai báo tiền xử lý:
#define ROW1 PIN_C0
#define ROW2 PIN_C1
#define ROW3 PIN_C2
#define ROW4 PIN_C3
#define COL1 PIN_C4
#define COL2 PIN_C5
#define COL3 PIN_C6
#define COL4 PIN_C7
Trang 14/*Giao tiep phim ma tran*/
#define ROW1 PIN_C0
#define ROW2 PIN_C1
#define ROW3 PIN_C2
#define ROW4 PIN_C3
#define COL1 PIN_C4
#define COL2 PIN_C5
#define COL3 PIN_C6
#define COL4 PIN_C7
if(code=='C') output_low(RST); //Nếu mã phím là C thì cho chân RST tích cực
else if((code!=temp)&&(code!=' ')) //Ngược lại, nếu mã phím khác mã trước đó và khác mã khoảng trống thì in mã mới ra LCD
Trang 15BÀI 3: ANALOG INPUT
I Giới thiệu:
- Một số dòng PIC có hỗ trợ bộ chuyển đổi tín hiệu tương tự sang số với độ phân giải 8/10 bit
- Bộ chuyển đổi tương tự sang số gọi là ADC (Analog to Digital Converter)
- Ý nghĩa:
> Nhiều bạn chưa học xử lý số tín hiệu nên AD tạm giải thích như sau:
+ Độ phân giải (số bit phân giải) là 8 hoặc 10bit, tức có 2^8=256 hoặc 2^10=1024 giá trị số được chuyển đổi (số bậc phân giải)
+ Áp tham chiếu: Là điện áp chuẩn, lớn nhất, điện áp này được chia đều cho số bậc phân giải
VD minh hoạ với độ phân giải là 2 bit (4 bậc phân giải) Áp tham chiếu Vref=9V
Giá trị analog Giá trị số
9V 3
6V 2
3V 1
0V 0
Ta thấy, nếu ngỏ vào [0V;3V) ADC=0, [3V;6V) ADC=1, [6V;9V) ADC=2, [9V; ) ADC=3
> Với PIC, giá trị ADC min=Vfref-=0, ADC max=Vref+
Công thức chung để tính giá trị mỗi bậc ADC của PIC là:
Vref/((2^bit)-1)
II Phần cứng:
- Cần kiểm tra datasheet xem chip sử dụng có bộ ADC hay không
- Một số dòng PIC, ADC chỉ có 8 bit, hầu hết là có 2 độ phân giải 8/10 bit
- Trong Proteus, chân ANx là chân vào của tín hiệu analog Một chip có thể có nhiều ngỏ vào analog
- Với PIC, áp tham chiếu tối đa là 5V, nếu sử dụng áp khác thì cần cấp áp chuẩn vào chân có kí hiệu Vref
III Phần mềm:
1 Khai báo tiền xử lý:
#device ADC=8 //Chế độ 8 bit
#device ADC=10 //Chế độ 10 bit
> Khai báo ngay sau khai báo #include<device.h> và trước khai báo #fuses
2 Khai báo config:
setup_adc(ADC_CLOCK_INTERNAL); //Chu kỳ lấy mẫu 2-6us
setup_adc_ports(pin name); //Chọn port vào analog Tối đa 2 port, phân cách bằng dấu phẩy
set_adc_channel(value); //Đi chung với setup_adc_port() tương ứng Chỉ khai báo lệnh này khi dùng 1 port analog
> Xem trong file device.h
3 Hàm lấy giá trị ADC:
/*Dùng 1 port analog*/
delay_us(20); //Delay tối thiểu để lấy mẫu
float value=read_adc();
/*Dùng 2 port analog*/
set_adc_channel(x);
delay_us(20);
float value1=read_adc();
set_adc_channel(y);
delay_us(20);
float value2=read_adc();
/*Dùng trên 2 port analog*/
setup_adc_ports(pin name);
set_adc_channel(x);
delay_us(20);
float value2=read_adc();
Trang 16float temp, adc;
unsigned int16 vol;
adc=read_adc(); //Đọc giá trị ADC
temp=(5000*adc)/1023; //Chuyển về giá trị điện áp (mV)
vol=(unsigned int16)temp; //Lấy phần nguyên của số thực temp sprintf(string,"%04ld %04ldmV",(unsigned int16)adc, vol);
Trang 17- Để đo được nhiệt độ bằng phương pháp điện tử, ta phải chuyển năng đại lượng nhiệt (dạng phi điện)
về dạng tín hiệu điện với một
tỉ lệ chuyển đổi tương đối tuyến tính Phương pháp chuyển đổi này là cơ sở hình thành cảm biến mà cụ thể ở đây là cảm biến nhiệt
- Trên thị trường có nhiều loại cảm biến nhiệt với cấu tạo và phương thức chuyển đổi sang tín hiệu điện khác nhau Khá phổ biến
hiện nay là cảm biến nhiệt LM35
Đo nhiệt độ dùng LM35 với các yêu cầu sau:
+ Hiển thị led 7 đoạn 4 số
+ Tầm đo 0-99 độ C Vượt quá sẽ báo lỗi
#define CA1 PIN_B4 //Pin lái cực dương led hàng nghìn
#define CA2 PIN_B5 //Pin lái cực dương led hàng trăm
#define CA3 PIN_B6 //Pin lái cực dương led hàng chục
#define CA4 PIN_B7 //Pin lái cực dương led hàng đv
#define LOW output_low
#define HIG output_high
unsigned char ma_7doan[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xd8,0x80,0x90}; //Mã led 7 đoạn
unsigned char digit[4]; //Mảng nhớ mã hiển thị cho từng led 7 đoạn
Trang 18Đọc adc và chuyển giá trị adc sang nhiệt độ
Cứ 10mV thì đƣợc 1 độ C Tầm toàn thang Vref= 5V= 5000mV thì đo đƣợc 500 độ Vậy ta xem nhƣ tầm toàn thang Vref= 500 thì công thức tính nhiệt độ nhƣ sau: to=(Vref*adc)/1023=(500*read_adc())/1023;
*/
temp=0.5+((500.0*read_adc())/1023.0); //Cộng 0.5 là làm tròn đến hàng đơn vị doC=(unsigned int8) temp; //Lấy phần nguyên của nhiệt độ
count=0; //Reset biến đếm
Trang 19sử dụng IC ADC chuyên dụng để kết nối với PIC Bài viết hôm nay, mình xin giới thiệu IC MCP3204 là IC
ADC 12 bit do Microchip sản
xuất
- Thông số kỹ thuật:
+ 12 bit ADC
+ 4 kênh ngỏ vào analog
+ Cho phép sử dụng áp tham chiếu khác áp nguồn
+ Giao tiếp 4 dây theo kiểu giao tiếp SPI - sẽ tìm hiểu kỹ các phần sau, nhƣng về cơ bản ta cần kết nối IC với PIC bằng 4 IO
bất kỳ với các chức năng: IO tạo xung clock, IO cho phép, IO dữ liệu vào, IO dữ liệu ra Về bản chất, giữa PIC
và IC ADC chỉ
truyền nhận tín hiệu số
+ Nguồn nuôi 5VDC
II Lập trình:
CCS đã hỗ trợ sẵn thƣ viện giao tiếp nên ta không cần phải "sáng tạo" làm gì
Thƣ viện chứa tại: "C:\Program Files\PICC\Drivers\mcp3204.c"
1 Khai báo tiền xử lý:
#define MCP3204_CLK PIN_B0 //IO xung nhịp
#define MCP3204_DIN PIN_B1 //IO ghi dữ liệu
Trang 20#define MCP3204_DOUT PIN_B2 //IO nhận dữ liệu
#define MCP3204_CS PIN_B3 //IO chọn chip
#define MCP3204_DIN PIN_B1
#define MCP3204_DOUT PIN_B2
#define MCP3204_CS PIN_B3
#include<MCP3204.c>
unsigned char string[17];
unsigned int32 vol;
temp=read_analog_mcp(i,1); //Đọc giá trị ADC ở channel thứ i
temp=0.5+((temp*5000)/4095); //Tính giá trị điện áp (mV) và làm tròn đến hàng đv
vol=(unsigned int32)temp; //Lấy phần nguyên của giá trị
Trang 21[HƯỚNG DẪN LẬP TRÌNH PIC CĂN BẢN]
BÀI 4: TIMER - BỘ ĐỊNH THỜI
I Giới thiệu:
- Tốc độ xử lý của PIC16 tối đa là 5 MIPS (Million Instructions Per Second) tức 5 triệu
lệnh mỗi giây ứng với nguồn cấp xung 20MHz
- PIC16 có tốc độ core xử lý (fcore) bằng ¼ tốc độ nguồn cấp xung nhịp (fosc) Tức xung
nhịp cấp cho PIC hoạt động được đưa qua bộ chia 4 trước khi đưa vào core
Bộ định thời của PIC16 hoạt động dựa trên xung nhịp core xử lý Tuy nhiên, PIC
không dùng trực tiếp xung nhịp của core để định thời mà đưa nó qua một bộ chia
trước gọi là prescaler Sau khi qua bộ chia trước, xung nhịp mới được cấp vào thanh
ghi định thời Vậy xung nhịp từ nguồn xung đến được thanh ghi định thời có tốc độ
là:
Cứ 1 xung nhịp (ftimer) thì giá trị thanh ghi tăng lên 1 Khi thanh ghi đạt giá trị max mà
tiếp tục có xung nhịp thì cờ tràn định thời sẽ được set