You are on page 1of 48

Bài 1: LẬP TRÌNH VÀO RA SỐ

Mục tiêu:

- Làm quen với phần mềm lập trình PICC, ngôn ngữ lập trình CCS
- Tạo được dự án phần mềm trên PICC
- Hiểu và ứng dụng được các phương pháp lập trình vào ra số trong lập trình cho hệ
thống nhúng trên nền phần cứng VĐK Pic 16F877A
- Sử dụng thành thạo các lệnh cơ bản, lệnh điều khiển rẽ nhánh, vòng lặp trong
CCS.
- Rèn luyện tính tự giác, tư duy và cẩn thận trong quá trình học tập

A. Bài tập hướng dẫn

Bài 1.1: Viết chương trình nhấp nháy led trên cổng D0 (sơ đồ mạch hình vẽ)

Quy trình tạo dự án mới sử dụng Wizard trong PICC:

- Khởi động Project Wizard:


- Nhập tên file, ghi vào thư mục chứa dự án muốn tạo mới
- Chọn loại chip (Device): 16F877A trên danh sách
- Thiết lập tần số thạch anh dao động 20MHz (mặc định có sẵn)
- Đặt các tùy chọn khác rồi nhấn OK để hoàn tất thao tác khởi tạo ban đầu
- Nhấn F9: để thực hiện dịch. Sau khi dịch sẽ xuất hiện file *.h và các thư viện khác
nếu lựa chọn lúc khởi tạo dự án.
- Viết chương trình trên khung cửa sổ mở cho file *.c.
- Dịch chương trình (F9), lấy file *.hex để nạp cho chip trên board mạch thật hoặc
mạch mô phỏng.

Gợi ý giải:

- Dùng phương pháp định nghĩa BYTE, BIT ánh xạ vào địa chỉ tương ứng các

cổng và thao tác trực tiếp.

- Sử dụng Set_Tris_X: để thiết lập trạng thái/khả năng vào/ra của cổng

- Dùng hàm trễ Delay_ms() với tham số có đơn vị trễ 1/1000 giây
Cách 1:

Code:

//#include <main.h>

#include <16f877a.h>

#include <def_877a.h>

#device *=16 ADC=8

#FUSES NOWDT, HS, NOLVP

#use delay(clock = 20000000)

void main()

Set_tris_d (0x00); // port D là cong output

portd = (0xff) ; //gia tri thanh ghi port d =11111111

while(1)

portd =0x00; //gia tri port d =00000000 - cac den sang

delay_ms (500); //tre 500 ms

portd = 0xff; //gia tri port d = 1111111 - cac led tat

delay_ms (500);

Cách 2: Sử dụng khai báo lại tên các chân

//#include <main.h>

#include <16f877a.h>
#include <def_877a.h>

#device *=16 ADC=8

#FUSES NOWDT, HS, NOLVP

#use delay(clock = 20000000)

// dinh nghia cac cong

#byte conga = 0x05 //dinh nghia lai ten cho Port a

#byte congd = 0x08

void main()

Set_tris_d (0x00); // port D là cong output

congd = (0xff) ; //gia tri thanh ghi port d =11111111

while(1)

congd =0x00; //gia tri port d =00000000 - cac den sang

delay_ms (500); //tre 500 ms

congd = 0xff; //gia tri port d = 1111111 - cac led tat

delay_ms (500);

Bài 1.2: Sử dụng nút nhấn kết nối vào chân RB0 như hình vẽ, khi nhấn nút chương các
led sẽ sang nhấp nháy (như trong bài 1)
Code:

//#include <main.h>

#include <16f877a.h>

#include <def_877a.h>

#device *=16 ADC=8

#FUSES NOWDT, HS, NOLVP

#use delay(clock = 20000000)

// dinh nghia cac cong

//Việc định nghĩa lại tên cổng giúp người dùng dễ nhớ, nếu ko muốn định nghĩa lại tên
cổng hoặc tên chân thì ta có thể lấy tên theo file thư viện là PORTA, PORTB….giống
như sử dụng cách 1 của bài 1.

#byte conga = 0x05 //dinh nghia lai ten cho Port a


#byte congb = 0x06

#byte congd = 0x08

//dinh nghia bit

#bit congb0 = congb.0 //dinh nghia lai ten cho pin RB0

void main()

set_tris_b (0x01); //port b =00000001 - chan rb0 la input

Set_tris_d (0x00); // port D là cong output

congd = (0xff) ; //gia tri thanh ghi port d =11111111

while(1)

if (congb0 ==0)

congd =0x00; //gia tri port d =00000000 - cac den sang

delay_ms (500); //tre 500 ms

congd = 0xff; //gia tri port d = 1111111 - cac led tat

delay_ms (500);

B. Bài tập tự làm:

Bài 1.3. Lập trình điều khiển hai LED đơn luân phiên nhấp nháy (LED1 được nối

với D.0, LED 2 nối với D0.1


Bài 1.4. Lập trình điều dãy 8 LED nối với cổng D sáng dần rồi tắt dần.

Bài 1.5. Viết chương trình điều khiển 2 LED liền kề sáng liên tục và dịch chuyển từ trái
sang phải rồi từ phải về trái mỗi khi trạm “mép bên” – nháy đuổi. Sử dụng (các led nối ở
port B)

Bài 1.6. Viết chương trình chia 2 cụm LED (nửa trái/nửa phải, mỗi nửa 4 LED)

nhấp nháy luân phiên

Bài 1.7. Sử sụng nút nhấn làm nút start để thực hiện yêu cầu bài 1.6

Bài 1.8: Viết chương trình cho ma trận phím 4x4 theo sơ đồ kết nối như hình vẽ. Khi
nhấn nút sẽ hiển thị số tương ứng trên led 7 thanh.
BÀI 2: LẬP TRÌNH HIỂN THỊ TRÊN LED 7 THANH

Mục tiêu:

- Nắm bắt được sơ đồ cấu tạo và các loại led 7 thanh trên thực tế

- Lập trình hiển thị trên led 7 thanh theo các phương pháp khác nhau

- Rèn luyện khả năng tư duy, sáng tạo và ham học hỏi trong sinh viên

A. Bài tập tự làm

Bài số 1: Cho sơ đồ kết nối như hình vẽ, viết chương trình hiển thị đếm từ số 0 đến 9 trên
led 7 thanh

Hình 13.5: Kết nối led 7 thanh với port D


Hướng dẫn:
- Ta thiết lập mã cho led 7 thanh theo lạo có trong hình vẽ (loại anot chung)
- Xuất lần lượt từng giá trị ra led sau khoảng thời gian trễ theo ý muốn
Code:
#include <16f877a.h>
#include <def_877a.h>
#device *=16 adc=8
#use delay (clock=20000000) // su dung thach anh 20mhz
#use fast_io (b) // dung voi cac lenh nhu output_low... nhanh hon bthuong
#byte portb=0x06
#byte portd=0x08
void main ()
{
set_tris_d (0x00) ; //pordD la ngo ra
portd = (0xff); // ban đầu tắt led
while (true)
{
delay_ms (500);
portd = (0x0C0); //so 0
delay_ms (500);
portd = (0x0F9); //so 1
delay_ms (500);
portd = (0x0A4); //so 2
delay_ms (500);
portd = (0x0B0); //so 3
delay_ms (500);
portd = (0x99); //so 4
delay_ms (500);
portd = (0x92); //so 5
delay_ms (500);
portd = (0x82); //so 6
delay_ms (500);
portd = (0x0F8); //so 7
delay_ms (500);
portd = (0x80); //so 8
delay_ms (500);
portd = (0x90); //so 9
}
}
Bài tập 2: Cho sơ đồ kết nối như hình vẽ, viết chương trình hiển thị đếm từ số 0 đến 9
trên led 7 thanh
Hình 13.6: Kết nối led 7 thanh với port D thông qua IC 74247
Hướng dẫn:
- Do sơ đồ mạch sử dụng IC giải mã 74247 vì vậy lúc này ta ko cần phải thiết lập
mã như bài số 1
- Muốn hiển thị số chỉ cần xuất mã nhị phân (4 bit) từ các chân được kết nối tương
ứng sẽ được số như mong muốn.
Code:
#include <16f877a.h>
#include <def_877a.h>
#device *=16 adc=8
#use delay (clock=20000000) // su dung thach anh 20mhz
#use fast_io (b) // dung voi cac lenh nhu output_low... nhanh hon bthuong
#byte portb=0x06
#byte portd=0x08

void main ()
{
set_tris_d (0x00) ; //pordD la ngo ra
portd = (0xff);
while (true)
{
delay_ms (500);
portd = (0x00); //so 0
delay_ms (500);
portd = (0x01); //so 1
delay_ms (500);
portd = (0x02); //so 2
delay_ms (500);
portd = (0x03); //so 3
delay_ms (500);
portd = (0x04); //so 4
delay_ms (500);
portd = (0x05); //so 5
delay_ms (500);
portd = (0x06); //so 6
delay_ms (500);
portd = (0x07); //so 7
delay_ms (500);
portd = (0x08); //so 8
delay_ms (500);
portd = (0x09); //so 9
}
}

Bài số 3: Cho sơ đồ mạch như hình vẽ, hãy lập trình theo phương pháp quét led để hiển
thị số 1234 lên trên led 7 đoạn.
Hướng dẫn:

- Sử dụng phương pháp quét led


- Tính toán thời gian quét (số ảnh quét trong một giây)
1000ms = thời gian trễ*số led*số ảnh quét

Ví dụ: Giả sử có 4 led cần quét 50 lần/s


Để hiển thị 50 ảnh trên 1s =1000ms
-> 1000 ms = t/g trễ *6*50
=> t/g trễ = 1000/(4*50) = 5 ms
delay_ms(5);

Code:
#include <16f877a.h>
#include <def_877a.h>
#device *=16 adc=8
#use delay (clock=20000000) // su dung thach anh 20mhz
#use fast_io (b) // dung voi cac lenh nhu output_low... nhanh hon bthuong
#byte porta=0x05
#byte portb=0x06
#byte portc=0x07
#byte portd=0x08

// MA LED 7 DOAN ANOT CHUNG


//unsigned char
//constma_led[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xf8,0x80,0x90};

void main()
{
// cau hinh io port

TRISC = 0; //cau hinh PORTC la ngo ra


PORTC = 0xff; //tat het PORTC

TRISB = 0; //cau hinh PORTb la ngo ra


PORTB = 0xff; //tat het PORTb

while(1)
{
// hien thi so hang don vi
PORTB = 0x0f9;
PORTC = 0b11111110;
delay_ms(5);
PORTC = 0xff; // chong lem

// hien thi so hang chuc


PORTB = 0x0A4;
PORTC = 0b11111101;
delay_ms(5);
PORTC = 0xff; // chong lem

// hien thi so hang tram


PORTB = 0x0B0;
PORTC = 0b11111011;
delay_ms(5);
PORTC = 0xff; // chong lem

// hien thi so hang nghin


PORTB = 0x99;
PORTC = 0b11110111;
delay_ms(5);
PORTC = 0xff; // chong lem
}
}
B. Bài tập tự làm

Bài 4: Viết chương trình đếm từ 0 đến 99 sử dụng:

a. Phương pháp xuất giá trị trực tiếp


b. Phương pháp kết nối thêm IC
c. Quét led

Bài 5: Viết chương trình hiển thị:

a. Số 546 trên led 7 thanh theo phương pháp quét led


b. Một số bất kì trên 3 led 7 thanh
BÀI 3: LẬP TRÌNH HIỂN THỊ TRÊN LCD

Mục tiêu:

- Nắm bắt được chức năng và nguyên lý hoạt động của LCD

- Lập trình hiển thị nội dung trên LCD

- Rèn luyện khả năng tư duy, sáng tạo và ham học hỏi trong sinh viên

A. Bài tập hướng dẫn

Chú ý:

/*Để LCD thực thi các lệnh điều khiển:*/

RS = 0; //chọn thanh ghi lệnh


R/W = 0; //ghi dữ liệu, R/W = 1;//đọc dữ liệu
E= 1; //đưa chân E lên mức cao
E= 0; //tạo sườn xuống để chốt dữ liệu

/*Để LCD thực thi các lệnh hiển thị:*/

RS = 1; //chọn thanh ghi dữ liệu


R/W = 0; //ghi dữ liệu
E = 1; //đưa chân E lên mức cao
E = 0; //tạo sườn xuống để chốt dữ liệu

Bài 1: Cho sơ đồ kết nối của LCD và PIC 16F877A như hình vẽ. Hãy lập trình hiển thị
nội dung “KTMT” ở đầu dòng hàng 1 của LCD
Code:

#include <16f877a.h>

#include <def_877a.h>

#device *=16 adc=8

#use delay (clock=20000000) // su dung thach anh 20mhz

// =================Định nghĩa lại các chân===============

#define RS RE2 //chân RE2 có tên là RS

#define RW RE1 // chân RE1 có tên là RW

#define E RE0 //chân RE0 có tên là E

#define LCD PORTB //PORTB có tên là LCD

//========CAC CHUONG TRINH CON CHO LCD============

/*Ham goi lenh dieu khien LCD*/

void comnwrt(void)
{

RS = 0;

RW = 0;

E = 1;

E = 0;

delay_ms(1);

/*Ham hien thi du lieu len LCD*/

void datawrt(void)

RS = 1;

RW = 0;

E = 1;

E = 0;

delay_ms(1);

//===============CHUONG TRINH CHINH=================

void main(void)

set_tris_B(0); //port B la cong output

set_tris_E(0); //port E la cong output

delay_ms(100); // Tao tre 100ms cho LCD khoi dong


//=================Lenh cau hinh cho LCD==============

LCD = 0x38; // Hai hang, 8 bit interface

comnwrt(); //gọi chương trình để cấu hình

LCD = 0x0C; // Bat hien thi, tat con tro

comnwrt(); // goi chương trình để cấu hình

LCD = 0x86; // Vi tri hang 1,cot 6

comnwrt();

//================Lenh ghi du lieu len LCD========

LCD = 'K'; // Xuat chu L ra LCD

datawrt(); //goi chuong trình ghi du lieu

LCD = 'T';

datawrt();

LCD = 'M';

datawrt();

LCD = 'T';

datawrt();

while (1)

}
Bài 2: Cho sơ đồ mạch như hình 1, viết chương trình hiển thị nội dung KTMT hiển thị ở
giữa hàng số 2 của LCD

Gợi ý: Ta chỉ việc thay lệnh điều khiển cho LCD để con trỏ về vị trí giữa hàng 2 (giá trị
C7h) và code như bài 1

Code:

#include <16f877a.h>

#include <def_877a.h>

#device *=16 adc=8

#use delay (clock=20000000) // su dung thach anh 20mhz

// =================Định nghĩa lại các chân===============

#define RS RE2 //chân RE2 có tên là RS

#define RW RE1 // chân RE1 có tên là RW

#define E RE0 //chân RE0 có tên là E

#define LCD PORTB //PORTB có tên là LCD

//========CAC CHUONG TRINH CON CHO LCD============

/*Ham goi lenh dieu khien LCD*/

void comnwrt(void)

RS = 0;

RW = 0;

E = 1;

E = 0;

delay_ms(1);

}
/*Ham hien thi du lieu len LCD*/

void datawrt(void)

RS = 1;

RW = 0;

E = 1;

E = 0;

delay_ms(1);

//===============CHUONG TRINH CHINH=================

void main(void)

set_tris_B(0); //port B la cong output

set_tris_E(0); //port E la cong output

delay_ms(100); // Tao tre 100ms cho LCD khoi dong

//=================Lenh cau hinh cho LCD==============

LCD = 0x38; // Hai hang, 8 bit interface

comnwrt(); //gọi chương trình để cấu hình

LCD = 0x0C; // Bat hien thi, tat con tro

comnwrt(); // goi chương trình để cấu hình

LCD = 0xC7; // Vi tri hang 2,cot 7

comnwrt();
//================Lenh ghi du lieu len LCD========

LCD = 'K'; // Xuat chu L ra LCD

datawrt(); //goi chuong trình ghi du lieu

LCD = 'K'; // Xuat chu L ra LCD

datawrt(); //goi chuong trình ghi du lieu

LCD = 'M';

datawrt();

LCD = 'T';

datawrt();

while (1)

Bài 3: Cho sơ đồ mạch kết nối như hình vẽ, lập trình hiển thị nội dung như trong hình

Gợi ý:

- Theo như hình vẽ, chúng ta lập trình cho LCD theo chế độ 4 bit
- Sử dụng thư viện LCD có sẵn trong CCS
Code:

#include <LCD_4BIT.h>

#include <def_877a.h>

//========KHAI BAO DINH NGHIA CAC CHAN================

#define LCD_ENABLE_PIN PIN_B2 // chân B2 có tên là LCD_ENABLE_PIN

#define LCD_RS_PIN PIN_B0 //Chan B0 có tên là LCD_RS_PIN

#define LCD_RW_PIN PIN_B1

#define LCD_DATA4 PIN_B4

#define LCD_DATA5 PIN_B5

#define LCD_DATA6 PIN_B6

#define LCD_DATA7 PIN_B7


#include <lcd.c> //chen thu vien LCD

void main()

trisb = (0x00); // port B la cong xuat

lcd_init(); // goi 1 lan trong ham

lcd_gotoxy(4,1); // vi tri con tro: cot 4 hang 1

lcd_putc("Bo mon KTMT");

lcd_gotoxy(4,2); // vi tri con tro: cot 4 hang 1

lcd_putc("Khoa CNTT");

while(TRUE)

B. Bài tập tự làm

Bài 4: Viết chương trình hiển thị trên LCD với các chân kết nối như sau:

RS nối PIN_B0

RW nối PIN_B1

RW nối PIN B2

D0….D7 nối với PORD


Viết chương trình hiển thị nội dung “ Lop” ở giữa hàng 1 và “ 1011XX” ở giữa hàng 2
của LCD

Bài 5: Viết chương trình hiển thị trên LCD với các chân kết nối như sau:

RS nối PIN_B0

RW nối PIN_B1

RW nối PIN B2

D4, D5, D6, D7 của LCD lần lượt nối với các PIN_C4, PIN_C5, PIN_C6, PIN_D7 của vi
điều khiển.

Viết chương trình hiển thị nội dung họ và tên ở giữa hàng 1 và tên lớp ở hàng 2 của LCD
BÀI 4: LẬP TRÌNH TIMER - COUNTER

Mục tiêu:

- Giải thích được hoạt động, ứng dụng của Timer/Count trong VĐK Pic

- Lập trình khai thác các tính năng Timer/Count của VĐK Pic

- Ứng dụng lập trình Timer/Counter với giao tiếp bàn phím, hiển thị LED đơn, LED 7
thanh.

- Rèn luyện khả năng tư duy, sáng tạo và ham học hỏi trong sinh viên

A. Bài tập hướng dẫn

Bài 2. 1: Viết chương trình đếm sự kiện trên chân RA4 (là chân cấp xung clock bên ngoài
của bộ timer0) (sử dụng 1 led 7 thanh như hình vẽ)

Code:

/*Chương trình đọc giá trị của timer với xung clock đưa từ chân bên ngoài – Thông qua
nút nhấn or xung clock.

Lệnh: setup_timer_0 (rtcc_ext_l_to_h); mặc định bộ chia tần là chia cho 2.


➔ Ví dụ tín hiệu xung clock là 2HZ -> qua bộ chia tần còn 1hz –> T = 1S -> Cứ sau
1s giá trị timer tang lên 1 đơn vị).

*/

#include <16f877a.h>

#include <def_877a.h>

#device *=16 ADC=8

#FUSES NOWDT, HS, NOLVP

#use delay(clock = 20000000)

Const unsigned char


maled7doan[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80, 0x90};

int dem;

void main()

set_tris_a (0x10); // porta = 0001000 - chân a4 la input

set_tris_d (0x00); // port d la output

setup_timer_0 (rtcc_ext_l_to_h); //dinh ngia bo couter 0 tai chan RA4, mac dinh chia tan
la 2

set_timer0 (0); dem bat dau tu 0

while(1)

dem = get_timer0();

portd = maled7doan[dem];

Hướng dẫn chạy chương trình:


Trường hợp 1: Sử dụng xung clock có sẵn trong Proteus thiết lập tần số 2Hz (f = 2hz ->
tần số của bộ timer 0 theo chương trình trên là 2/2 =1hz (vì lệnh setup_timer_0
(rtcc_ext_l_to_h); mặc định là chia 2) -> tần số của Timer0 là T = 1/1 = 1s. Vậy cứ sau
1s bộ đếm sẽ tang lên 1 đơn vị -> dễ quan sát.

Trường hợp 2: Thay xung clock có sẵn bằng nút nhấn, nhấn nút và quan sát.

B. Bài tập tự làm:

Bài 2. 2: Viết chương trình như bài 2.1, thay đổi lệnh setup_timer_0 (rtcc_ext_l_to_h);
thành lệnh setup_timer_0 (rtcc_ext_h_to_l); sau đó nạp code chạy và cho nhận xét.

Bài 2. 3: Viết chương trình đếm sự kiện trên chân RA4 (là chân cấp xung clock bên ngoài
của bộ timer0) sử dụng 3 led 7 đoạn để đếm hết giá trị của Timer 0

Bài 2. 4: Viết chương trình đếm sự kiện trên chân RC0 (là chân cấp xung clock bên ngoài
của bộ timer1) ( Sử dụng 2 led 7 đoạn)
BÀI 5: LẬP TRÌNH VỚI BỘ CCP
Mục tiêu:

- Giải thích được hoạt động, ứng dụng của bộ CCP

- Lập trình khai thác các tính năng PWM

- Ứng dụng vào lập trình điều khiển tốc độ: Led sáng tối, động cơ một chiều…

- Rèn luyện khả năng tư duy, sáng tạo và ham học hỏi trong sinh viên

A. Bài tập hướng dẫn

Bài 3.1: Cho thạch anh dao động với tần số 10Mhz, chu kì điều xung là 1ms. Viết
chương trình điều khiển tốc độ động cơ chạy với tốc độ 100%.
Hướng dẫn:

Bước 1: Tính toán thiết lập cho bộ Timer2

FOSC = 10Mhz -> TOSC = 1/10 = 0.1us


Chu kỳ của PWM:
TPWM = [(PR2) +1] *4*TOSC*PVTMR2
 [(PR2) +1] = TPWM / (4*TOSC*PVTMR2)
PVTMR2 có 3 giá trị là chia 1, 4 hoặc 16 ; ta chọn PWtmr2 = 16
 [(PR2) +1] = 1000 / (4*0.1*16) = 156
 PR2 = 156 -1 =155
Khởi tạo lệnh: Setup_timer_2(T2_div_by_16, 155, 1)

Bước 2: Tính toán giá trị điều xung (giá trị mức 1 và mức 0 trong 1 chu kì)

Để điều khiển tốc độ động cơ ở các cấp độ khác nhau ta cần tìm giá trị Value
trong lệnh SET_CCPx_duty (value) (hay tín hiệu ở mức 1 trong một chu kỳ)
Tín hiệu mức 1 trong một chu kỳ lớn nhất bằng chu kỳ PWM -> động cơ chạy nhanh
nhất)
Ta có công thức tính hệ số chu kỳ:
DUTY_CYCLEPWM = Value*TOSC*PVTMR2
Hệ số chu kỳ DUTY_CYCLEPWM (MAX) = TPWM = 1ms =1000us
 1ms = Valuemax*TOSC*PVTMR2
 Valuemax = 1000 /( TOSC*PVTMR2)
 Valuemax = 1000 /(0.1*16) = 625
Vậy động cơ chạy nhanh nhất khi Value = 625
SET_CCP1_Duty(625)
Lúc này ta có thể chia các cấp độ khác nhau ví du động cơ chạy:
50% => SET_CCP1_Duty(312) hay một tốc độ bất kì.
Bước 3: Code chương trình

#include <16F877A.h>

#fuses NOWDT,PUT,HS,NOPROTECT,NOLVP

#use delay(clock=10000000)

void main()

setup_ccp1(CCP_PWM); //cho phép bộ CCP1 hoạt động

setup_timer_2(T2_div_by_16,155,1); // thiết lập chu kì cho PWM = 1ms

while(1)

set_pwm1_duty(625); // nap gia tri max cho PWM (dong co chay toc do toi da)

B. Bài tập tự làm

Bài 3.2: Viết chương trình điều khiển động cơ với các thông số như bài 1, điều khiển tốc
độ động cơ chạy với tốc độ là 50%

Bài 3.3: Viết chương trình điều khiển động cơ với các thông số như bài 1, điều khiển tốc
độ động cơ chạy với tốc độ là 30%

Bài 3.4: Viết chương trình sử dụng nút nhấn để chọn các chế độ chạy tốc độ khác nhau
của động cơ theo bài 3.1, 3.2, 3.3

Chú ý: Quan sát điện áp trên động cơ để so sánh các tốc độ (ví dụ: Động cơ chạy tốc độ
tối đa -> điện áp của động cơ là +45 -> chạy 50% tốc độ thì điện áp hiển thị trên động
cơ sẽ khoảng +22.5)

Bài 3.5: Cho thạch anh dao động với tần số 20Mhz, tần số điều xung là 10Khz. Viết
chương trình điều khiển tốc độ động cơ chạy với 5 cấp tốc độ
BÀI 6: LẬP TRÌNH ADC
Mục tiêu:

- Giải thích được hoạt động của bộ ADC

- Lập trình khai thác các tính năng ADC trên vi điều khiển PIC

- Ứng dụng lập trình điều khiển với các cảm biến có trong thực tế (LM35, quang trở…)

- Rèn luyện khả năng tư duy, sáng tạo và ham học hỏi trong sinh viên

A. Bài tập hướng dẫn

Bài 6.1: Viết chương trình đọc giá trị ADC tại chân RA0 và hiển thị giá trị nhị phân lên
led đơn được kết nối tại PORT B (chọn ADC chế độ 8 bit).

Code:

#include <16f877a.h>

#include <def_877a.h>

#device *=16 adc=8 // chọn ADC che do 8 bit

#use delay (clock=20000000)

int8 adc;
main()

Setup_ADC(ADC_clock_internal);

setup_adc_ports(AN0); // chan AN0 lam chan vao adc

set_adc_channel(0); //chon chan A0 de doc vao gia tri analog bang lenh read_adc

delay_us(10); // tre 10us

while(true)

adc=read_adc (); //doc adc tu chan A0 sau do gan cho bien adc

output_B(adc); //xuat ra port B gia tri adc

output_d(adc);

}}

Bài 6.2: Viết chương trình đọc giá trị ADC tại chân RA0 và hiển thị giá trị nhị phân lên
led đơn được kết nối như hình vẽ (chọn ADC chế độ 10 bit).

Code:

#include <16f877a.h>

#include <def_877a.h>
#device *=16 adc=8 // chọn ADC che do 8 bit

#use delay (clock=20000000)

void main()

int16 adc;

int8 tam;

setup_adc(ADC_CLOCK_INTERNAL); //Dung xung clock noi bo

setup_adc_ports(AN0);//Chi dung 1 dau vao Analog A0, VrefH = 5V

set_adc_channel(0); //Chon kenh vao chan AN0

Delay_us(10);

set_tris_d(0); // cấu hình cho cổng D là output

set_tris_b(0); // cấu hình cho cổng B là output

while (1)

adc=read_adc(); //Doc gia tri ADC (bat dau giai ma, cho, doc KQ)

adc=~adc; //Dao gia tri de hien thi LED cho de quan sat

tam=Make8(adc,0); // ham trich 1 byte tu bien adc tại vị tri thu 0.

//VD: adc=13 -> tam = 3

output_d(tam); //Xuat gia tri ADC dieu khien LED sang

tam=Make8(adc,1);

output_b(tam); //Xuat gia tri ADC dieu khien LED sang

delay_us(10);

}}
Bài 6.3: Viết chương trình điều khiển tốc độ nhấp nháy của các led thông qua biến trở
được kết nối như hình vẽ (Chú ý: Nút nhấn kết nối tại chân RB0 dùng để khởi động
chương trình)

#include <16f877a.h>

#include <def_877a.h>

#device *=16 adc=8 //su dung ADC 8 bit

#use delay (clock=20000000)

int8 adc_delay;

main()

setup_adc(adc_clock_internal); // lay thoi gian lay mau bang xung clock

setup_adc_ports(AN0_AN1_AN3); // chan A0, A1, A3 la chan analog

set_adc_channel (0); // chon doc adc tu chan A0 bang read_adc()

delay_us(10);

while(1)
{

If (PIN_B0 ==0)

adc_delay=read_adc();

output_B (0); //portB=00000000

delay_ms(adc_delay);

output_b (255); // portb=11111111

delay_ms (adc_delay);

} }}

Bài 6.4: Viết chương trình hiển thị giá trị ADC, giá trị điện áp đọc được hiển thị lên LCD
(theo sơ đồ hình vẽ)

Chú ý: Tính toán giá trị điện áp chuyển đổi khi đọc giá trị ADC

adc_value = read_adc();

- Nếu sử dụng ADC 8 bit, điện áp tham chiếu Rvf+ = 5v, Rvf- = 0v thì

Voltage = (adc*5)/255
- Nếu sử dụng ADC 10 bit, điện áp tham chiếu Rvf+ = 5v, Rvf- = 0v thì
Voltage = (adc*5)/1023

voltage = adc_value * 5000.0 /1023; // 5v = 5000mv - don vi tin se la mv, 5000.0 thuc
hien phep chia lay so thuc nham giam bot sai so

Code

#include <LCD_4BIT.h>

#include <def_877a.h>

//========KHAI BAO DINH NGHIA CAC CHAN================

#define LCD_ENABLE_PIN PIN_B2

#define LCD_RS_PIN PIN_B0

#define LCD_RW_PIN PIN_B1

#define LCD_DATA4 PIN_B4

#define LCD_DATA5 PIN_B5

#define LCD_DATA6 PIN_B6

#define LCD_DATA7 PIN_B7

#include <lcd.c> //chen thu vien LCD

void main()

float adc_value;

float voltage;

trisb = (0x00); // port B la cong xuat

lcd_init(); // goi 1 lan trong ham

setup_adc(adc_clock_internal);//thoi gian lay mau 2-6us


setup_adc_ports(an0);//AN0 nhan analog

set_adc_channel(0);//chon chan de doc

delay_ms(10);

while(TRUE)

// doc gia tri adc

adc_value = read_adc();

// LCD HANG 1

lcd_gotoxy(1,1); // vi tri con tro: cot 1 hang 1

lcd_putc("adc=");

lcd_gotoxy(6,1); // vi tri con tro: cot 6 hang 1

printf(lcd_putc,"%f", adc_value);

// LCD hang 2

lcd_gotoxy(1,2); // vi tri con tro: cot 1 hang 2

lcd_putc("voltage=");

lcd_gotoxy(10,2); // vi tri con tro: cot 10 hang 2

printf (lcd_putc,"%f", voltage);

B. BÀI TẬP TỰ LÀM


Bài 6.5. Thay đổi mạch điện ở bài 4.1 để đo điện áp ở dải rộng hơn (0-12V) và thử

nghiệm.

Bài 6.6. Thay đổi mạch điện ở bài 4.1 để đo điện áp ở dại hẹp hơn (0-3V) và lập

trình thử nghiệm.


Bài 6.7. Thay đổi thiết kế mạch ở bài 4.1 để đo và hiển thị kết quả trên LED 7

thanh có 3 chữ số, độ phân giải 8 bit.

Bài 6.8. Thay đổi thiết kế mạch ở bài 4.1 để đo và hiển thị kết quả trên LED 7

thanh có 4 chữ số, độ phân giải 10 bit.


BÀI 7: LẬP TRÌNH ADC
Mục tiêu:

- Trình bày được các ngắt và nguyên lý hoạt động của ngắt trong PIC 16F877A

- Lập trình khai thác các ngắt trong và ngắt ngoài của PIC16F877A

- Rèn luyện khả năng tư duy, sáng tạo và ham học hỏi trong sinh viên

A. Bài tập hướng dẫn

Bài 7.1: Viết chương trình ngắt bật tắt các led theo các nút tương ứng (nút nhấn tại chân
RB4 – đk led tại RD4, nút tại chân RB5 – đk led tại RD5…)
Code:

#include <16f877a.h>
#include <def_877a.h>
#device *=16 adc=8
#use delay (clock=20000000) // su dung thach anh 20mhz
#use fast_io(b) // dung voi cac lenh nhu output_low... nhanh hon binh thuong
#byte portb=0x06
#byte portd=0x08
// =======Chương trình ngắt RB=============
#int_rb
void rb_led()
{
portd=portb;
}
// ================chương trình chính=================
void main()
{
set_tris_b(0xf0); //portb=11110000: B4:B7 la ngo vao, B0:B3 la ngo ra
set_tris_d(0x00); //pordD la ngo ra
enable_interrupts(int_rb); //cho phep ngat RB: bat ki thay doi nao tren B4:B7
enable_interrupts(global); //cho phep ngat tat ca ngat
while(true)
{
}
}

Bài 7.2: Cho sơ đồ mạch kết nối các nút như hình vẽ ở ví dụ 1. Viết chương trình sử dụng
ngắt RB để điều khiển tốc độ nhấp nháy led tại cổng D theo 4 cấp tốc độ tương ứng với 4
nút nhấn.

Code:
#include <16f877a.h>
#include <def_877a.h>
#device *=16 adc=8
#use delay (clock=20000000) // su dung thach anh 20mhz
#use fast_io(B) // dung voi cac lenh nhu output_low... nhanh hon binh thuong
#use fast_io(D)
#byte portb=0x06
#byte portd=0x08
#byte portc=0x07
#byte intcon=0x000B
#bit RB0=0x06.0
#BIT RB1=0x06.1
#BIT RB2=0x06.2
#BIT RB3=0x06.3
#BIT RB4=0x06.4
#BIT RB5=0x06.5
#BIT RB6=0x06.6
#BIT RB7=0x06.7
#BIT RBIF=0x000B.0 //Dinh nghia co ngat cho RB
#BIT RBIE=0x000B.3 // dinh nghia bit cho phep ngat RB
int led=0xff, speed;
// CHUONG TRINH NGAT
#int_RB // cho phep vao ngat ngoai
void ngat_RB()
{
IF ((RBIF)&&(RBIE))
{
// kiem tra nut nhan 1
{
IF(RB4==0)
{
led=0;
speed=250;
}
}
//kiem tra nut nhan 2
{
if(RB5==0)
{
led=0;
speed=100;
}
}
//kiem tra nut nhan 3
{
if(rb6==0)
{
led=0;
speed=50;
}
}
//kiem tra nut nhan 4
{
if(rb7==0)
{
led=0;
speed=20;
}
}
RBIF=0; //XOA CO NGAT RB
}
}
// chuong trinh chinh
void main()
{
set_tris_b(0x0ff); //Pin_rb la cong nhap, vua la cong xuat
set_tris_D(0); // portd la cong xuat
enable_interrupts(global);
enable_interrupts(int_rb);
ext_int_edge(h_to_l);
while(true)
{
portd=led;
delay_ms(speed);
portd=0xff;
delay_ms(speed);
}
}

Bài 7.3: Viết chương trình đếm từ 0 đến 9 sử dụng nút nhấn tại chân RB0 ( sử dụng ngắt
RB0)

Code:
#include <16f877a.h>
#include <def_877a.h>
#device *=16 adc=8
#use delay (clock=20000000)
#use fast_io(d) // dung voi cac lenh nhu output_low... nhanh hon binh thuong
#use fast_io(d)
#byte portb=0x06
#byte portd=0x08
int i;
const unsigned char
machu[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xf8,0x80,0x90};
//chuong trinh ngat
#int_ext // cho phep vao ngat ngoai
void ngat_RB0()
{
//int i; //ko su dung duoc vi se luon lam i= 0 khi co ngat nen chi hien so 0
if(i<10)
{
portd=machu[i];
++i;
}
if(i==10)
{
i=0;
}
}
// chuong trinh chinh
void main()
{
set_tris_b(0x01); //Pin_rb0 la cong nhap
set_tris_d(0x00); // portd la cong xuat
enable_interrupts(global);
enable_interrupts(int_ext);
ext_int_edge(h_to_l);
portd= 0xff;
i = 0;
while(true)
{
}
}

Bài 7.4: Viết chương trình điều khiển hiệu ứng led: Ban đầu các led sáng hết, cứ sau 1s
các led tắt xen kẽ từ trái qua phải (tại 1 thời điểm chỉ có một led tắt)
(Yêu cầu: Sử dụng ngắt timer0 để tạo thời gian trễ)

#include <16f877a.h>
#include <def_877a.h>
#device *=16 adc=8
#use delay (clock=4000000)
#use fast_io(b) // dung voi cac lenh nhu output_low... nhanh hon binh thuong
#byte portb=0x06
#byte portd=0x08
int16 count;
int8 a;
// chuong trinh ngat ngat timer0
#int_timer0 // cho phep vao ngat timer0
void interrupt_timer0()
{
//set_timer0(6);//T_dinhthi = 500us
++count;
if(count==2000) //2000*500=1s
{count=0;
rotate_left(&a,1); //xoay bien a 1 lan 1 bit
}
}
// chuong trinh chinh
void main()
{
set_tris_d(0); //cong B la cong xuat

enable_interrupts(int_timer0); //cho phep ngat timer0 hoat dong


setup_timer_0(rtcc_internal|rtcc_div_2); //chon xung clock noi va chia tan trc 1:2 -> ftimer = 4/4/2 =1/2
enable_interrupts(global); //cho phep tat ca ngat hoat dong
set_timer0(6); //thoi gian tran = T = 1*(256-6)*2 =500
portd = 0x00;
delay_ms (1000);
a=0x01;
while(true)
{
portd=a;
}
}
BÀI TẬP TỰ LÀM

Bài 7.5: Viết chương trình điều khiển hiệu ứng led: Ban đầu các led sáng hết, cứ sau 1s
các led tắt xen kẽ từ trái qua phải (tại 1 thời điểm chỉ có một led tắt)
(Yêu cầu: Sử dụng ngắt timer1 để tạo thời gian trễ)
Bài 7.7: Viết chương trình điều khiển hiệu ứng led: Ban đầu các led sáng hết, cứ sau 1s
các led tắt xen kẽ từ trái qua phải (tại 1 thời điểm chỉ có một led tắt)
(Yêu cầu: Sử dụng ngắt timer2 để tạo thời gian trễ)

You might also like