Professional Documents
Culture Documents
Pratical Experiment
Pratical Experiment
PIC 16F877A
PICKit Programmer/ Debugger là một công cụ phát triển giá rẻ nhưng tính năng và độ ổn
định cao, dễ dàng để sử dụng để nạp và gỡ lỗi PIC Microcontrollers Flash. Ngoài ra còn có
thể sử dụng như một thiết bị đầu cuối truyền dữ liệu với PC qua chức năng UART Tool và
Logic Tool Analyzer. sử dụng software PICKit 2/3 hoặc MPLAB IDE.
Phần mềm Proteus là một phần mềm thiết kế mạch in được phát minh bởi Labcenter
Electronics. Nó được sử dụng để thiết kế các mạch khác nhau trên PCB (bo mạch in) và mô
phỏng các mạch khác nhau. Việc sử dụng proteus cho bất kỳ dự án mạch điện tử nào làm cho
dự án đó tiết kiệm chi phí và ít sai sót hơn do cấu trúc sơ đồ trên proteus. Năm 1988, phiên
bản Proteus đầu tiên được gọi là PCB-B được tạo ra bởi John Jameson, chủ tịch của công ty.
1
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
BOOK1 không phải là một cuốn sách, mà BOOK1 là một bo mạch phát triển giúp người
mới học PIC làm quen với các tính năng cũng như các công cụ làm việc với PIC. BOOK1 là
một dự án nằm trong chương trình tài trợ cho các trường đại học, và phổ biến PIC cho sinh
viên kỹ thuật. Khác với cách xây dựng các bài giảng trước đây về vi điều khiển, người ta cố
gắng trang bị các ngoại vi phổ biến càng nhiều càng tốt, nhưng xem ra, các ngoại vi này chỉ
đều là các chức năng I/O thông thường như: LED, nút bấm, LED ma trận, LED 7 đoạn, màn
hình LCD segment, ADC ngoài, các thanh ghi dịch,… Chúng tôi lại nhận thấy một cách nhìn
khác khi làm việc với vi điều khiển, đó là vi điều khiển, trên cơ bản có thể thực hiện được 3
nhóm nhiệm vụ: Điều khiển, Giao tiếp và Xử lý. Bên cạnh đó, ngày nay, với hướng đi SoC
(System on Chip), người ta càng tích hợp nhiều hơn các tính năng cho vi điều khiển, và cũng
không nằm ngoài 3 nhóm nhiệm vụ trên. Chính vì thế, chúng tôi xây dựng một mô hình bài
giảng và sản phẩm BOOK1 nhằm tập trung làm rõ và chứng minh năng lực của 3 nhóm nhiệm
vụ này trong vi điều khiển, đồng thời khai thác một cách tối đa các tính năng được tích hợp
sẵn trong vi điều khiển PIC16F877A.
Trong phần thực hành này, chúng ta sẽ thực hiện các bài tập sử dụng phần mềm MPLAB
để lập trình, gỡ lỗi và nạp chương trình vào PIC microcontrollers bằng phần mềm Pickit2/3.
2
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Cửa sổ New Project hiện lên và bạn chọn Microchip Embedded >> Standalone Project
>> Next.
3
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
4
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Sau đó cửa số lệnh hiện lên project mà bạn đã tạo chứa các nguồn folder như sau:
Một project đơn giản nhất phải gồm có 2 thành phần Source files và Hearder Files. Thư
mục Source files chứa file text *.asm hoặc file *.c chứa code lập trình. Thư mục Hearder Files
chứa file *.h hoặc *.INC: file có sẵn của microchip. User khai báo dùng loại chip gì >> add
vào thư mục này.
Bắt đầu tạo file main.c từ Source files để lập trình cho PIC thực thi chương trình.
>>>
5
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
6
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
GPIO_init();
while(1)
{
__delay_ms(100);
// Anode();
Cathode();
__delay_ms(100);
}
}
void GPIO_init(void)
{
TRISBbits.TRISB0 = 0; // RB0 LÀ OUTPUT
TRISBbits.TRISB7 = 0; // RB7 LÀ OUTPUT
PORTBbits.RB0 = 1; // ON LED RB0
PORTBbits.RB7 = 0; // OFF LED RB7
}
/*
void Anode (void)
{
PORTBbits.RB0 = 0;
__delay_ms(500);
PORTBbits.RB0 = 1;
}
*/
void Cathode (void)
{
PORTBbits.RB7 = 1;
__delay_ms(500);
PORTBbits.RB7 = 0;}
Sau khi trình biên dịch phát hiện không có lỗi và build project thành công. Dưới cửa sổ
thực thi sẽ hiển thị như sau:
7
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
8
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Chọn Create Firmware Project cho mạch được thiết kế cần mô phỏng. Khi sử dụng phần
mềm trình biện dịch nào cho file .hex chúng ta cần chọn firmware tương ứng. Ở đây sử dụng
MPLAB XC 8 compiler >> Next.
Sau đó cửa sổ lệnh sẽ xuất hiện như sau. Proteus cho phép viết chương trình cho vi điều
khiển trực tiếp trên phần mềm để mô phỏng. Chúng ta sẽ bỏ qua phần này chỉ quan tâm đến
cách ADD file .hex để mô phỏng.
Đây là giao diện khi đã thiết kế các linh kiện ngoại vi như led, bộ dao động thạch anh
20Mhz, nút nhấn.
9
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Sai
Click vào PIC16F877A sau đó nhấn chuột phải sẽ hiển thị cửa sổ để trỏ thư mục chứa file
.hex vào chương trình mô phỏng.
Edit vị trí ở Program File chỉ dẫn đến file .hex >> click OK.
Có thể copy đường dẫn được hiển thị sau khi biên dịch ở phần mềm MPLAB như sau:
10
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Sơ đồ đấu nối dây giữa Pickit3 và vi điều khiển PIC 16F877A để nạp chương trình.
Nguồn: https://linhkienthanhcong.com/mach-nap-pickit3-kem-giac-icd2
11
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Khi mới sử dụng lần đầu bạn cần nạp firmware, làm theo các bước sau để nạp firmware.
Tải file .hex để nạp vào chương trình bằng Import Hex >> Click vào Write để nạp chương
trình.
12
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
13
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Theo yêu cầu sơ đồ hiển thị LED có kết nối như sau:
14
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Khi phím được nhấn, do tác động của hiện tượng rung cơ học, tín hiệu điện tại ngõ ra bị
chuyển trạng thái giữa logic 0 và logic 1. Khi phím được thả, hiện tượng rung cũng xảy ra
tương tự.
c. LED 7 đoạn
Led 7 đoạn gồm 7 đoạn được đánh dấu: a, b, c, d, e, f, g và một ddierm dp được kí tự là
h. Led 7 đoạn có hai loại là Common Anode và Common Cathode, tương ứng các LED nối
chung Anode hay nối chung Cathode.
15
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Bước 2: Khai báo các cấu hình cho PIC 16F877A. Click vào Window >> trỏ chuột vào Target
Memmory >> chọn Configuration Bits >> Tắt và mở cấu hình các chức năng cần thiết.
16
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Tiếp theo click vào “Generate Source Code to Output” và copy các đoạn mã cấu hình
vào chương trình chính.
Bước 3: Khai báo các thanh ghi của PORTB để thực hiện yêu cầu ngõ ra.
Bước 4: Sử dụng hàm delay có sẵn để làm chương trình delay 1s.
Bước 5: Viết chương trình chính thực hiện yêu cầu.
CHƯƠNG TRÌNH CHÍNH THỰC HIỆN YÊU CẦU 1:
/*
* File: led_on.c
* Author: Thethinh
*/
// CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
17
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
if (count < 16 && status == 0) // Điều kiện nếu nhỏ hơn 16 thì đếm từ 0 đến 15
{
PORTB = count;
display(count);
__delay_ms(1000);
count++;
if (count == 15)
{
status = 1;
}
}
else // Ngược lại đếm từ 15 về 0
{
PORTB = count;
display(count);
18
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
__delay_ms(1000);
count--;
if (count == 0)
{
status = 0;
}
}
}
}
// Chương trình con hiển thị LED 7 đoạn
void display (unsigned int count)
{
chuc = count/10;
donvi = count%10;
PORTAbits.RA0 = 0; // LED don vi
PORTC = LED7Seg[donvi];
__delay_ms(50);
PORTAbits.RA0 = 1;
PORTAbits.RA1 = 0; // LED chuc
PORTC = LED7Seg[chuc];
__delay_ms(50);
PORTAbits.RA1 = 1;
}
19
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Bước 3: Khai báo các thanh ghi của PORTA và PORTB để thực hiện yêu cầu ngõ vào và
ngõ ra.
Bước 4: Viết chương trình chính thực hiện yêu cầu.
CHƯƠNG TRÌNH CHÍNH THỰC HIỆN YÊU CẦU 2:
/*
* File: led_on.c
* Author: Thethinh
*/
// CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = OFF
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
// Khai báo thư viện
#include <xc.h>
#include <stdint.h>
#include <stdio.h>
#include "config_uart.h"
// Định nghĩa và khai báo các biến và hàm
#define _XTAL_FREQ 20000000
void set_GPIO(void);
unsigned char count = 0;
unsigned int i,j = 1;
unsigned char status = 0;
const unsigned char LED7Seg[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82,0xF8, 0x80, 0x90};
unsigned int chuc,donvi,ng_dv, ng_c;
void display(unsigned count);
// Chương trình con set up các chân I/O
void set_GPIO(void)
{
TRISB = 0X00; // Định nghĩa ngõ ra của tất cả kênh B
PORTB = 0X00; // Định nghĩa trạng thái ban đầu của tất cả kênh B ở mức thấp
TRISAbits.TRISA4 = 1; // Định nghĩa ngõ vào
ADCON1 = 0x07;
}
// Chương trình chính của hệ thống
void main(void) {
set_GPIO(); //Gọi chương trình con I/O để thực hiện
while(1)
{
if (PORTAbits.RA4 == 0) // Nếu nhấn nút bấm thì đèn sẽ sáng
{
PORTBbits.RB0 = 1;
}
else // Nếu không bấm đền sẽ tắt
{
20
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
PORTBbits.RB0 = 0;
}
}
}
// Chương trình con hiển thị LED 7 đoạn
void display (unsigned int count)
{
chuc = count/10;
donvi = count%10;
PORTAbits.RA0 = 0; // LED don vi
PORTC = LED7Seg[donvi];
__delay_ms(50);
PORTAbits.RA0 = 1;
PORTAbits.RA1 = 0; // LED chuc
PORTC = LED7Seg[chuc];
__delay_ms(50);
PORTAbits.RA1 = 1;
}
21
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
22
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
23
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
24
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Muốn Timer 0 hoạt động ở chế độ Timer ta clear bit TOSC (OPTION_REG<5>), khi đó
giá trị thanh ghi TMR0 sẽ tăng theo từng chu kì xung đồng hồ (tần số vào Timer0 bằng ¼ tần
số oscillator). Muốn Timer 0 hoạt động ở chế độ counter ta set bit TOSC
25
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
(OPTION_REG<5>). Khi đó xung tác động lên bộ đếm được lấy từ chân RA4/TOCK1. Bit
TOSE (OPTION_REG<4>) cho phép lựa chọn cạnh tác động vào bộ đếm. Cạnh tác động sẽ
là cạnh lên nếu TOSE = 0 và cạnh tác động sẽ là cạnh xuống nếu TOSE = 1.
Các thanh ghi điều khiển liên quan đến Timer 0 bao gồm:
Thanh ghi 8 bit chứa giá trị của bộ định thời Timer 0.
Thanh ghi chứa các bit điều khiển và các bit cờ hiệu khi Timer 0 bị tràn, ngắt ngoại vi
RB0/INT và ngắt interrput-on-change tại các chân của PORTB.
26
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
INTEDG = 1 ngắt xảy ra khi cạnh dương chân RB0/INT xuất hiện.
TOSC = 0 dùng xung clock bên trong (xung clock này bằng với xung clock dùng để thực thi
lệnh).
27
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Các bit này cho phép thiết lập tỉ số chia tần số của Prescaler
3.1.2 Timer 1
Timer 1 là bộ định thời 16 bit, giá trị của Timer 1 sẽ được lưu trong hai thanh ghi
(TMR1H:TMR1L). Tương tự như Timer 0, Timer 1 cũng có hai chế độ hoạt động: chế độ
định thời (timer) với xung kích là xung clock của oscillator (tần số của timer bằng ¼ tần số
của oscillator) và chế độ đếm (counter) với xung kích là xung phản ánh các sự kiện cần đếm
lấy từ bên ngòai thông qua chân RC0/T1OSO/T1CKI (cạnh tác động là cạnh lên).Sau đây là
sơ đồ khối của Timer 1.
Ngoài ra Timer 1 còn có chức năng reset input bên trong được điều khiển bởi một trong hai
khối CCP (Capture/Compare/PWM).
28
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Thanh ghi INTCON (địa chỉ 0Bh, 8Bh, 10Bh, 18Bh): cho phép ngắt hoạt động (GIE và
PEIE).
PSPIF = 1 vừa hoàn tất thao tác đọc hoặc ghi PSP (phải xóa bằng chương trình).
PSPIF = 0 không có thao tác đọc ghi PSP nào diễn ra.
29
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
CCP1IF=0 chưa cập nhật giá trị trong thanh ghi TMR1.
CCP1IF=1 giá trị cần so sánh bằng với giá trị chứa trong TMR1.
CCP1IF=0 giá trị cần so sánh không bằng với giá trị trong TMR1.
TMR2IF = 1 giá trị chứa trong thanh ghi TMR2 bằng với giá trị chứa trong thanh ghi PR2.
TMR2IF = 0 giá trị chứa trong thanh ghi TMR2 chưa bằng với giá trị chứa trong thanh ghi
PR2.
TMR1IF = 1 thanh ghi TMR1 bị tràn (phải xóa bằng chương trình).
Thanh ghi chứa các bit cho phép các ngắt ngoại vi.
30
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
31
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
T1OSCEN = 1 cho phép Timer1 hoạt động với xung do oscillator cung cấp.
T1OSCEN = 0 không cho phép Timer 1 hoạt động với xung do oscillator cung cấp (tắt bộ
chuyển đổi xung bên trong Timer1).
Khi TMR1CS = 1
Khi TMR1CS = 0
Bit T1SYNC không được quan tâm do Timer1 sử dụng xung clock bên trong.
TMR1CS = 1 chọn xung đếm là xung ngoại vi lấy từ pin RC0/T1OSC /T1CKI (cạnh tác động
là cạnh lên).
3.1.3 Timer 2
Timer 2 là bộ định thời 8 bit và được hỗ trợ bởi hai bộ chia tần số prescaler và postscaler.
Thanh ghi chứa giá trị đếm của Timer 2 là TMR2.
32
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Timer 2 còn được hỗ trợ bởi thanh ghi PR2. Giá trị đếm trong thanh ghi TMR2 sẽ tăng từ
00h đến giá trị chứa trong thanh ghi PR2, sau đó được reset về 00h. Khi reset thanh ghi PR2
được nhận giá trị mặc định FFh. Ngoài ra ngõ ra của Timer2 còn được kết nối với khối SSP,
do đó Timer 2 còn đóng vai trò tạo ra xung clock đồng bộ cho khối giao tiếp SSP.
Thanh ghi INTCON (địa chỉ 0Bh, 8Bh, 10Bh, 18Bh): cho phép tòan
Thanh ghi PIR1 (địa chỉ 0Ch): chứa cờ ngắt Timer 2 (TMR2IF).
Thanh ghi PIE1 (địa chị 8Ch): chứa bit điều khiển Timer 2 (TMR2IE).
Thanh ghi TMR2 (địa chỉ 11h): chứa giá trị đếm của Timer 2.
Các bit này điều khiển việc lựa chọn tỉ số chia tần số cho postscaler.
33
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
0000 tỉ số 1:1
0001 tỉ số 1:2
0010 tỉ số 1:3
……………………
1111 tỉ số 1:16
00 tỉ số 1:1
01 tỉ số 1:4
1x tỉ số 1:16
Thanh ghi PR2 (địa chỉ 92h): thanh ghi hỗ trợ cho Timer 2. Thanh ghi dùng để ấn định trước
giá trị đếm cho Timer 2. Khi vi điều khiển được reset, PR2 mang giá trị FFh. Khi ta đưa một
giá trị vào thanh ghi PR2, Timer 2 sẽ đếm từ 00h cho đến khi giá trị bộ đếm của Timer 2 bằng
với giá trị của bộ đếm trong thanh ghi PR2. Như vậy mặc định Timer 2 sẽ đếm từ 00h đến
FFh.
3.1.4 Giao tiếp LCD ký tự 2x16
a. Hình dạng và ý nghĩa các chân
34
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Character Generator Ram (CGRAM): lưu trữ tám mẫu ký tự do người dùng định
nghĩa. Tám mẫu ký tự này tương ứng với các mã ký tự D7-D0 = 0000*D2D1D0 (* mang giá
trị tùy định 0 hay 1).
35
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Character Generator Rom (CGROM): lưu trữ cứng các mẫu ký tự tương ứng với mã
ASCII. Dưới đây là bảng ánh xạ giữa mã ký tự và mẫu ký tự.
Chúng ta muốn hiển thị chữ “CE” ở giữa hàng đầu tiên, giả sử cửa sổ hiển thị đang bắt
đầu từ vị trí đầu tiên (hàng thứ nhất hiển thị dữ liệu của ô nhớ từ 0x00 đến 0x0f, hàng thứ hai
hiển thị dữ liệu của ô nhớ từ 0x40 đến 0x4f, đây là vị trí home). Giá trị của ô nhớ 0x07 là
0x43 (ký tự C), của ô nhớ 0x08 là 0x45 (ký tự E). Chúng ta muốn hiển thị chữ “®” ở giữ hàng
thứ hai, giả sử cử sổ hiển thị đang ở vị trí home. Trong bảng mẫu ký tự chúng ta thấy không
có mẫu “®”. Lúc này chúng ta phải định nghĩa mẫu “®” 5x8 điểm, gồm có 8 byte, sau đó lưu
vào vị trí của mẫu ký tự CGRAM thứ nhất. Lúc này giá trị của ô nhớ 0x47 là 0x00 hoặc 0x08
(vị trí của mẫu ký tự CGRAM thứ nhất “®”).
c. Các lệnh giao tiếp với LCD
36
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Các bit trên bảng tóm tắt các lệnh có ý nghĩa như sau:
Ở thí nghiệm này LCD sẽ hoạt động ở chế độ 4 bit, để đọc hay ghi một byte phải tiến
hành cài dữ liệu hai lần, lần đầu là 4 bit cao, lần thứ hai là 4 bit thấp.
3.2 THỰC HIỆN CÁC YÊU CẦU
3.2.1 Các bước thực hiện yêu cầu 1
Bước 1: Tạo project mới giống như hướng dẫn ở Phần 1 lấy tên project là Timer_LED,
tạo file Timer_led.c và chọn chip 16F877A trong MPLAB. Ta được hình sau:
37
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Bước 2: Khai báo các cấu hình cho PIC 16F877A. Click vào Window >> trỏ chuột vào
Target Memmory >> chọn Configuration Bits >> Tắt và mở cấu hình các chức năng cần thiết.
Tiếp theo click vào “Generate Source Code to Output” và copy các đoạn mã cấu hình
vào chương trình chính.
38
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Bước 3: Khai báo các thanh ghi của PORTB để thực hiện yêu cầu ngõ ra. Cần gán giá trị
cho thanh ghi ADCON1 vì thanh ghi này có chức năng chọn các PORT có chức năng là
input/output digital hay là input Analog. Do đó, trước khi sử dụng các port ta phải kiểm tra
xem thanh ghi ADCON1 đã cấu hình đúng chưa.
Bước 4: Khởi tạo ngắt timer 1 cứ sau 100ms thì vào ngắt một lần. Chọn Prescalar: 8 và
tần số thạch anh là 8 Mhz.
Giá trị thanh ghi ban đầu của timer 1 được tính như sau:
RegValue = 65536-(Delay * Fosc)/(Prescalar*4)) = 65536- ((100ms * 8Mhz)/(8*4)) = 40536
Nên khi ta để giá trị trong các thanh ghi của timer 1 giá trị 40530 thì cứ sau 100ms, timer sẽ
ngắt một lần. Để sau 1s đến lên 1 đơn vị. Ta lặp lại ngắt của timer 1 là 10 lần.
Bước 5: Viết chương trình chính thực hiện yêu cầu.
CHƯƠNG TRÌNH CHÍNH THỰC HIỆN YÊU CẦU 1:
/*
* File: main.c
* Author: Thethinh
*/
// CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = OFF
39
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
40
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
41
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
42
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
43
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
INTCONbits.TMR0IF = 0;
TMR0 = 100;
Count ++;
if (Count >= 1000)
{
tat_led();
Count = 0;
}
}
}
}
44
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
if(a & 2)
D5 = 1;
else
D5 = 0;
if(a & 4)
D6 = 1;
else
D6 = 0;
if(a & 8)
D7 = 1;
else
D7 = 0;
}
void Lcd_Cmd(char a)
{
RS = 0; // => RS = 0
Lcd_Port(a);
EN = 1; // => E = 1
__delay_ms(4);
EN = 0; // => E = 0
}
void Lcd_Clear(void)
{
Lcd_Cmd(0);
Lcd_Cmd(1);
}
45
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
char temp,z,y;
if(a == 1)
{
temp = 0x80 + b - 1;
z = temp>>4;
y = temp & 0x0F;
Lcd_Cmd(z);
Lcd_Cmd(y);
}
else if(a == 2)
{
temp = 0xC0 + b - 1;
z = temp>>4;
y = temp & 0x0F;
Lcd_Cmd(z);
Lcd_Cmd(y);
}
}
void Lcd_Init(void)
{
Lcd_Port(0x00);
__delay_ms(20);
Lcd_Cmd(0x03);
__delay_ms(5);
Lcd_Cmd(0x03);
__delay_ms(11);
Lcd_Cmd(0x03);
/////////////////////////////////////////////////////
Lcd_Cmd(0x02);
Lcd_Cmd(0x02);
Lcd_Cmd(0x08);
Lcd_Cmd(0x00);
Lcd_Cmd(0x0C);
Lcd_Cmd(0x00);
Lcd_Cmd(0x06);
}
void Lcd_Write_Char(char a)
{
char temp,y;
temp = a&0x0F;
y = a&0xF0;
RS = 1; // => RS = 1
Lcd_Port(y>>4); //Data transfer
EN = 1;
__delay_us(40);
EN = 0;
46
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Lcd_Port(temp);
EN = 1;
__delay_us(40);
EN = 0;
}
void Lcd_Shift_Right(void)
{
Lcd_Cmd(0x01);
Lcd_Cmd(0x0C);
}
void Lcd_Shift_Left(void)
{
Lcd_Cmd(0x01);
Lcd_Cmd(0x08);
}
Main file - Code chính
* File: main.c
* Author: Thethinh
*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "my_lcd.h"
#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
47
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
#define D6 RD6
#define D7 RD7
// BEGIN CONFIG
//END CONFIG
void main(void)
{
char s[20];
unsigned int a;
TRISD = 0x00;
Lcd_Init();
while(1)
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Set_Cursor(2,1);
Lcd_Write_String(" VI DIEU KHIEN ");
48
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
__delay_ms(2000);
Lcd_Clear();
Lcd_Set_Cursor(1,1);
for(a=0;a<15;a++)
__delay_ms(300);
Lcd_Shift_Left();
for(a=0;a<15;a++)
__delay_ms(300);
Lcd_Shift_Right();
Lcd_Clear();
Lcd_Set_Cursor(2,1);
__delay_ms(2000);
}}
49
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
50
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
51
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
52
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Quy trình chuyển đổi tín hiệu số sang tín hiệu tương tự:
1. Thiết lập các thông số cho bộ chuyển đổi ADC:
• Chọn điện áp mẫu (dựa trên các thông số của thanh ghi ADCON1)
• Chọn kênh chuyển đổi AD (thanh ghi ADCON0)
• Chọn xung clock cho kênh chuyển đổi AD (thanh ghi ADCON0)
• Cho phép bộ chuyển đổi AD hoạt động (thanh ghi ADCON0).
2. Thiết lập các cờ ngắt cho bộ AD
• Clear bit ADIF, ADIE, PEIE, GIE.
3. Đợi cho tới khi quá trình lấy mẫu hoàn tất.
4. Bắt đầu quá trình chuyển đổi (set GO/DONE bit ).
5. Đợi cho tới khi quá trình chuyển đổi hoàn tất bằng cách 1 trong 2 cách:
• Kiểm tra bit GO/DONE. Nếu GO/DONE=0, quá trình chuyển đổi đã hoàn tất
• Kiểm tra cờ ngắt.
6. Đọc kết quả chuyển đổi và xóa cờ ngắt, set bit GO/DONE (nếu cần tiếp tục chuyển
đổi ).
7. Tiếp tục thực hiện các bước 1 và 2 cho quá trình chuyển đổi tiếp theo.
4.1.2 Khối chức năng đặt biệt PWM
PWM (Pulse-width modulation) là một kỹ thuật được sử dụng rất nhiều trong hệ thống
truyền thông và nhiều ứng dụng khác như điều khiển vận tốc của động cơ DC hoặc điều khiển
cường độ (intensity).
Sơ đồ khối chức năng PWM của Pic16F877A:
53
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
54
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
55
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
{
ADCON0 = 0b01000001; //0x41
ADCON1 = 0b11000000; //0xC0
}
unsigned int ADC_Read(unsigned char channel)
{
if(channel > 7)
return 0;
ADCON0 &= 0xC5;
ADCON0 |= channel<<3;
__delay_ms(2);
GO_nDONE = 1;
while(GO_nDONE);
return ((ADRESH<<8)+ADRESL);
}
void main()
{
unsigned int a;
TRISB = 0x00;
TRISC = 0x00;
ADC_Init();
do
{
a = ADC_Read(0);
PORTB = a;
PORTC = a>>8;
__delay_ms(100);
}while(1);
}
56
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
57
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = ON
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
#define _XTAL_FREQ 20000000
#define TMR2PRESCALE 4
#include <xc.h>
long PWM_freq = 5000;
void PWM_Initialize();
void PWM_Duty(unsigned int duty);
void PWM_Initialize()
{
PR2 = (_XTAL_FREQ/(PWM_freq*4*TMR2PRESCALE)) - 1; //Setting the PR2
formulae using Datasheet // Makes the PWM work in 5KHZ
CCP1M3 = 1; CCP1M2 = 1; //Configure the CCP1 module
T2CKPS0 = 1;T2CKPS1 = 0; TMR2ON = 1; //Configure the Timer module
TRISC2 = 0; // make port pin on C as output
}
void PWM_Duty(unsigned int duty)
{
if(duty<1023)
{
duty = ((float)duty/1023)*(_XTAL_FREQ/(PWM_freq*TMR2PRESCALE)); // On
reducing //duty = (((float)duty/1023)*(1/PWM_freq)) / ((1/_XTAL_FREQ) *
TMR2PRESCALE);
CCP1X = duty & 1; //Store the 1st bit
CCP1Y = duty & 2; //Store the 0th bit
CCPR1L = duty>>2;// Store the remining 8 bit
}
}
void ADC_Initialize()
58
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
{
ADCON0 = 0b01000001; //ADC ON and Fosc/16 is selected
ADCON1 = 0b11000000; // Internal reference voltage is selected
}
unsigned int ADC_Read(unsigned char channel)
{
ADCON0 &= 0x11000101; //Clearing the Channel Selection Bits
ADCON0 |= channel<<3; //Setting the required Bits
__delay_ms(2); //Acquisition time to charge hold capacitor
GO_nDONE = 1; //Initializes A/D Conversion
while(GO_nDONE); //Wait for A/D Conversion to complete
return ((ADRESH<<8)+ADRESL); //Returns Result
}
void main()
{
int adc_value;
TRISC = 0x00; //PORTC as output
TRISA = 0xFF; //PORTA as input
TRISD = 0x00;
ADC_Initialize(); //Initializes ADC Module
PWM_Initialize(); //This sets the PWM frequency of PWM1
do
{
adc_value = ADC_Read(4); //Reading Analog Channel 0
PWM_Duty(adc_value);
__delay_ms(50);
}while(1); //Infinite Loop
}
59
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
60
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
61
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
62
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
- Thanh ghi PIE1 (địa chỉ 8Ch): chứa bit cho phép ngắt RCIE.
- Thanh ghi RCSTA (địa chỉ 18h): xác định các trang thái trong quá trình nhận dữ liệu.
- Thanh ghi RCREG (địa chỉ 1Ah): chứa dữ liệu nhận được.
- Thanh ghi TXSTA (địa chỉ 98h): chứa các bit điều khiển SYNC và BRGH.
- Thanh ghi SPBRG (địa chỉ 99h): điều khiển tốc độ baud.
63
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
Ví dụ, mình muốn tốc độ truyền là 9600 bit/s ở chế độ bất đồng bộ 8 bit, tần số thạch anh nội
của PIC16F877A là 8MHz :
Vì thế ta sẽ ghi giá trị 12 vào cặp thanh ghi <SPBRGH:SPBRG> để có được tốc độ thỏa mãn
yêu cầu.
5.1.2 SPI
5.2 THỰC HIỆN CÁC YÊU CẦU
5.2.1 Các bước thực hiện yêu cầu 1
Bước 1 và Bước 2 thực hiện như phần 3
Bước 3: Cấu hình 2 chân RC6 là chân TX, RC7 là RX, thanh ghi SPBRG để xác định tốc
độ baudrate và chọn mode tốc độ cao chọn chế độ bất đồng bộ, truyền nhận 8 bit.
Bước 4: Viết chương trình chính thực hiện yêu cầu.
CHƯƠNG TRÌNH CHÍNH THỰC HIỆN YÊU CẦU 1:
Head file – Bao gồm thư viện “uart.h”
#include <xc.h>
#define _XTAL_FREQ 8000000
void UART1_Init(int Baud_rate)
{
// cau hinh chan uart
TRISCbits.TRISC6 = 0; // TX Pin set as output
TRISCbits.TRISC7 = 1; // RX Pin set as input
SPBRG = ((_XTAL_FREQ / 16) / Baud_rate) - 1;
BRGH = 1; // baudrate toc do cao
SYNC = 0; // Asynchronous
SPEN = 1; // cho phep cong noi tiep
TXEN = 1; // cho phep truyen
CREN = 1; // cho phep nhan
// chon che do truyen nhan 8 bits
64
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
TX9 = 0;
RX9 = 0;
}
void UART_sendChar(char bt)
{
while (!TXIF); //lam tre he thong khi bo dem TX dang trong
TXREG = bt; // ghi gia tri truyen vao thanh ghi TXREG
}
char UART1_Read()
{
if (OERR) // check Error
{
CREN = 0; //If error -> Reset
CREN = 1; //If error -> Reset
}
while (!RCIF); // lam tre he thong khi bo dem RX dang trong
return RCREG;
}
void UART1_Write(char* str)
{
while (*str)
{
UART_sendChar(*str++);
}
}
Code chính cho PIC truyền
// CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config BOREN = OFF
#pragma config LVP = ON
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
#include <xc.h>
#include "uart.h"
#define _XTAL_FREQ 8000000
void main()
{
TRISB = 0xFF;
PORTB = 0x00;
UART1_Init(9600); // Initialize UART module at 9600bps
__delay_ms(100); // Wait for UART module to stabilize
while (1)
{ // Endless loop
UART_sendChar(PORTB); // and send data via UART
__delay_ms(500);
}
}
Code chính cho PIC nhận
65
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
// CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config BOREN = OFF
#pragma config LVP = ON
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
#include <xc.h>
#include "uart.h"
#define _XTAL_FREQ 8000000
void main()
{
TRISB = 0;
PORTB = 0;
UART1_Init(9600); // Initialize UART module at 9600bps
__delay_ms(100); // Wait for UART module to stabilize
while (1)
{// Endless loop
PORTB = UART1_Read(); // read the received data,
}
}
66
Trường Đại học Kỹ thuật – Công nghệ Cần Thơ Tài liệu thực hành vi điều khiển
67