Giáo trình thí nghiệm vi điều khiển ứng dụng Hai thanh ghi này có tổng cộng 14bit từ ANS0 đến ANS13 , sẽ quy định tín hiệu làm việc của các chân từ AN0 đến AN13 là tín hiệu số hay tín hi
Trang 11
BÀI 1 : XUẤT NHẬP I/O PORT:
I.MỤC ĐÍCH THÍ NGHIỆM :
Kiến thức sinh viên cần đạt được sau khi thực tập:
Liệt kê các thanh ghi liên quan đến việc xử lý tính hiệu số ở các chân vi điều khiển
Khởi tạo các chân của vi điều khiển là ngõ ra , vào số
Giải thích được công dụng của hàm _delay(n) , cách dùng hàm delay để chống dội cho
nút nhấn
Lập trình điều khiển led theo yêu cầu
Giải thích ưu khuyết điểm của ngắt
hiệu tương tự Do đó khi làm việc với những chân này ta cần chú ý đến hai thanh ghi :
Trang 2Giáo trình thí nghiệm vi điều khiển ứng dụng
Hai thanh ghi này có tổng cộng 14bit từ ANS0 đến ANS13 , sẽ quy định tín hiệu làm việc của các chân từ AN0 đến AN13 là tín hiệu số hay tín hiệu analog
ANSX=0 : Cho phép chân ANX xử lý tín hiệu số
ANSX=1 : Cho phép chân ANX xử lý tín hiệu tương tự
Trong đó : X= 0 – 13
2.Chức năng của thanh ghi TRIS :
Trong các chân xử lý tín hiệu số , hoạt động của chân có thể là ngõ ra (làm cho led chớp tắt, kích transistor , điều khiển hoạt động IC ) , hay có thể là ngõ vào (đọc trạng thái nút nhấn , đọc encoder , đọc tín hiệu từ cảm biến số ) Như vậy , để khởi tạo cho các chân là ngõ ra hay ngõ vào tín hiệu số , chúng ta cần chú ý đến thanh ghi TRISX (X=A,B,C,D,E):
TRISXY=0:Quy định bit thứ Y của PORTX là ngõ ra (0 = Output)
TRISXY=1:Quy định bit thứ Y của PORTX là ngõ vào (1=Input)
(Trong đó :X=A,B,C,D,E ; Y=0-7)
Chú ý : PORTE chỉ có 4 bit thấp : TRISE0, TRISE1, TRISE2 ,TRISE3
3 Chức năng của thanh ghi PORT :
Trong trường hợp xử lý tín hiệu số và là ngõ ra , thì có thể là ngõ ra mức cao (điện áp ở chân
đó là VH) , hay ngõ ra là mức thấp (điện áp là VL) sẽ do bit RXY của thanh ghi PORTX quy định
RXY=0 : Quy định chân thứ Y của PORTX là mức thấp(VL)
RXY=1: Quy định chân thứ Y của PORTX là mức cao(VH)
(Trong đó : X=A,B,C,D,E ; Y=0-7)
Trang 34.Những thanh ghi đặc biệt chỉ có riêng ở PORTB:
4.1.Thanh ghi hỗ trợ điện trở treo bên trong:
Để tránh trạng thái thả nổi (tín hiệu điện áp ở chân đó không rõ ràng) khi khởi tạo PORTB là
ngõ vào số , PIC16f887 tích hợp thêm vào cho PORTB các điện trở kéo lên (pull-up), để sử dụng
các điện trở này ta chú ý đến thanh ghi :
WPUBy=0: Không cho phép điện trở kéo lên ở chân thứ y của PORTB
WPUBy=1: Cho phép điện trở kéo lên ở chân thứ y của PORTB
Khi sử dụng điện trở kéo lên ngoài việc sử dụng thanh ghi WPUB còn phải khởi tạo bit: RBPU
Điện trở kéo lên nên khởi tạo khi PORTB là ngõ vào số , các PORT khác không có hỗ trợ điện trở treo trong , do đó nếu có nhu cầu sử dụng ta có thể mắc thêm điện trở bên ngoài
4.2.Ngắt ngoài ở chân RB0:
Để xử lý được các tín hiệu tác động tức thời , chân RB0 có hỗ trợ xử lý ngắt (interrupt ) kí
hiệu ở chân là INT, khởi tạo ngắt ngoài ở chân RB0 ta cần chú ý đến các bit sau :
INTE(Interrupt enable ) : bit cho phép ngắt ở PORTB
Trang 4Giáo trình thí nghiệm vi điều khiển ứng dụng
INTF(Interrupt flag): cờ ngắt , bit này tự động bằng 1 khi có sự kiện ngắt (cạnh lên hay cạnh xuống) xảy ra ở chân RB0, ta phải xóa bít này trong khi lập trình
GIE(Global interrupt ) : bit cho phép ngắt toàn cục
INTEDG (interrupt edge select bit ) : Bit chọn cạnh tác động để sinh ra sự kiện ngắt ở PORTB
INTEDG=1: Xảy ra ngắt khi có tín hiệu cạnh lên ở PORTB INTEDG=0: Xảy ra ngắt khi có tín hiệu cạnh xuống ở PORTB
Các bước khởi tạo ngắt INT:
Bước 1 : Khởi tạo chân RB0 là ngõ vào số , điện trở treo
Bước 2 : Khởi tạo ngắt INT
INTE=1; //Cho phép ngắt hoạt động INTF=0; //Xóa cờ ngắt thì ngắt lần tiếp theo mới có thể xảy ra INTEDG= ; //Chọn cạnh tác động ngắt
GIE=1; //Cho phép ngắt toàn cục
4.3.Ngắt on-change ở PORTB:
Ngoài ngắt INT chỉ có duy nhất ở chân RB0 , thì cả PORTB (từ RB0 đến RB7) còn hỗ trợ ngắt on-change , ngắt on-change xảy ra khi tín hiệu logic ở chân của PORTB thay đổi trạng thái logic
Sơ đồ ngắt on-change:
Trang 55
Các thanh ghi và các bit điều khiển ngắt on-change :
IOCBX=0 : Không cho phép ngắt on-change ở chân thứ X của PORTB
IOCBX=1 : Cho phép ngắt on-change ở chân thứ X của PORTB
Các bit khởi tạo khác :
RBIF : Cờ ngắt on-change ở PORTB, cần phải xóa bít này trong lập trình
RBIE : Bit cho phép ngắt on-change của PORTB
GIE : Bit cho phép ngắt toàn cục
Các bước khởi tạo ngắt on-change :
Bước 1 : Khởi tạo PORTB là ngõ vào số , có điện trở treo
Bước 2 : Khởi tạo ngắt on-change ở PORTB
IOCB=0xFF; //khởi tạo toàn bộ PORTB ngắt on-change(có thể khởi tạo một hay cả PORTB)
RBIE=1; //Cho phép ngắt xảy ra
Chú ý : Đối với ngắt on-change , việc xóa cờ ngắt (RBIF=0) không đủ để cho lần ngắt
tiếp theo được thực hiện , mà còn phải thêm điều kiện đọc hoặc viết vào thanh ghi PORTB
Ví dụ :
unsigned char bien ;
bien = PORTB ; //đọc thanh ghi PORTB
hoặc PORTB =5 ; //viết vào thanh ghi PORTB
4.4.Bảng so sánh giữa ngắt INT và ngắt on-change :
Ngắt ở chân INT(RB0) Ngắt on-change
Để xảy ra ngắt thì tín hiệu logic là cạnh lên
hoặc cạnh xuống
Chỉ cần tín hiệu logic thay đổi là xảy ra ngắt, không phân biệt cạnh lên hay cạnh xuống Các bit khởi tạo :
INTE , INTF , INTEDG , GIE
Các bit khởi tạo : IOCBx , RBIE , RBIF , GIE
Để cho lần ngắt tiếp theo được thực hiện thì
cần phải xóa cờ ngắt INTF
Để cho lần ngắt tiếp theo được thực hiện thì cần phải xóa cờ ngắt INTF và đọc ( hoặc ghi) vào thanh ghi PORTB
Trang 6Giáo trình thí nghiệm vi điều khiển ứng dụng
IV.BÀI TẬP THỰC HÀNH :
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ử 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_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&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BORDIS&IESODIS&LVPDIS&FCMDIS);
void delay(unsigned char counter); //Khai báo chương trình con hàm delay
void RB_0( );void RB_1( );void RB_2( );
Trang 77
//( -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 -)
//Hiển thị led
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) RB_2( ); //Chạy chương trình con RB_2
}
}
//( -5 -) void delay(unsigned char counter) //Chương trình con làm tăng thời gian delay
*Bước 4: Thay đổi chương trình như sau:
Thêm vào dòng : ( -1 -) đoạn code sau:
Trang 8Giáo trình thí nghiệm vi điều khiển ứng dụng
IOCB0=IOCB1=IOCB2=1; //Cho phép ngắt onchange ở chân B0,B1,B2
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
}
}
*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:
-
-
Trang 99
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&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BORDIS&IESODIS&LVPDIS&FCMDIS);
Trang 10Giáo trình thí nghiệm vi điều khiển ứng dụng
Trang 1111
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 :
-
V.BÀI TẬP TỰ GIẢI :
Bài 3.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_03_MSSV)
(Phím từ 0-9 , led hiển thị số tương ứng , phím „*‟ thể hiện chữ „S‟, phím „#‟ thể hiện chữ
„H‟, lúc không nhấn thể hiện chữ „U‟ )
Trang 12Giáo trình thí nghiệm vi điều khiển ứng dụng
Bài 4.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_04_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 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 project mới với tên 01_05_MSSV)
Trang 1313
BÀI 2 : ADC MODULE
I.MỤC ĐÍCH THÍ NGHIỆM :
Kiến thức sinh viên cần đạt được sau khi thực tập :
Giải thích được khái niệm và chức năng của điện áp tham chiếu
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
Liệt kê được các bước thiết lập đo ADC cho một hoặc nhiều kênh
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
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
Thiết lập và khởi tạo được một project 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
1.Tín hiệu tương tự và tính hiệu số :
Tín hiệu tương tự Tín hiệu số
Đồ thị tín hiệu analog 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)
Trang 14Giáo trình thí nghiệm vi điều khiển ứng dụng
Bộ ADC được tích hợp bên trong vi điều khiển
Đồ 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 bit thì sẽ có 255 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-1 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
8- Đ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 analog 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
2.ADC của vi điều khiển PIC16F887:
2.1Các chân vi điều khiển có khả năng xử lý tín hiệu analog :
Các chân có thể làm việc với tín hiệu analog
Trang 1515
Sơ đồ khối bộ ADC trong vi điều khiển PIC16F887
2.2Cá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
Trang 16Giáo trình thí nghiệm vi điều khiển ứng dụng
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
Trang 1717
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)
Đố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-bit : 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)
2.3 Ngắt 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 chuyển đổi hoàn tất
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
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= ;
Trang 18Giáo trình thí nghiệm vi điều khiển ứng dụng
Chọn điện áp tham chiếu VCFG1= ; VCFG0= ;
Chọn kênh cần đo
CHS3= ;CHS2= ;CHS1= ;CHS0= ;
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):
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.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 code 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
Trang 19lcd_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 đó x là giá trị của hàng ngang (x=[0,1]) , y là giá trị của hàng
dọc(y=[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í (0,0)
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 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
Trang 20Giáo trình thí nghiệm vi điều khiển ứng dụng
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();
IV.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
Định thời bằng hàm delay , điện áp tham chiếu trong , Fosc = 4Mhz , giao tiếp LCD bằng thư viện LCD.h
Sơ đồ phần cứng :
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
Trang 2121
*Bước 1 : Tạo một project mới với tên 02_01_ 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> #include<stdio.h> //thư viện cho hàm printf( ); CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BO RDIS&IESODIS&LVPDIS&FCMDIS); #include"lcd.h"; void main( ) { lcd_init( ); //Khởi tạo LCD ANS3=…….; //Enable analog ở chân RA3 TRISA3=…….;RA3=…….; //Khởi tạo RA3 là ngõ vào VCFG0=VCFG1=…….; //Chọn điện áp tham chiếu trong CHS3=CHS2=…….;CHS1=CHS0=…….; //Chọn kênh đo là AN3 ADFM=…….; //Định dạng dữ liệu canh trái , bởi vì chỉ sử dụng ADC 8 bit ADCS0=ADCS1=…….; //Tần số chuyển đổi ADON=…….; //Enable module ADC hoạt động while(1) { GODONE=…….; //Cho phép ADC bắt đầu chuyển đổi while(GODONE) …… //Chờ bộ ADC chuyển đổi xong lcd_gotoxy(0,0); printf("\fADRESH :%d",ADRESH); lcd_gotoxy(0,1); printf("Dien ap :%3.2f",ADRESH*5.0/255.0); _delay(100000); } } void putch(char c) //Hỗ trợ cho hàm printf in ra LCD { lcd_putc(c); } *Bước 3: Biên dịch chương trình , nạp xuống kít thí nghiệm , jum header 3 ở vị trí POT , dùng vít vặn biến trở và quan sát kết quả trên LCD *Bước 4:Thiết lập công thức quan hệ giữa điện áp và giá trị thanh ghi ADRESH
-
Trang 22Giáo trình thí nghiệm vi điều khiển ứng dụng
Bài 2: Viết chương trình đọc ADC 10 bit ở hai kênh AN3 , AN12 và thực hiện theo yêu cầu sau :
Hiển thị giá trị điện áp tại chân AN3 ở hàng (0,0) của LCD
Hiển thị giá trị điện áp tại chân AN12 ở hàng (0,1) của LCD
Định thời bằng hàm delay , điện áp tham chiếu trong , Fosc = 4Mhz, giao tiếp LCD bằng thư viện LCD.h
Sơ đồ phần cứng :
*Bước 1 : Tạo một project mới với tên 02_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>
#include<stdio.h>
CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BORDIS&IESODIS&LVPDIS&FCMDIS);
ANS3= …….;ANS12= …….; //Enable analog ở chân RA3 và chân RB0
TRISA3= …….;RA3= …….;TRISB0=1;RB0=1; //Khởi tạo RA3,RB0 là ngõ vào
while(1)
{
CHS3=CHS2= …….;CHS1=CHS0= …….; //Chọn kênh AN3
Trang 23*Bước 3 : Jum header 3 ở vị trí BUTTON
Nhấn giữ nút nhấn SW2 và quan sát kết quả trên LCD ở vị trí (0,0) tức là kết quả đo kênh AN3
Nhấn giữ nút nhấn SW3và quan sát kết quả trên LCD ở vị trí (0,0) tức là kết quả đo kênh AN3
Nhấn giữ cả hai nút SW2,SW3 và quan sát kết quả trên LCD ở vị trí (0,0) tức là kết quả
đo kênh AN3
Dựa vào mạch điện nguyên lý, chứng minh cả 3 kết quả quan sát được
- - - - - - - - - - - - - -
Trang 24-Giáo trình thí nghiệm vi điều khiển ứng dụng
*Bước 4 : Quan sát kết quả ở hàng (0,1) của lcd , tức là kết quả đo được ở kênh AN12 khi có
nhấn nút RB0 và khi không có nhấn nút và nhận xét :
- - - - - - - - - - - - - -
-V.BÀI TẬP TỰ GIẢI :
Bài 3 : Viết chương trình sử dụng khối ADC của vi điều khiển PIC16F887 đo nhiệt độ của
5 phòng và hiển thị lên LCD, sử dụng LM35 theo yêu cầu sau :
(Tạo một project mới với tên 02_03_ MSSV)
Khi nhấn (không giữ )RB0 thì LCD hiển thị giá trị giá trị nhiệt độ của phòng 1
Khi nhấn (không giữ )RB1thì LCD hiển thị giá trị giá trị nhiệt độ của phòng 2
Khi nhấn (không giữ )RB2 thì LCD hiển thị giá trị giá trị nhiệt độ của phòng 3
Khi nhấn (không giữ )RB3 thì LCD hiển thị giá trị giá trị nhiệt độ của phòng 4
Khi nhấn (không giữ )RB4 thì LCD hiển thị giá trị giá trị nhiệt độ của phòng 5
Tần số hoạt động Fosc = 4MHz , phần cứng LCD được kết nối với PORTD của Vi Điều khiển theo sơ đồ chân của thư viện lcd.h , điện áp tham chiếu bên trong , sử dụng ADC 8 bit
Trang 2525
Bài 4:Viết chương trình đọc giá trị điện áp ở chân AN0 và hiển thị lên LCD 16x2 theo yêu cầu sau : (Tạo một project mới với tên 02_04_ MSSV)
Hiển thị giá trị hai thanh ghi ADRESH và ADRESL ở vị trí (0,0) của LCD
Hiển thị giá trị điện áp đo được ở vị trí (0,1) của LCD
Tần số hoạt động Fosc = 4MHz , phần cứng LCD được kết nối với PORTD của Vi Điều khiển theo sơ đồ chân của thư viện lcd.h , điện áp tham chiếu bên ngoài , sử dụng ADC 10 bit
Bài 5 : Viết chương trình dùng vi điều khiển PIC16F887 thực hiện chức năng như một máy tính theo sơ đồ phần cứng sau : (Tạo một project mới với tên 02_05_ MSSV)
Trang 26Giáo trình thí nghiệm vi điều khiển ứng dụng
BÀI 3 :TIMER
I.MỤC ĐÍCH THÍ NGHIỆM :
Kiến thức sinh viên cần đạt được sau khi thực tập :
− Giải thích được nguyên tắc hoạt động của timer0 , timer1 , timer 2
− Thiết lập công thức tính định thời của từng timer
− Liệt kê các bit điều khiển từng hoạt động của timer
− Phân biệt sự khác nhau và giống nhau giữa hai chế độ timer và counter trong timer 0 , timer1
− Giải thích chức năng của bộ chia trong timer
− Khởi tạo ngắt cho timer0 , timer 1 , timer 2
Sơ đồ khối các timer trong PIC16F887
Trang 2727
: Tràn timer
1.Nguyên tắc hoạt động của timer :
Nguyên tắc hoạt động chung của timer là tăng giá trị của thanh ghi đếm lên khi nhận được một xung clock (đã qua bộ chia ) Khi thanh ghi đếm đến giá trị lớn nhất , nếu có xung clock tiếp tục tác động thì timer sẽ xảy ra sự kiện tràn timer (overflow) , sự kiện này có thể xảy ra ngắt
Ví dụ : Thanh ghi TMR0 là thanh ghi 8-bit chứa giá trị đếm của timer 0 :
− Thanh ghi 8-bit timer/counter (TMR0)
− Bộ chia prescaler 8-bit (dùng chung với Watchdog timer )
− Hoạt động với xung clock bên trong hoặc bên ngoài
− Hoạt động với việc lựa chọn cạnh của xung clock bên ngoài
− Ngắt tràn timer
Sơ đồ khối timer 0 và watchdog timer trong PIC16F887
TMR0=0 +∆𝑡 TMR0=1 +∆𝑡 TMR0=2 +∆𝑡 TMR0=3 +∆𝑡 TMR0=255 +∆𝑡
Trang 28Giáo trình thí nghiệm vi điều khiển ứng dụng
2.1 Các thanh ghi khởi tạo timer 0 :
T0CS : bit lựa chọn chế độ hoạt động của timer 0
− T0CS=1: Timer 0 hoạt động với chế độ đếm counter (clock được cấp từ chân T0CKI)
− T0CS=0:Timer 1 hoạt động với chế độ định thời timer.(clock được cấp từ thạch anh hoạt động của vi điều khiển )
T0SE : Bit chọn cạnh tác động khi timer hoạt động với chế độ đếm counter
− T0SE=1: Thanh ghi TMR0 tăng khi có sự kiện cạnh xuống ở chân T0CKI
− T0SE=0: Thanh ghi TMR0 tăng khi có sự kiện cạnh lên ở chân T0CKI
PSA : Dùng để lựa chọn bộ chia Prescaler thuộc về của timer 0 hay của Watchdog
− PSA=1:Bộ chia prescaler thuộc về Watchdog
− PSA=0: Bộ chia prescaler thuộc về Timer 0
PS<2:0> : Chọn tỉ lệ cho bộ chia prescaler
2.2 Công thức định thời timer 0:
Thời gian hoạt động của timer0 (8-bit)
Over flow
∆𝑡
0
Trang 2929
Từ sơ đồ trên ta thấy thời gian định thời của timer 0 :
T=(255-TMR0‟)*∆𝑡 = (255−𝑇𝑀𝑅0′)∗𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 ∗4
𝐹𝑜𝑠𝑐
Do đó để thay đổi thời gian định thời T ta có thể thay đổi một trong các thông số sau :
− TMR0‟ : Giá trị ban đầu của thanh ghi TMR0 cho timer 0 bắt đầu đếm Khi trong lập trình không gán giá trị đầu cho thanh ghi TMR0 thì timer bắt đầu đếm là 0
(TMR0‟=0)
− Prescaler : Tỉ lệ bộ chia của timer 0
− Fosc : Tần số hoạt động của vi điều khiển.(Ít khi thay đổi thông số này)
Chú ý : Trong quá trình tính toán tìm ra thời gian định thời T hợp lý , thường có sai số xảy ra , do đó chúng ta chọn Prescaler và TMR0‟ sao cho sai số ít nhất
T0IE : Bit cho phép xảy ra ngắt timer 0 , để ngắt timer 0 xảy ra thì bit này phải bằng 1
T0IF : Cờ ngắt timer 0 , khi ngắt xảy ra bít này tự động bằng 1 , chúng ta cần phải xóa (=0) bít
này trong lập trình
GIE : GIE bit cho phép ngắt toàn cục , để ngắt timer 0 xảy ra thì bit này phải bằng 1
2.4 : Các bước khởi tạo timer 0:
2.4.1 : Khởi tạo timer 0 hoạt động với chế độ định thời timer:
T0CS=0; //Clock cấp cho timer 0 là Fosc (tần số hoạt động của vi điều khiển) PSA=0 ; //Bộ chia prescaler được sử dụng cho timer 0
PS<2:0>= ; //Chọn tỉ lệ bộ chia Nếu PSA=1 thì có thể bỏ qua dòng này
//Khởi tạo ngắt nếu có sử dụng
INTE=1;
INTF=0;
GIE=1;
Trang 30Giáo trình thí nghiệm vi điều khiển ứng dụng
2.4.2:Khởi tạo timer 0 hoạt động với chế độ đếm counter :
//Khởi tạo chân T0CKI là ngõ vào
TRISA4=1;
RA4=1;
T0CS=1; // Clock cấp cho timer 0 từ chân T0CKI
PSA=0 ; //Bộ chia prescaler được sử dụng cho timer 0
PS<2:0>= ; //Chọn tỉ lệ bộ chia Nếu PSA=1thì có thể bỏ qua dòng này
//Khởi tạo ngắt nếu có sử dụng
INTE=1;
INTF=0;
GIE=1;
3.Timer 1 :
Timer 1 có hai thanh ghi chứa giá trị đếm , do đó có thể đếm lên đến 65535(2^16-1) mới xảy
sự kiện tràn timer , timer 1 thích hợp nhất cho việc đếm xung encoder tốc độ cao , cũng giống như timer 0 , timer 1 cũng hoạt động với hai chế độ : chế độ định thời và chế độ đếm counter
Sơ đồ khối timer 1
Trang 31− T thời gian định thời timer 1
− TMR1L , TMR1H : thanh ghi chứa giá trị đếm của timer 1
− FOSC : tần số hoạt động của vi điều khiển
− Prescaler : tỉ lệ bộ chia
3.2Thanh ghi điều khiển timer1 :
TMR1ON : Bit cho phép timer1 hoạt động
− 1: Cho phép timer 1 (điều kiện cần cho timer 1 hoạt động , chưa đủ)
− 0: Timer 1 ngừng hoạt động
TMR1CS :Bit lựa chọn clock cho timer 1
− 1:Clock từ bên ngoài (từ chân T1CKI)
− 0:Clock bên trong (FOSC/4)
𝐓𝟏𝐒𝐘𝐍𝐂
: Bit điều khiển lựa chọn đồng bộ clock vào từ bên ngoài của timer 1
Nếu TMR1CS =1:
− 1:Clock vào từ bên ngoài không được đồng bộ
− 0:Clock vào từ bên ngoài được đồng bộ
Nếu TMR1CS = 0:
− Không cần quan tâm bit này , timer 1 sử dụng clock bên trong
T1OSCEN : Bit điều khiển cho phép dao động LP
− 1: Dao động LP được cho phép cho clock timer 1
TMR1GE : Bit cho phép cổng timer 1
Nếu TMR1ON=0 : bit này không cần quan tâm
Nếu TMR1ON=1 :
− 1 : Sự đếm lên của timer1 sẽ được điểu khiển bởi cổng Timer 1
− 0 : Timer 1 có thể đếm lên mà không cần quan tâm đến trạng thái của cổng timer 1
T1GINV : Bit đảo cổng timer1
Trang 32Giáo trình thí nghiệm vi điều khiển ứng dụng
1 : Cổng timer1 tác động mức cao (Timer1 hoạt động khi cổng ở mức cao )
0 : Cổng timer 1 tác động mức thấp (Timer 1 hoạt động khi cổng ở mức thấp)
Cho phép timer 1 hoạt động khi có tín hiệu logic ở chân T1G :
//Cho phép điện trở treo
//Khởi tạo chân T1G là ngõ vào
TMR1IF : Cờ ngắt , bit này tự động bằng 1 khi có sự kiện tràn timer
TMR1IE :Bit cho phép ngắt tràn timer
PEIE :Bit cho phép ngắt ngoại vi
GIE :Bit cho phép ngắt toàn cục
Sơ đồ ngắt timer 1
3.5 Khởi tạo timer 1 hoạt động với chế độ đếm counter :
//Khởi tạo chân T1CKI là ngõ vào số ……
Trang 3333
Ngoài ra , timer 1 còn có thể hoạt động với chế độ timer sử dụng thạch anh ngoài , độc lập với tần số họat động của vi điều khiển , thạch anh ngoài ta có thể kết nối với hai chân : OSC1 và OSC2 và khởi tạo tương tự như trên
3.6 Khởi tạo timer 1 hoạt động với chế độ định thời timer :
Sơ đồ khối timer 2
Nguyên tắc hoạt động timer 2 :
Khi có xung clock tần số Fosc/4 qua bộ chia Prescaler đi vào thanh ghi TMR2 , làm thanh ghi TMR2 tăng lên , khi thanh ghi TMR2 bằng giá trị thanh ghi đặt PR2 thì sẽ có một xung clock
đi qua bộ chia Postscaler , đồng thời thanh ghi TMR2 trở về vị trí ban đầu , nếu tỉ lệ bộ chia Postscaler được chọn 1:1 thì sẽ xảy ra sự kiện ngắt timer 2
4.1 Công thức tín định thời timer 2 :
T= PR 2−TMR 2′ ∗Postscaler ∗Prescaler ∗4
Fosc
Trong đó
T :Thời gian định thời timer 2
PR2 :giá trị thanh ghi đặt
TMR2‟ : giá trị bắt đầu đếm của thanh ghi TMR0
Prescaler : Tỉ lệ bộ chia prescaler
Postscaler : Tỉ lệ bộ chia Postscaler
Fosc :Tần số hoạt động của vi điều khiển
Trang 34Giáo trình thí nghiệm vi điều khiển ứng dụng
4.2 Thanh ghi điều khiển timer 2 :
T2CKPS<1:0>: Bit lựa chọn tỉ lệ bộ chia Prescaler
00 : 1:1
01 : 1:4 1x : 1:16
TMR2ON : Bit cho phép timer 2 hoạt động
0:Không cho phép timer2 hoạt động 1:Cho phép timer 2 hoạt động
TOUTPS<3:0>: Bit lựa chọn tỉ lệ bộ chia Postscaler
4.2.Khởi tạo timer 2 hoạt động với chế độ định thời timer :
//Tín toán lựa chọn tỉ lệ bộ chia Prescaler , Postscaler
Trang 35*Bước 1: Tạo một project mới với tên 03_01_ 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>
#include<stdio.h>
CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BORDIS&IESODIS&LVPDIS&FCMDIS);
#include "lcd.h";
void main( )
{
lcd_init( );
TRISA4=…….; RA4=…….; //Khởi tạo chân T0CKI là ngõ vào
T0CS =…….; //Chọn clock cấp cho Timer0 là từ chân T0CKI
T0SE =…….; //Chọn cạnh tác động là cạnh xuống
PSA =…….; //Xung clock không qua bộ chia ( -1 -)
//( -2 -) while(1)