Professional Documents
Culture Documents
Bai Tap Thuc Hanh
Bai Tap Thuc Hanh
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
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ẽ)
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
- 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>
void main()
while(1)
delay_ms (500);
//#include <main.h>
#include <16f877a.h>
#include <def_877a.h>
void main()
while(1)
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>
//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.
#bit congb0 = congb.0 //dinh nghia lai ten cho pin RB0
void main()
while(1)
if (congb0 ==0)
delay_ms (500);
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
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)
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
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
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:
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
void main()
{
// cau hinh io port
while(1)
{
// hien thi so hang don vi
PORTB = 0x0f9;
PORTC = 0b11111110;
delay_ms(5);
PORTC = 0xff; // chong lem
Mục tiêu:
- Nắm bắt được chức năng và nguyên lý hoạt động của LCD
- Rèn luyện khả năng tư duy, sáng tạo và ham học hỏi trong sinh viên
Chú ý:
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>
void comnwrt(void)
{
RS = 0;
RW = 0;
E = 1;
E = 0;
delay_ms(1);
void datawrt(void)
RS = 1;
RW = 0;
E = 1;
E = 0;
delay_ms(1);
void main(void)
comnwrt();
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>
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);
void main(void)
comnwrt();
//================Lenh ghi du lieu len LCD========
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>
void main()
lcd_putc("Khoa CNTT");
while(TRUE)
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
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
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.
*/
#include <16f877a.h>
#include <def_877a.h>
int dem;
void main()
setup_timer_0 (rtcc_ext_l_to_h); //dinh ngia bo couter 0 tai chan RA4, mac dinh chia tan
la 2
while(1)
dem = get_timer0();
portd = maled7doan[dem];
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à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:
- Ứ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
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 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()
while(1)
set_pwm1_duty(625); // nap gia tri max cho PWM (dong co chay toc do toi da)
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:
- 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
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>
int8 adc;
main()
Setup_ADC(ADC_clock_internal);
set_adc_channel(0); //chon chan A0 de doc vao gia tri analog bang lenh read_adc
while(true)
adc=read_adc (); //doc adc tu chan A0 sau do gan cho bien 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
void main()
int16 adc;
int8 tam;
Delay_us(10);
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,1);
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>
int8 adc_delay;
main()
delay_us(10);
while(1)
{
If (PIN_B0 ==0)
adc_delay=read_adc();
delay_ms(adc_delay);
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>
void main()
float adc_value;
float voltage;
delay_ms(10);
while(TRUE)
adc_value = read_adc();
// LCD HANG 1
lcd_putc("adc=");
printf(lcd_putc,"%f", adc_value);
// LCD hang 2
lcd_putc("voltage=");
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
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
- 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
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
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ễ)