BÀI TẬP THỰC HÀNH

Một phần của tài liệu Giáo trình vi điều khiển PIC16F và ngôn ngữ lập trình HITECH C, Giáo trình dùng cho sinh viên ngành Cơ điện tử Nguyễn Trường Thịnh, Nguyễn Tấn Nó (Trang 34)

Bài 1: Viết chương trình điều khiển led theo yêu cầu sau:

 Nhấn (không giữ) nút nhấn nối với chân RB0: led RE1 và led RE2 chớp tắt xen kẽ trong thời gian T=0.2(s).

 Nhấn (không giữ) nút nhấn nối với chân RB1: led RE1 và led RE2 cùng chớp tắt trong thời gian T=0.5(s).

 Nhấn (không giữ) nút nhấn nối với chân RB2: led RE1 sáng và led RE2 tắt trong thời gian T=0.1(s), led RE1 tat và LED2 sáng T=0.7(s).

Sơ đồ phần cứng:

* Bước 1: Tạo một project mới với tên 01_01_MSSV.

* Bước 2: Nhập chương trình sau vào máy tính và hoàn thành các dấu … #include<htc.h>

__CONFIG(INTIO&WDTDIS &MCLREN&BORDIS&LVPDIS);

void delay(unsigned char counter); //Khai báo chương trình con

void RB_0();void RB_1();void RB_2(); char so_lan_nhan;

void main() //Chương trình chính

{

//Disable analog ở các chân RE1,RE2,RB0,RB1,RB2

ANS6=ANS7=ANS12=ANS10=ANS8= …….;

//Khởi tạo các chân RE1,RE2 là ngõ ra, ban đầu led tắt

TRISE1=TRISE2= …….; RE1=RE2= …….;

//Khởi tạo chân RB0,RB1,RB2 là ngõ vào, tác động mức thấp

TRISB0=TRISB1=TRISB2= …….; RB0=RB1=RB2= …….;

//Khởi tạo điện trở kéo lên ở các chân RB0,RB1,RB2

WPUB0=WPUB1=WPUB2= …….; RBPU= …….; //(---1---) while(1) { //Xác định trạng thái các nút nhấn if(!RB0)so_lan_nhan=0; //(---2---) else if(!RB1)so_lan_nhan=1; //(---3---) else if(!RB2)so_lan_nhan=2; //(---4---) if (so_lan_nhan==0)

RB_0(); //Chạy chương trình con RB_0

else if(so_lan_nhan==1)

RB_1(); //Chạy chương trình con RB_1

else if(so_lan_nhan==2)

} }

//(---5---)

void delay(unsigned char counter) //Chương trình con làm tăng thời gian delay

{

unsigned char value=0; while(counter>value)

{

value++;

_delay(100000); //trễ 1ms với Fosc = 4MHz

} }

void RB_0()

{

RE1^=1;RE2= …….RE1; // led RE1 và led RE2 chớp tắt xen kẽ

delay(2); //delay 0.2s

}

void RB_1()

{

RE1^=1;RE2 …….RE1; // led RE1 và led RE2 cùng chớp tắt

delay(5); //delay 0.5s

}

void RB_2()

{

RE1= …….;RE2= …….; // led RE1 sáng và led RE2 tắt

delay(1); //delay 0.1s

RE1= …….;RE2= …….; // led RE1 tat và LED2 sáng

delay(7); //delay 0.7s

*Bước 3: Biên dịch chương trình, nạp xuống kít thí nghiệm, tiến hành

nhấn các nút nhấn và quan sát 2 led.

*Bước 4: Thay đổi chương trình như sau:

 Thêm vào dòng: (---1---) đoạn code sau: IOCB0=IOCB1=IOCB2=1; //Cho phép ngắt onchange. RBIE=1; //Cho phép ngắt onchange toàn PORTB

RBIF=0; //Reset cờ ngắt

PEIE=1; //Cho phép ngắt ngoại vi

GIE=1; //Cho phép ngắt toàn cục  Xóa các dòng 2,3,4.

 Thêm vào dòng: (---5---) đoạn code sau:

void interrupt isr() //Chương trình con xử lý tất cả ngắt

{

if(RBIE&&RBIF) //Chương trình con cho ngắt on-change

{

if(!RB0) so_lan_nhan=0; //nhấn RB0

else if(!RB1) so_lan_nhan=1; //nhấn RB1

else if(!RB2) so_lan_nhan=2; //nhấn RB2

RBIF=0; //Reset cờ ngắt

} }

*Bước 5: Biên dịch chương trình, nạp xuống kít thí nghiệm, tiến hành

nhấn các nút nhấn và quan sát 2 led.

*Bước 6: Nhận xét sự khác nhau về tốc độ đáp ứng khi nhấn nút nhấn

trước và sau khi sửa code, giải thích, rút ra kết luận:

……… ……… ……… ……… ……… ……… ……… ………

……… ……… ………...

Bài 2: Viết chương trình điều khiển led theo yêu cầu sau:

 Nhấn (không giữ) nút nhấn nối với chân RB0 lần (2n+1): 8 led dịch từ trái qua phải.

 Nhấn (không giữ) nút nhấn nối với chân RB0 lần (2n): 8 led dịch từ phải qua trái.

n = 0,1,3,4,5…k

Sử dụng định thời bằng hàm _delay(n); thạch anh Fosc = 4 Mhz.  Sơ đồ phần cứng:

* Bước 1: Tạo một project mới với tên 01_02_MSSV.

* Bước 2: Nhập chương trình sau vào máy tính và hoàn thành vào dấu … #include<htc.h>

__CONFIG(INTIO&WDTDIS&MCLREN&BORDIS&LVPDIS);

char count=0;

void display(char number); void main()

{

//Disable analog các chân RE1,RE2,RB0,RB3,RB4,RB5

ANS6=ANS7=ANS9=ANS11=ANS12=ANS13=…….;

//Khởi tạo RE1, RE2 là ngõ ra, trạng thái ban đầu led tắt

TRISE1=TRISE2=…….; RE1=RE2=…….;

//Khởi tạo RB0 là ngõ vào, tác động mức thấp

TRISB0=…….; RB0=…….;

//Cho phép điện trở kéo lên ở chân RB0;

IOCB0=…….; RBPU=…….;

//Khởi tạo ngắt ngoài ở chân RB0.

INTEDG=...; //cạnh lên INTE =…….; INTF =…….; GIE =…….; while(1) {

while(count==1) //Chương trình dịch từ trái qua phải.

{ i++; if(i>=9) i=1; display(i); _delay(100000); }

while(count==2) //Chương trình dịch từ phải qua trái.

{

i--;

if(i<=0)

display(i); _delay(100000); }

} }

void interrupt isr()

{ if(INTE&&INTF) { count++; if(count…….3)count=1; INTF=…….; } }

void display(char number) //Chương trình con hiển thị led

{

RE1=RE2=…….; //Tắt led RE1, RE2

TRISB |= 0b00111000;

//Khởi tạo chân RB3,RB4,RB5 là tổng trở cao

RB3=RB4=RB5=…….; switch(number) { case 1: RE2=…….; //RE2 sáng break; case 2: RE1=…….; //RE1 sáng break; case 3: //led D6 sáng

TRISB3=0;RB3=…….;TRISB4=…….;RB4=0; break; case 4: //led D7 sáng TRISB3=…….;RB3=0;TRISB4=…….;RB4=1; break; case 5: //led D8 sáng TRISB4=…….;RB4=1;TRISB5=…….;RB5=0; break; case 6: //led D9 sáng TRISB4=…….;RB4=0;TRISB5=…….;RB5=1; break; case 7: //led D10 sáng TRISB5=0;RB5=…….;TRISB3=0;RB3=…….; break; case 8: //led D11 sáng TRISB5=0;RB5=…….;TRISB3=0;RB3=…….; break; } }

* Bước 3: Biên dịch chương trình, nạp xuống kít thí nghiệm, tiến hành

nhấn nút nhấn và quan sát các led.

* Bước 4:Trả lời câu hỏi:

Đề ra các phương pháp xử lý khi ngõ vào tác động mức cao:

? SENSOR-PNP

……… ……… ……… ……… ……… ……… ……… ……… ……… ……… ……… ……… ……… 2.4. BÀI TẬP TỰ GIẢI

Bài 3. Viết chương trình theo yêu cầu sau, 16 led kết nối với PORTD, PORTC (tác động mức cao), 8 nút nhấn kết nối với PORTB: (Tạo

một project mới với tên 01_03_MSSV)

 Nhấn nút RB0:16 led dịch từ phải qua trái.  Nhấn nút RB1:16 led dịch từ trái qua phải.  Nhấn nút RB2:16 led chớp tắt xen kẽ.

 Nhấn nút RB3:16 led sáng dần từ trái qua phải.  Nhấn nút RB4:16 led sáng dần từ phải qua trái.  Nhấn nút RB5:16 led sáng dần từ trong ra ngoài.  Nhấn nút RB6:16 led sáng dần từ ngoài vào trong.  Nhấn nút RB7:16 led cùng chớp tắt.

Bài 4. Viết chương trình đọc giá trị phím và hiển thị giá trị lên led 7 đoạn theo sơ đồ phần cứng sau: (Tạo một project mới với tên 01_04_MSSV). (Phím từ 0-9, led hiển thị số tương ứng,phím‘*’ thể hiện

Bài 5. Viết chương trình đếm số lần nhấn nút (RB0) và hiển thị từ 000 đến 255 lên 3 led bảy đoạn theo sơ đồ phần cứng sau: (Tạo một

Chương III ADC MODULE

Sau khi học xong chương ADC module sinh viên có khả năng sau: a. Giải thích được khái niệm và chức năng của điện áp tham chiếu. b. Thiết lập được điện áp tham chiếu trong và ngoài cho khối ADC

của vi điều khiển.

c. Liệt kê được các bước thiết lập đo ADC cho một hoặc nhiều kênh. d. Thiết lập được công thức tính ADC 8-bit, và ADC 10-bit ở chế

độ định dạng canh trái và canh phải.

e. Tín toán được giá trị tín hiệu tương tự thu được thông qua giá trị của thanh ghi ADRESL, ADRESH.

f. Thiết lập và khởi tạo được một bài tập có liên quan lcd, thay đổi file lcd.h phù hợp với cấu hình phần cứng bên ngoài.

3.1. DỤNG CỤ THÍ NGHIỆM  Kít thí nghiệm + cáp USB.  Kít thí nghiệm + cáp USB.  Vít (vặn biến trở).  Máy tính.  Nguồn 12V/1A. 3.2. CƠ SỞ LÝ THUYẾT

3.2.1. Tín hiệu tương tự và tín hiệu số

Trong thực tế, tín hiệu cần xử lý xung quanh ta là tín hiệu tương tự, ví dụ: vận tốc, nhiệt độ, độ ẩm, cường độ ánh sáng, áp suất v.v... Tuy nhiên vi xử lý chỉ có thể làm việc với tín hiệu số (chỉ có hai trạng thái 0 và 1) do đó để xử lý được các tín hiệu tương tự, thì vi điều khiển cần phải có bộ chuyển đổi tín hiệu tương tự sang số ADC (Analog to Digital Converter).

CPU

ADC

PIC16F887

Hình 3.2: Bộ ADC được tích hợp bên trong vi điều khiển

Tín hiệu số Tín hiệu tương tự 0 Vref+ 255 Vref-

Hình 3.3: Đồ thị của bộ chuyển đổi ADC 8-bit

Độ phân giải (Resolution): Từ sơ đồ trên ta thấy bộ chuyển đổi ADC có độ phân giải 8-bit thì sẽ có 256 giá trị dùng để chứa các giá trị điện áp từ VREF- đến VREF+, như vậy nếu bộ chuyển đổi ADC có độ phân giải n bit thì sẽ có 2n giá trị. Độ phân giải có liên quan mật thiết đến chất lượng chuyển đổi ADC, độ phân giải càng cao thì kết quả chuyển đổi càng chính xác.

Điện áp tham chiếu (Reference voltage): Điện áp tham chiếu là điện áp dùng để so sánh với tín hiệu điện áp tương tự cần đo, VREF+ nên chọn bằng với mức điện áp lớn nhất cần đo, không nên chọn nhỏ hơn hay lớn hơn.

3.2.2. Bộ ADC của vi điều khiển PIC16F887

3.2.2.1. Các chân vi điều khiển có khả năng xử lý tín hiệu analog

Hình 3.4: Các chân có thể làm việc với tín hiệu tương tự

3.2.2.2. Các thanh ghi điều khiển hoạt động chuyển đổi của bộ ADC

ADON: Bit cho phép bộ ADC hoạt động

 ADON=1: Cho phép bộ ADC hoạt động  ADON=0: Không cho phép hoạt động

GO/ ̅̅̅̅̅̅̅̅ Bit chỉ trạng thái chuyển đổi, bit này tự động bằng 0 khi bộ ADC chuyển đổi xong, muốn cho lần chuyển đổi tiếp theo được thực hiện, cần phải đặt bit này lên bằng 1 trong lập trình.

CHS<3:0>: Dùng để chọn kênh cần chuyển đổi.

ADCS<1:0>: Bit lựa chọn tần số chuyển đổi.

VCFG1: Dùng để chọn điện áp tham chiếu VREF-.  VCFG1=1: khi đó VREF-= điện áp ở chân số 4 (VREF-)

 VCFG1=0: khi đó VREF- = Vss

VCFG0: Dùng để chọn điện áp tham chiếu VREF+.

 VCFG0=1: khi đó VREF+= điện áp ở chân số 5 (VREF+) VCFG0=0: khi đó VREF+= VDD

ADFM: Bit dùng để lựa chọn kiểu định dạng kết quả chuyển đổi.

Sau khi chuyển đổi hoàn tất, kết quả sẽ được lưu theo một trong hai kiểu.

Hai thanh ghi ADRESH và ADRESL là hai thanh ghi dùng để chứa kết quả khi bộ ADC chuyển đổi hoàn tất, bộ ADC của vi điều khiển PIC16F887 có độ phân giải 10-bit do đó cần hai byte để chứa kết quả, tuy nhiên kết quả có thể lưu theo hai kiểu: canh trái (ADFM=0) và canh phải (ADFM=1).

Đối với định dạng kết quả bên trái: ADFM=0 thì ta có thể đọc kết quả như sau:

 Độ phân giải 10-bit:Kết quả = ADRESH*4+ADRESL >> 6.(1)  Độ phân giải 8-bit:Kết quả = ADRESH.(2)

 Đối với định dạng kết quả bên phải: ADFM=1 thì ta có thể đọc kết quả như sau:

 Độ phân giải 10-bi:Kết quả = ADRESH*256+ADRESL.(3)  Độ phân giải 8-bit:Kết quả = ADRESH*64+ADRESL>>2.(4)  Rõ ràng ta thấy biểu thức (1) và (4) gây khó khăn trong việc lập trình và thời gian cần tín toán lâu hơn, do đó ta rút ra kết luận:

 Khi cần đọc ADC 8-bit thì cần định dạng kết quả bên trái(ADFM=0)

 Khi cần đọc ADC 10-bit thì cần định dạng kết quả bên phải (ADFM=1).

3.2.2.3. Ngắt trong ADC

Khối ADC cũng có thể tạo ra sự kiện ngắt (ngắt trong), sự kiện ngắt xảy ra khi bộ ADC thực hiện xong một chu kỳ chuyển đổi.

Hình 3.6: Sơ đồ khởi tạo ngắt ADC

ADIE: Bit cho phép bộ chuyển đổi ADC.

ADIF: Cờ ngắt ADC, bit này tự động bằng 1 khi bộ ADC chuyển

đổi hoàn tất, để cho lần chuyển đổi tiếp theo được thực hiện, chúng ta cần phải xóa bít này bằng phầm mềm lập trình.

PEIE: Bit cho phép ngắt ngoại vi. GIE: Bit cho phép ngắt toàn cục.

3.2.2.4. Các bước khởi tạo bộ chuyển đổi ADC

 Bước 1: Chọn tín hiệu xử lý

 Khởi tạo chân là ngõ vào:TRISxy=1; //x:A,B,E, y:0-7  Khởi tạo chân xử lý tín hiệu tương tự: ANSx=1;

//Trong đó: x=0-13

 Bước 2: Khởi tạo khối ADC  Chọn tần số chuyển đổi

ADCS1=...;ADCS0=...; Chọn điện áp tham chiếu

VCFG1=...; VCFG0=...;  Chọn kênh cần đo.

 Chọn định dạng kết quả ADFM=...;

 Cho phép module ADC ADON=1;

 Bước 3: Khởi tạo ngắt ADC (có thể bỏ qua bước này nếu không sử dụng ngắt):

 Xóa cờ ngắt: ADIF=0;

 Cho phép ngắt ADC: ADIE=1;  Cho phép ngắt ngoại vi: PEIE=1;  Cho phép ngắt toàn cục: GIE=1;  Bước 4: Chờ thời gian khởi tạo.  Bước 5: Bắt đầu cho phép chuyển đổi.

GODONE=1;

 Bước 6: Chờ cho bộ ADC chuyển đổi hoàn tất bằng các dấu hiệu sau:

 Bit GODONE tự động xuống 0, ta có thể sử dụng code sau để thực hiện việc chờ:

while(GODONE);

 Ngắt ADC xảy ra. (Nếu bước 3 được thực hiện)  Bước 7: Đọc kết quả

 ADC 8-bit: kết quả = ADRESH //canh trái  ADC 10-bit:kết quả = ADRESH*64+ADRESL //canh phải  Bước 8: Xóa cờ ngắt cho lần chuyển đổi tiếp theo (Nếu bước 3

được thực hiện)  ADIF=0;

3.2.3. Làm việc với LCD 16x2

Để vi điều khiển PIC16F887 giao tiếp được với LCD đòi hỏi trong chương trình cần phải có những dòng lệnh phù hợp lcd, thường những yêu cầu lệnh này được quy định bởi chip xử lý bên trong lcd, do đó để chương trình ngắn gọn và đơn giản, ta thường xây dựng file lcd.c và lcd.h là những file chứa sẵn những chương trình con có những câu lệnh giao tiếp với lcd, ta chỉ cần khai báo hai file lcd.c và lcd.h thì có thể dễ dàng

giao tiếp với lcd bằng những câu lệnh bên trong file đó. Các bước khởi tạo và làm việc với LCD:

 Bước 1: Kiểm tra phần cứng, phải phù hợp với những khai báo trong file LCD.h

 Bước 2: Copy 2 file LCD.c và LCD.h vào thư mục của project đang lập trình.

 Bước 3: Add hai file trên vào Header file và Source file.

− Bước 4: Tối thiểu cần phải khai báo 2 dòng lệnh sau (tô đen) trong chương trình khi có liên quan tới file LCD:

#include<htc.h> __CONFIG(…….);

#include “lcd.h” //khai báo thư viện hàm lcd.h

void main() {

lcd_init(); //lệnh khởi tạo lcd

//Các lệnh được sử dụng cho lcd có thể tham khảo trong file lcd.c ví dụ:

lcd_gotoxy(x,y); //Lệnh này dùng để di chuyển con trỏ đi đến các

vị trí trên màn hình lcd, trong đó y là giá trị của hàng dọc (y=[0,1]), x là giá trị của hàng ngang(x=[0,15]).

lcd_putc(‘kí tự cần in’); //Lệnh này dùng để in kí tự lên màn

hình lcd tại vị trí con trỏ.

lcd_puts(“chuỗi cần in”); //Lệnh này dùng để in chuỗi lên màn

hình lcd tại vị trí con trỏ, chú ý chuỗi cần in nằm giữa hai dấu “ ” và kí tự cần in nằm giữa hai dấu ‘ ’.

lcd_putc(‘\f’); //xóa màn hình lcd, sau đó con trỏ trở về vị trí

52

while(1) {

} }

* Ngoài ra còn có thể sử dụng hàm printf nhưng cần khai báo như sau: #include<htc.h>

#include<stdio.h> //khai báo thư viện cho hàm printf __CONFIG(…….);

#include “lcd.h” //khai báo thư viện hàm lcd.h

void main()

{

lcd_init(); //lệnh khởi tạo lcd

while(1); }

void putch(char ki_tu) char bien2=6;

float bien1=19.66667;

unsigned int bien3=60000;

printf(“In ra man hinh ”); //Hiển thị chuỗi In ra man hinh printf(“In ra \n man hinh ”); //Hiển thị chuỗi In ra

man hinh

printf(“In gia tri:%d ”, bien2); //Hiển thị chuỗi In gia tri:6

printf(“In gia tri:%3d ”, bien2); //Hiển thị chuỗi In gia tri:

6

printf(“In gia tri:%03d ”, bien2); //Hiển thị chuỗi In gia

tri:006

printf(“In gia tri:%5.3d ”, bien2); //Hiển thị chuỗi In gia tri:

006

printf(“In gia tri:%f ”, bien1); //Hiển thị chuỗi In gia printf(“In gia tri:%3d ”, bien2); //Hiển thị chuỗi In gia tri: 6 printf(“In gia tri:%03d ”, bien2); //Hiển thị chuỗi In gia tri:006 printf(“In gia tri:%5.3d ”, bien2); //Hiển thị chuỗi In gia tri: 006 printf(“In gia tri:%f ”, bien1); //Hiển thị chuỗi In gia tri:19.6666 printf(“In gia tri:%3.2f ”, bien1); //Hiển thị chuỗi In gia tri: 19.67 printf(“In gia tri:%d ”, bien3); //Hiển thị chuỗi In gia tri:-5536 printf(“In gia tri:%ld ”, bien3); //Hiển thị chuỗi In gia tri:60000

{

lcd_putc(ki_tu); }

 Chú ý: Khi viết chương trình có liên quan LCD mà phần cứng thực tế không có LCD hay LCD kết nối không đúng với thư viện LCD.H thì con trỏ chương trình sẽ dừng ngay lệnh lcd_init();

3.3. BÀI TẬP THỰC HÀNH

Bài 1: Viết chương trình đọc ADC 8 bit ở chân AN3 và thực hiện theo yêu cầu sau:

 Hiển thị giá trị thanh ghi ANSEL ở hàng (0,0) của LCD.  Hiển thị giá trị điện áp chân AN3 ở hàng (0,1) của LCD.

Một phần của tài liệu Giáo trình vi điều khiển PIC16F và ngôn ngữ lập trình HITECH C, Giáo trình dùng cho sinh viên ngành Cơ điện tử Nguyễn Trường Thịnh, Nguyễn Tấn Nó (Trang 34)

Tải bản đầy đủ (PDF)

(165 trang)