Professional Documents
Culture Documents
HỒ CHÍ MINH
KHOA ĐIỆN – ĐIỆN TỬ
BỘ MÔN ĐIỆN TỬ – CÔNG NGHIỆP YS
Hình 3-1. Sơ đồ nguyên lý giao tiếp vi điều khiển với module 32 led đơn ............................................. 42
Hình 3-2. Sơ đồ giao tiếp vi điều khiển với 4 nút nhấn đơn ..................................................................... 52
Hình 3-3. Lưu đồ điều khiển 8 led sáng tắt bằng 2 nút ON và OFF ......................................................... 53
Hình 3-4. Lưu đồ điều khiển 8 led sáng tắt bằng 2 nút ON, OFF và INV ............................................... 54
Hình 3-5. Lưu đồ điều khiển 8 led bằng ON, OFF và INV – có chống dội ............................................. 56
Hình 3-6. Điều khiển 32 led sáng tắt dần từ phải sang trái dùng lệnh if .................................................. 61
Hình 4-1. Sơ đồ nguyên lý giao tiếp vi điều khiển với module 4 led 7 đoạn ........................................... 70
Hình 4-2. Sơ đồ khối timer T0: chế độ 8 bit .............................................................................................. 76
Hình 4-3. Sơ đồ khối timer T0: chế độ 16 bit ............................................................................................ 76
Hình 4-4. Hình ảnh led thu phát HY860F và sơ đồ nguyên lý ................................................................. 76
Hình 4-5. Sơ đồ nguyên lý module thu phát hồng ngoại tạo xung ........................................................... 77
Hình 5-1. Giao tiếp vi điều khiển với LCD qua thanh ghi dịch MBI5026 ............................................. 102
Hình 5-2. Hình ảnh các đoạn cho số lớn trên LCD .................................................................................. 111
Hình 5-3. Tìm mã của các đoạn cho số lớn trên LCD ............................................................................. 112
Hình 5-4. Hình ảnh các số lớn từ 0 đến 9 trên LCD ................................................................................ 112
Hình 8-1. Sơ đồ nguyên lý giao tiếp vi điều khiển với 3 led ma trận ..................................................... 208
Bảng 7-1. Các trạng thái điều khiển động cơ bước đủ - cách 1 .............................................................. 180
Bảng 7-2. Các trạng thái điều khiển động cơ bước đủ - cách 2 ............................................................. 181
Bảng 7-3. Các trạng thái điều khiển động cơ nữa bước – cách 1 ........................................................... 181
Bảng 7-4. Các trạng thái điều khiển động cơ nữa bước – cách 2 ........................................................... 181
Bảng 7-5. Các trạng thái điều khiển động cơ DC .................................................................................... 189
MỤC LỤC
GIÁO TRÌNH THỰC HÀNH ..................................................................................................................... i
LỜI NÓI ĐẦU ................................................................................................................................................ ii
DANH SÁCH HÌNH .................................................................................................................................... v
DANH SÁCH BẢNG .................................................................................................................................... x
MỤC LỤC .................................................................................................................................................... xii
Chương 1: CẤU HÌNH KÍT THỰC HÀNH VI ĐIỀU KHIỂN ............................................................... 1
1.1 GIỚI THIỆU BỘ KIT THỰC HÀNH ....................................................................................... 2
1.2 SƠ ĐỒ NGUYÊN LÝ KIT VI ĐIỀU KHIỂN .......................................................................... 4
1.2.1 Hệ thống vi điều khiển PIC18F6722 giao tiếp với các module ngoại vi........................ 4
1.2.2 Module 1: Giao tiếp với 32 Led đơn ................................................................................... 6
1.2.3 Module 2: 8 led 7 đoạn ......................................................................................................... 7
1.2.4 Module 3: LCD 20×4 ............................................................................................................ 8
1.2.5 Module 4: GLCD 128×64 ................................................................................................... 10
1.2.6 Module 5: phím đơn và phím ma trận 4×4 ..................................................................... 10
1.2.7 Module 6: thu phát hồng ngoại tạo xung......................................................................... 11
1.2.8 Module 7: giao tiếp relay, buzzer và động cơ ................................................................. 11
1.2.9 Module 8: các module giao tiếp theo chuẩn I2C ............................................................ 15
1.2.10 Module 9: giao tiếp các cảm biến nhiệt, cảm biến khoảng cách, led thu.................... 16
1.2.11 Module 10: giao tiếp led ma trận ...................................................................................... 18
1.2.12 Module 11: giao tiếp máy tính bằng USB qua IC chuyển đổi UART ......................... 19
1.2.13 Module 12: giao tiếp SIM800 ............................................................................................ 20
1.2.14 Module 13: giao tiếp ADC HX711 .................................................................................... 20
1.2.15 Module 14: giao tiếp module Bluetooth HC-05 .............................................................. 21
1.2.16 Module 15: giao tiếp NRF24L01 ....................................................................................... 21
1.2.17 Module 16: giao tiếp RFID RC522 ................................................................................... 21
1.2.18 Module 17: Wifi BLE ESP32............................................................................................. 21
1.2.19 Module 18: module vi điều khiển trung tâm................................................................... 22
1.2.20 Các Module khác: ............................................................................................................... 24
1.2.21 Module vi điều khiển PIC: ................................................................................................. 24
Chương 2: SỬ DỤNG PHẦN MỀM CCS VÀ PITKIT2 ........................................................................ 29
2.1 GIỚI THIỆU PHẦN MỀM CCS ............................................................................................. 30
2.2 COPY PHẦN MỀM CCS, THƯ VIỆN, CODE MẪU .......................................................... 30
2.2.1 Copy phần mềm, thư viện, code mẫu ............................................................................... 30
xii Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
2.2.2 Cài phần mềm CCS............................................................................................................. 30
2.2.3 Cài phần mềm PICKIT2 .................................................................................................... 30
2.2.4 Sử dụng phần mềm PICKIT2 không cần cài .................................................................. 30
2.3 HƯỚNG DẪN SỬ DỤNG PHẦN MỀM CCS ........................................................................ 31
2.3.1 Khởi động phần mềm CCS ................................................................................................ 31
2.3.2 Chỉnh font chữ phần mềm CCS ........................................................................................ 31
2.3.3 Mở code mẫu ........................................................................................................................ 32
2.3.4 Biên dịch chương trình tạo ra file hex ............................................................................. 33
2.4 HƯỚNG DẪN SỬ DỤNG PHẦN MỀM NẠP FILE HEX PICKIT2 ................................. 35
2.4.1 Kết nối cáp USB và mở nguồn cho kit thực hành .......................................................... 35
2.4.2 Mở phần mềm PICKIT2 .................................................................................................... 35
2.4.3 Nạp file hex tự động ............................................................................................................ 36
2.4.4 Quan sát kết quả ở kit thực hành sau khi nạp................................................................ 36
2.4.5 Cách bố trí hai phần mềm ................................................................................................. 36
2.4.6 PICKIT2 tự động nạp file hex đã nạp khi có thay đổi .................................................. 37
2.4.7 Cách xử lý khi nhận chip không đúng ............................................................................. 37
2.4.8 Cách xử lý khi không nhận mạch nạp ............................................................................. 37
2.4.9 Cách xử lý sau khi nạp xong mà vi điều khiển không chạy.......................................... 38
Chương 3: THỰC HÀNH MODULE 32 LED ĐƠN, NÚT NHẤN ĐƠN ........................................... 41
3.1 CÁC CHƯƠNG TRÌNH ĐIỀU KHIỂN 32 LED ĐƠN ........................................................ 42
3.1.1 Mạch giao tiếp vi điều khiển với module 32 led đơn ..................................................... 42
3.1.2 Thư viện khởi tạo và thư viện của module 32 led đơn .................................................. 42
3.1.3 Các chương trình điều khiển 32 led đơn dùng lệnh for ................................................ 44
3.2 ĐIỀU KHIỂN 32 LED ĐƠN VÀ NÚT NHẤN – CÁCH 1 ................................................... 51
3.2.1 Giới thiệu .............................................................................................................................. 51
3.2.2 Mạch điện giao tiếp vi điều khiển với 4 nút nhấn đơn .................................................. 51
3.2.3 Định nghĩa tên các nút nhấn trong thư viện ................................................................... 52
3.2.4 Các chương trình điều khiển dùng các nút nhấn đơn ................................................... 52
3.3 ĐIỀU KHIỂN 32 LED ĐƠN VÀ NÚT NHẤN – CÁCH 2 ................................................... 57
3.3.1 Hiện tượng đáp ứng chậm, chờ nhả phím ....................................................................... 57
3.3.2 Thư viện hàm quét phím .................................................................................................... 59
3.3.3 Giải quyết các vấn đề để được đáp ứng nhanh............................................................... 60
3.3.4 Tối ưu thời gian delay 20ms của hàm chống dội nút nhấn ........................................... 63
3.3.5 Các bài tập mở rộng dùng lệnh if ..................................................................................... 65
3.3.6 Chương trình chạy tự động ............................................................................................... 67
3.4 THƯ VIỆN CHÍNH .................................................................................................................... 68
1
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
1.1 GIỚI THIỆU BỘ KIT THỰC HÀNH
Chương này giới thiệu bộ kit thực hành vi điều khiển tương đối đầy đủ các yêu cầu phần
cứng như hình 1-1 có thể giúp bạn thực hành và có thể tự nghiên cứu, tự học.
MBI_SDI
MBI_SCK
MODULE 8
MBI_OE LED 7 ĐOẠN
MBI_LE1
RF6
MBI_SDI
MBI_SCK
MODULE
MBI_OE
LCD
RG4 MBI_LE3
PIC18F6722 MBI_SDI
MBI_SCK
MBI_OE MODULE
GLCD
MBI_LE4
RF7
MBI_SDI
MBI_SCK MODULE 3
MBI_OE LED MA
MBI_LE2 TRẬN
RF5
MBI_SDI
MODULE
MBI_SCK
BUZZER
MBI_OE RELAY,
MBI_LE5 MOTOR
RF4
Hình 1-2. Sơ đồ khối vi điều khiển PIC giao tiếp với các module ngoại vi
Có 1 socket để gắn module chuyển đổi UART sang RS485.
Có 1 module mạch nạp cho các loại vi điều khiển.
Các module truyền dữ liệu, giao tiếp với vi điều khiển bằng chuẩn SPI:
Có 1 module RFID RC522
Có 1 module RF NRF 24L01 – 2.4GHZ
Có 1 module wifi BLE ESP32 LUA
1.2 SƠ ĐỒ NGUYÊN LÝ KIT VI ĐIỀU KHIỂN
Kit thực hành vi điều khiển có thể sử dụng nhiều loại vi điều khiển khác nhau, tuy nhiên
tài liệu chỉ trình bày cho loại vi điều khiển PIC18F6722.
1.2.1 Hệ thống vi điều khiển PIC18F6722 giao tiếp với các module ngoại vi
4 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
Sơ đồ khối của kit dùng vi điều khiển PIC18F6722 giao tiếp với 6 module ngoại vi như
hình 1-2.
Kit vi điều khiển có nhiều module ngoại vi, để có thể giao tiếp hết các module ngoại vi thì
có dùng thêm các IC mở rộng port là MB5026.
Các tín hiệu giao tiếp dùng chung là MBI_SDI, MBI_SCK và MBI_OE.
Hai chân MBI_SDI và MBI_SCK có chức năng truyền dữ liệu nối tiếp đồng bộ từng bit từ
vi điều khiển đến các vi mạch thanh ghi dịch MBI5026.
Chân MBI_SDI là truyền dữ liệu và chân MBI_SCK là truyền xung clock.
Chân MBI_OE là chân điều khiển cho phép/không cho phép module hoạt động.
Ba chân này nối song song đến tất cả các module nên khi gửi dữ liệu ra thì cả 6 module
đều nhận và tương tự khi cho phép hoặc không cho phép cả 6 module.
Chân tín hiệu còn lại là MBI_Lex có chức năng điều khiển IC MBI5026 làm cho 6 module
trở nên độc lập nhau.
Ta cần phải tìm hiểu nguyên lý hoạt động của IC thanh ghi dịch MBI5026.
a. Hoạt động của IC MBI5026
IC MBI50256 là thanh ghi dịch có chức năng chuyển dữ liệu từ nối tiếp sang song song và
nối tiếp để mở rộng port điều khiển.
Chỉ cần 4 tín hiệu giao tiếp với một IC MBI5026 thì ta có 16 port điều khiển mở rộng. Nếu
2 IC thì được 32 port mở rộng, …
Sơ đồ khối của vi mạch MBI5026 và bảng trạng thái hoạt động của IC như hình 1-3.
Hình 1-9. Sơ đồ giao tiếp bàn phím cảm ứng điện dung TTP229
1.2.7 Module 6: thu phát hồng ngoại tạo xung
Kit có tích hợp module thu phát hồng ngoại tạo xung khi có sản phẩm che chắn giữa led
phát và transistor thu. Ngõ ra transistor đưa đến mạch chỉnh dạng sóng dùng 2 cổng đảo Schmitt
Trigger rồi đưa đến timer/counter của vi điều khiển để thực hành các bài đếm xung ngoại dùng
counter. Mỗi sản phẩm đi qua sẽ tạo ra một xung tương ứng.
Sơ đồ mạch như hình 1-10.
Hình 1-11. Sơ đồ giao tiếp IC MBI5026 để điều khiển động cơ, buzzer, …
IC MBI có 16 ngõ ra kết nối điều khiển các thành phần như sau:
Năm ngõ ra out0, out7, out8, out9, out10 có tên tương ứng là ENAX, IN1X, IN2X,
IN3X, IN4X giao tiếp với IC công suất L298 để điều khiển động cơ bước. Xem hình
1-12.
Hình 1-17. Sơ đồ nguyên lý module giao tiếp I2C và các cảm biến tương tự
Kit có tích hợp các thiết bị giao tiếp với vi điều khiển theo chuẩn I2C bao gồm: module
oled GLCD (dự trữ), cảm biến ánh sáng BH1750, cảm biến áp suất BME280, cảm biến 3 trục
Thực hành vi điều khiển PIC 15
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
GY-521, IC ADC/DAC PCF8591T, IC thời gian thực DS1307 và IC nhớ Eeprom AT24C64 có
sơ đồ mạch như hình 1-17.
Các tín hiệu của I2C của các module nối với SDA và SCL của vi điều khiển thông qua
jumper JP701. Hai tín hiệu giao tiếp có 2 điện trở kéo lên nguồn.
IC thời gian thực DS1307
IC này có nguồn pin dự phòng để khi mất điện IC vẫn hoạt động. Ngõ ra SQW được nối
với led lên nguồn dùng để báo hiệu xung. Thạch anh sử dụng là 32768Hz.
IC ADC/DAC PCF8591T
IC này có 4 kênh ADC từ AN0 đến AN3 và có DAC 1 kênh. 4 kênh tương tự có tên là
AN0 đến AN3 nối với 2 cảm biến LM35A và LM35B và hai biến trở VRY và VRX của joystick.
Kênh DAC có ngõ ra là AOUT nối với led và có biến trở VR701 để chỉnh độ phân giải cho
khối ADC và DAC. Biến trở nằm bên dưới và đã chỉnh sẵn.
IC nhớ Eeprom AT24C64
IC này là bộ nhớ dạng nối tiếp có dung lượng 64Kbit hay 8 Kbyte.
Các thiết bị còn lại là module.
1.2.10 Module 9: giao tiếp các cảm biến nhiệt, cảm biến khoảng cách, led thu
Cảm biến chuyển động PIR
Kit có tích hợp cảm biến phát hiện người chuyển động PIR và có led báo hiệu dùng để làm
mạch báo trộm nối với chân tín hiệu có tên là PIR.
Hình 1-22. Sơ đồ giao tiếp cảm biến khoảng cách hồng ngoại GP2D12
Led thu IRF
Hình 1-25. Sơ đồ mạch chuyển đổi giao tiếp UART sang USB
1.2.13 Module 12: giao tiếp SIM800
Kit có tích hợp module SIM800 có sơ đồ giao tiếp như hình 1-26.
Hình 2-6. Thư mục chứa thư viện và file code mẫu
Kết quả giao diện như hình 2-7.
Hình 2-7. Giao diện phần mềm CCS với code mẫu
2.3.4 Biên dịch chương trình tạo ra file hex
Code mẫu đã được viết đúng, công việc tiếp theo là tiến hành biên dịch sang file hex.
Còn ý nghĩa của từng hàng lệnh nếu bạn chưa rõ thì sẽ giải thích ở phần sau.
Hãy chọn tab “Compile” và chọn biểu tượng “Compile” như hình 2-8.
Hình 2-8. Giao diện phần mềm CCS với code mẫu
Khi đó quá trình biên dịch sẽ xảy ra và xuất hiện giao diện như hình 2-9.
Hình 2-9. Giao diện đang biên dịch với code mẫu
Kết quả biên dịch hoàn tất và không có lỗi. Đồng thời cung cấp thêm thông tin tài nguyên
bộ nhớ RAM và ROM mà code mẫu này dùng.
Ngoài ra, sau khi biên dịch sẽ xuất hiện của sổ thông báo kết quả biên dịch như hình 2-10.
Hình 2-10. Màn hình thông báo kết quả biên dịch thành công
Nếu sai cú pháp thì biên dịch không thành công, phải hiệu chỉnh cho hết lỗi.
Kết quả của việc biên dịch thành công là tạo ra file Hex tương ứng như trong hình 2-11.
Hình 2-13. Giao diện mở file hex của code mẫu để nạp
Kết quả thông báo nạp thành công như hình 2-14.
Hình 2-18. Giao diện phần mềm không nhận ra mạch nạp
2.4.9 Cách xử lý sau khi nạp xong mà vi điều khiển không chạy
Với bài code mẫu này thì sau khi nạp xong thì vi điều khiển sẽ làm 4 led đơn chớp tắt.
Nếu 4 led không chớp tắt thì chỉ có một nguyên nhân duy nhất là phần mềm PICKIT2 đang
chọn chế độ reset vi điều khiển.
Tiến hành chọn mục “Programmer”, bỏ dấu tick đang chọn chế độ “Hold Device in Reset”
như hình 2-19.
38 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
Hình 3-1. Sơ đồ nguyên lý giao tiếp vi điều khiển với module 32 led đơn
Trong mạch sử dụng 2 IC thanh ghi MBI5026 để mở rộng port điều khiển 32 led đơn.
Phần vi điều khiển giao tiếp với IC thanh ghi dịch
Có 4 tín hiệu điều khiển là:
MBI_SDI dùng để dịch dữ liệu nối tiếp.
MBI_SCK dùng để cấp xung clock.
MBI_LE0 dùng để nạp dữ liệu song song từ thanh ghi dịch sang thanh ghi lưu trữ.
MBI_OE dùng để cho phép xuất dữ liệu.
Phần IC thanh ghi dịch giao tiếp với 32 led
Mỗi IC thanh ghi dịch MBI5026 có 16 bit kết nối với 16 led, 2 IC điều khiển được 32 led.
Số lượng byte dữ liệu điều khiển module 32 led là 4 byte hay 2 word.
Khả năng mở rộng
Trong kit thực hành dùng 2 IC để điều khiển 32 led, sau này các ứng dụng thực tế cần
nhiều led hơn thì bạn kết nối thêm IC thanh ghi nối tiếp vào một cách dễ dàng nhưng nếu có
nhiều IC thanh ghi dịch thì phải tính toán fan-out cho phù hợp.
3.1.2 Thư viện khởi tạo và thư viện của module 32 led đơn
Để giúp bạn viết code đơn giản nên một số hàm thư viện đã được viết sẵn lưu trong các
file thư viện. Phần này trình bày một số hàm chính có liên quan.
Hàm 301: Khởi tạo port.
void set_up_port()
{
set_tris_a(0xff); set_tris_b(0b11010000);
42 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
set_tris_c(0b11000001); output_high(mbi_oe);
set_tris_d(0b00001000); set_tris_e(0b01011111);
set_tris_f(0b00000111); set_tris_g(0x16);
output_low(mbi_le0); output_low(mbi_le1);
output_low(mbi_le2); output_low(mbi_le3);
output_low(mbi_le4); output_low(mbi_le5);
rbdc=0;
xoa_tat_ca_cac_module();
output_low(mbi_oe); output_high(rfid_ss);
output_high(nrf_ss);
setup_spi2(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H);
khoi_tao_cac_bien();
setup_adc(adc_clock_div_32);
setup_adc_ports(an0_to_an4|vss_vdd );
}
Khi bắt đầu lập trình thì trong chương trình chính phải gọi hàm khởi tạo này để khởi tạo
định hướng vào ra cho các port, truyền dữ liệu SPI. Tắt relay, triac, buzzer và các động cơ. Khởi
tạo các kênh ADC nối với các cảm biến tương tự.
Hàm 302: Xuất dữ liệu 1 word ra các IC thanh ghi dịch.
void xuat_1word(usi16 x)
{
spi_write2(x>>8); spi_write2(x);
}
Gửi dữ liệu byte cao của biến x theo chuẩn SPI2, tương tự cho byte thấp.
Hàm 303: Xuất dữ liệu 2 word ra module 32 led đơn.
void xuat_32led_don_2word(usi16 wld1, wld0)
{
xuat_1word(wld1); xuat_1word(wld0);
output_high(mbi_le0); output_low(mbi_le0);
}
Gọi hai hàm xuất dữ liệu 2 word ra 2 IC MBI 5026. Hai lệnh tiếp theo tạo xung chốt để
nạp dữ liệu từ tầng thanh ghi dịch sang tầng lưu trữ và xuất ra điều khiển led.
Hàm 304: Xuất dữ liệu 1 double word ra module 32 led đơn.
void xuat_32led_don_1dw(usi32 dwld)
{
unsigned int16 wd1,wd0;
wd1 = dwld>>16; wd0 = dwld;
xuat_32led_don_2word(wd1,wd0);
}
Tách dữ liệu double word thành 2 word và gọi hàm xuất dữ liệu 2 word.
Hàm 305: Xuất dữ liệu 4 byte ra module 32 led đơn.
Thực hành vi điều khiển PIC 43
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
void xuat_32led_don_4byte(usi8 bld3,bld2,bld1,bld0)
{
spi_write2(bld3); spi_write2(bld2);
spi_write2(bld1); spi_write2(bld0);
output_high(mbi_le0); output_low(mbi_le0);
}
Hàm 306: Xuất dữ liệu 1 byte ra module 32 led đơn. Ba byte còn lại là 0.
void xuat_32led_don_1byte(usi8 b0)
{
xuat_32led_don_4byte(0,0,0,b0);
}
3.1.3 Các chương trình điều khiển 32 led đơn dùng lệnh for
Phần này thực hành các bài điều khiển led dùng vòng lặp for, các chương trình đơn giản
dễ hiểu. Các bài thực hành từ chương này trở đi theo cách lập trình dùng chương trình con để dễ
dàng sử dụng lại.
Chú ý: Cách đặt tên bài và hàm có mối liên hệ với nhau để dễ quản lý.
Bài mẫu 301. Chương trình điều khiển 8 led chớp tắt với thời gian delay tùy ý.
Lưu tên file “bai_301_32led_chop_tat”.
a. Mục đích: Biết lập trình điều khiển led 8 đơn chớp tắt.
b. Lưu đồ, giải thuật: Rất đơn giản, gửi dữ liệu là 8 led tắt, delay, gửi dữ liệu làm 8 led
sáng, delay rồi lặp lại.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
void b301_8led_chop_tat(usi16 dl)
{
xuat_32led_don_4byte(0,0,0,0); delay_ms(dl);
xuat_32led_don_4byte(0,0,0,0xff); delay_ms(dl);
}
void main()
{
set_up_port();
while(true)
{
b301_8led_chop_tat(100);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Có 8 led chớp tắt là đúng.
f. Giải thích: Có 1 hàm con có chức năng chớp tắt 8 led và thời gian delay là “dl”.
Chương trình chính gọi hàm con và cho tham số delay là 100ms. Tham số này có thể
thay đổi: lớn thì chớp tắt chậm, nhỏ thì nhanh.
Bài tập 303. Hãy viết chương trình điều khiển 32 led chớp tắt, thời gian delay tùy ý.
Lưu tên file “bai_303_32led_chop_tat”.
Bài mẫu 304. Chương trình điều khiển 16 led phải sáng dần và tắt dần phải sang trái.
Lưu tên file “bai_304_16led_phai_std_pst”, thời gian delay tùy ý.
a. Mục đích: Biết viết chương trình điều khiển 16 led phải sáng tắt dần phải sang trái ở
dạng chương trình con.
b. Lưu đồ, giải thuật: Thực hiện vòng lặp dịch bit ‘1’ vào từ bên phải sẽ làm 16 led sáng
dần lên. Sau đó thực hiện vòng lặp dịch bit ‘0’ vào từ bên phải sẽ làm 16 led tắt dần.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
void b304_16led_phai_std_pst(usi16 dl)
{
usi8 i; usi16 LP;
LP = 0;
for(i=0;i<16;i++)
{
LP = (LP<<1)+1;
xuat_32led_don_2word(0,LP);
delay_ms(dl);
}
for(i=0;i<16;i++)
{
LP = (LP<<1);
xuat_32led_don_2word(0,LP);
delay_ms(dl);
}
}
void main()
{
set_up_port();
while(true)
{
b304_16led_phai_std_pst(40);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: 16 led bên phải sẽ sáng dần rồi tắt dần tử phải sang trái.
Bài mẫu 305. Chương trình điều khiển 16 led trái sáng dần và tắt dần trái sang phải
với thời gian delay tùy chọn.
Lưu tên file “bai_305_16led_trai_std_tsp”.
a. Mục đích: Biết cách thay đổi cho 16 led trái chiều ngược lại.
b. Lưu đồ, giải thuật: Giống bài 304 chỉ khác là chiều ngược lại.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
void b305_16led_trai_std_tsp(usi16 dl)
{
usi8 i; usi16 LT;
LT = 0;
for(i=0;i<16;i++)
{
LT = (LT>>1)+0x8000;
xuat_32led_don_2word(LT,0);
delay_ms(dl);
}
for(i=0;i<16;i++)
{
LT = (LT>>1);
xuat_32led_don_2word(LT,0);
delay_ms(dl);
}
}
void main()
{
set_up_port();
while(true)
{
b305_16led_trai_std_tsp(40);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: 16 led bên trái sáng dần rồi tắt dần từ trái sang phải.
f. Giải thích: Giống bài 304 nhưng chiều dịch từ trái sang phải. Để đẩy số 1 vào từ bên
trái của dữ liệu 16 bit thì phải cộng với số nhị phân: 1000_0000_0000_0000b =
0×8000.
Bài tập 306. Hãy viết chương trình điều khiển 32 led sáng tắt dần từ ngoài.
Lưu tên file “bai_306_32led_std_tnv”, thời gian delay tùy ý.
Bài mẫu 308. Chương trình điều khiển 32 led sáng dần và tắt dần phải sang trái.
Lưu tên file “bai_308_32led_std_pst”, thời gian delay tùy ý.
a. Mục đích: Biết cách viết chương trình điều khiển 32 led sáng tắt dần phải sang trái.
b. Lưu đồ, giải thuật: Giống bài 304, chỉ khác là mở rộng thành 32 led.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
void b308_32led_std_pst(usi16 dl)
{
usi8 i; usi32 x;
x = 0;
for(i=0;i<32;i++)
{
x = (x << 1)+1;
xuat_32led_don_1dw(x);
delay_ms(dl);
}
for(i=0;i<32;i++)
{
x = (x << 1);
xuat_32led_don_1dw(x);
delay_ms(dl);
}
}
void main()
{
set_up_port();
while(true)
{
b308_32led_std_pst(40);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: 32 led sẽ sáng dần rồi tắt dần từ phải sang trái.
Bài tập 309. Hãy viết chương trình điều khiển 32 led sáng tắt dần trái sang phải.
Lưu tên file “bai_309_32led_std_tsp”, thời gian delay tùy ý.
Bài mẫu 310. Hãy viết chương trình điều khiển 32 LED tổng hợp 8 yêu cầu gồm:
1. 32 led chớp tắt 5 lần. Hàm con đã viết ở bài 303.
void main()
{
set_up_port();
while(true)
{
h310_32led_chop_tat_nlan(5,100);
h310_32led_std_pst_nlan(2,20);
h310_32led_chop_tat_nlan(5,100);
h310_32led_std_tsp_nlan(2,20);
h310_32led_chop_tat_nlan(5,100);
h310_32led_std_tnv_nlan(2,20);
h310_32led_chop_tat_nlan(5,100);
h310_32led_std_ttr_nlan(2,20);
}
}
d. Tiến hành biên dịch và nạp.
Bài tập 311. Hãy vẽ lưu đồ và viết chương trình điều khiển 32 led sáng dồn phải sang
trái. Lưu tên file “bai_311_32led_sd_pst”, thời gian delay tùy ý.
Bài tập 312. Hãy vẽ lưu đồ và viết chương trình điều khiển 32 led sáng dồn trái sang
phải. Lưu tên file “bai_312_32led_sd_tsp”, thời gian delay tùy ý.
Bài tập 313. Hãy vẽ lưu đồ và viết chương trình điều khiển 32 led sáng dồn từ ngoài
vào. Lưu tên file “bai_313_32led_sd_tnv”, thời gian delay tùy ý.
Bài tập 314. Hãy vẽ lưu đồ và viết chương trình điều khiển 32 led sáng dồn từ trong
ra. Lưu tên file “bai_314_32led_sd_ttr”, thời gian delay tùy ý.
Bài tập 315. Hãy vẽ lưu đồ và viết chương trình điều khiển 32 led sáng hết rồi lần lượt
có 1 điểm sáng bên phải dịch phải mất dần cho đến khi tất cả các led dịch hết.
Lưu tên file “bai_315_32led_1dsp_mp”, thời gian delay tùy ý.
Bài tập 316. Hãy vẽ lưu đồ và viết chương trình điều khiển 32 led sáng hết rồi lần lượt
có 1 điểm sáng bên trái dịch trái mất dần cho đến khi tất cả các led dịch hết.
Lưu tên file “bai_316_32led_1dst_mp”, thời gian delay tùy ý.
Hình 3-2. Sơ đồ giao tiếp vi điều khiển với 4 nút nhấn đơn
3.2.3 Định nghĩa tên các nút nhấn trong thư viện
Kit thực hành có 4 nút nhấn đơn là BT0 đến BT3 kết nối trực tiếp với 4 bit của các port.
#define bt0 pin_b6
#define bt1 pin_f1
#define bt2 pin_b4
#define bt3 pin_b7
#define on bt0
#define off bt1
#define inv bt2
#define up bt0
#define mod bt1
#define dw bt2
#define clr bt3
Tắt 8 led
Nhấn ON
S
Đ
Sáng 8 led
Nhấn OFF
S
Đ
END
Hình 3-3. Lưu đồ điều khiển 8 led sáng tắt bằng 2 nút ON và OFF
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
void main()
{
set_up_port();
while(true)
{
while(input(ON));
xuat_32led_don_4byte(0,0,0,0xff);
while(input(Off));
xuat_32led_don_4byte(0,0,0,0);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Nhấn nút ON sẽ làm 8 led sáng, nhấn nút OFF sẽ làm 8 led tắt.
f. Tham khảo thêm cách viết dùng lệnh if:
#include <tv_kit_vdk_18f6722_all.c>
void main()
{
else if(!input(off))
xuat_32led_don_4byte(0,0,0,0);
}
}
g. Sự khác biệt của 2 chương trình dùng lệnh while và if: Cả 2 bài này đều có kết quả
điều khiển như nhau nhưng nếu hệ thống điều khiển thêm nhiều yêu cầu điều khiển
khác sẽ thấy được sự khác biệt: Nếu dùng lệnh while thì sẽ không đáp ứng được các
yêu cầu khác. Còn nếu dùng lệnh if thì đáp ứng được các yêu cầu khác. Tùy theo yêu
cầu mà chúng ta có thể dùng cho phù hợp.
Bài mẫu 322. Chương trình điều khiển 32 LED bằng 3 nút ON, OFF, INV. Khi có điện
thì 8 led tắt, khi nhấn ON thì 4 led sáng, khi nhấn INV thì 4 led sáng thành tắt, 4 led tắt
thành sáng. Khi nhấn OFF thì tất cả 8 led tắt.
Lưu tên file “bai_322_on_off_inv_8led”.
a. Mục đích: Thấy hiện tượng dội và tốc độ xử lý nhanh của vi điều khiển gây ra cho
nút nhấn INV làm mạch hoạt động không chính xác.
b. Lưu đồ, giải thuật: Xem hình.
BEGIN
Tắt 8 led
Nhấn ON
S
Đ
Sáng 4 led, tắt 4 led
Hình 3-4. Lưu đồ điều khiển 8 led sáng tắt bằng 2 nút ON, OFF và INV
54 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
unsigned int8 y;
void main()
{
set_up_port();
y=0;
xuat_32led_don_4byte(0,0,0,0);
while(true)
{
while(input(on));
y=0x0f;
xuat_32led_don_4byte(0,0,0,y);
do
{
if (!input(inv))
{
y=~y;
xuat_32led_don_4byte(0,0,0,y);
}
}while(input(off));
xuat_32led_don_4byte(0,0,0,0);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Nhấn ON làm 4 led sáng, nhấn INV thì đảo 4 sáng thành tắt, 4 tắt
thành sáng. Nhấn OFF thì tắt led.
Trong chương trình này khi chạy thực tế thì có vấn đề cho phím INV: ta nhấn phím INV
nhanh thì trạng thái đảo của led không thể đảo chiều một cách chính xác, ổn định mà lúc được
lúc không.
Có 2 nguyên nhân: Do bị dội phím và do tốc độ của vi điều khiển quá nhanh 200ns cho 1
lệnh. Khi ta nhấn đảo chiều thì thời gian nhấn phím dài hàng mili giây đến hàng giây, nên vi
điều khiển thực hiện đảo led liên tục cho đến khi ta nhả phím thì không thể xác định trạng thái
chính xác được.
Để điều khiển chính xác thì phải chống dội phím nhấn, rồi xử lý chức năng và kiểm tra
buông phím cho trường hợp nhấn nhả và delay cho trường hợp nhấn giữ.
Dội phím xảy ra khoảng 20ms và sau đó ổn định.
Trong bài điều khiển chỉ có phím INV gây ra ảnh hưởng nên lưu đồ và chương trình xử lý
phần chống dội và chờ buông phím INV theo sau.
Bài mẫu 323. Chương trình điều khiển 8 LED bằng 3 nút ON, OFF, INV. Khi có điện
thì 8 led tắt, khi nhấn ON thì 4 led sáng, khi nhấn OFF thì led tắt, khi nhấn INV thì 4 led
sáng thành tắt, 4 led tắt thành sáng, có chống dội phím và chờ nhả phím.
Lưu tên file “bai_323_on_off_inv_cd_8led”.
END
Hình 3-5. Lưu đồ điều khiển 8 led bằng ON, OFF và INV – có chống dội
Tiếp theo để giảm ảnh hưởng tốc độ xử lý của vi điều khiển nên thêm lệnh chờ nhả phím
cho trường hợp nhấn – nhả. Thêm delay cho trường hợp nhấn – giữ cho những ứng dụng có thực
hiện có tính liên tục.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
unsigned int8 y;
void phim_inv()
{
if (!input(inv))
{
delay_ms(20);
{
if (!input(inv))
{
y=~y;
xuat_32led_don_4byte(0,0,0,y);
while(!input(inv));
}
}
void main()
{
set_up_port();
y=0x00;
while(true)
{
while(input(on));
y=0x0f;
xuat_32led_don_4byte(0,0,0,y);
do
{
phim_inv();
}
while(input(off));
xuat_32led_don_4byte(0,0,0,0);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Giống bài 322 nhưng khi nhấn INV thì mạch hoạt động đảo chiều
sáng tắt một cách ổn định và chính xác.
Bài tập 324. Dùng vi điều khiển giao tiếp với 16 led đơn và 3 nút nhấn được đặt tên là
UP, DW, CLR. Khi cấp điện thì 16 led tắt, khi nhấn UP thì led sáng dần lên từ phải sang
trái – mỗi lần nhấn thì 1 led sáng, khi nhấn DW thì led tắt dần theo chiều ngược lại, khi
nhấn CLR thì xóa hết.
Lưu tên file “bai_324_up_dw_clr_16led”.
Bài tập 325. Giống bài 324 nhưng nút nhấn CLR có thêm chức năng đảo chiều sáng
và tắt của led: ví dụ khi nhấn UP thì sáng dần từng led từ phải sang trái, thì sau khi nhấn
CLR thì khi nhấn UP led sẽ sáng từng led theo chiều từ trái sang phải, tương tự cho nút
nhấn DW.
Lưu tên file “bai_325_up_dw_clr_16led_dao_chieu”.
void b326_32led_std_pst_tsp_tat_3bt()
{
if(phim_bt0_c1(c_ktnp,0)==co_nhan)
{
if(tt_ct<2) tt_ct++;
}
if(phim_bt1_c1(c_ktnp,0)==co_nhan)
{
if(tt_ct>0) tt_ct--;
}
if(tt_ct==0) xuat_32led_don_1dw(0);
if(tt_ct==1) b308_32led_std_pst(200);
if(tt_ct==2) b309_32led_std_tsp(200);
}
void main()
{
set_up_port();
tt_ct=0;
while(true)
{
b326_32led_std_pst_tsp_tat_3bt();
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Nhấn các nút để thực hiện các yêu cầu.
f. Nhận xét: Khi 32 led đang tắt thì ta nhấn nút bt0 hoặc bt1 để thực hiện chương trình
sáng tắt dần tương ứng sẽ chạy ngay sau nhấn phím.
Khi đã chạy chương trình điều khiển 32 led sáng tắt dần thì việc nhấn phím để chọn
yêu cầu khác chỉ có tác dụng khi chương trình đang chạy kết thúc chu kỳ. Còn khi
đang thực hiện thì ta nhấn không có tác dụng.
g. Kết luận: Bài này tồn tại vấn đề là đáp ứng phím nhấn quá chậm.
h. Nguyên nhân: Do chu kỳ thực hiện dùng vòng lặp for cho sáng dần rồi tắt dần là
64×200ms = 12,800ms = 12,8s nên gây ra đáp ứng chậm khi nhấn phím. Phần tiếp
theo trình bày cách khắc phục hai vấn đề trên.
Bài mẫu 327. Giống bài 331 nhưng giải quyết các vấn đề để đáp ứng nhanh.
Lưu tên file “bai_327_32led_tat_std_pst_tsp_3btn_nhanh”.
a. Mục đích: Biết lập trình vòng lặp dùng lệnh if thay cho vòng lặp for để đáp ứng nhanh
các yêu cầu điều khiển khác.
b. Lưu đồ, giải thuật: Xem hình.
Sang_tat_dan_pst_32led()
Dem_led<32 Dem_led<64
S S
Đ Đ
Xuất biến Y ra led đơn, delay, Xuất biến Y ra led đơn, delay,
dịch mức 1 vào Y từ bên phải, dịch mức 0 vào Y từ bên phải,
Dem_led = 0
Dem_led = Dem_led + 1
Y=0
end
Hình 3-6. Điều khiển 32 led sáng tắt dần từ phải sang trái dùng lệnh if
Các yêu cầu điều khiển kiểu khác cũng có thể thực hiện giống như lưu đồ trên.
c. Chương trình con “bai_327_tv”:
usi8 ttl,tt_ct;
usi32 x;
void h327_reset_tang_tcttd_if()
{
ttl=0; x=0;
}
void h327_32led_std_tsp_if()
{
if(ttl<32)
{
void h327_32led_std_pst_if()
{
if(ttl<32)
{
x=(x<<1)+1;
xuat_32led_don_1dw(x);
ttl++;
}
else if(ttl<64)
{
x=(x<<1);
xuat_32led_don_1dw(x);
ttl++;
}
else h327_reset_tang_tcttd_if();
}
d. Chương trình chính:
#include <tv_kit_vdk_18f6722_all.c>
#include <bai_327_tv.c>
void b327_32led_std_pst_tsp_tat_3bt_if()
{
if(phim_bt0_c1(c_ktnp,0)==co_nhan)
{
if(tt_ct<2)
{
tt_ct++;
h327_reset_tang_tcttd_if();
}
}
if(phim_bt1_c1(c_ktnp,0)==co_nhan)
{
void main()
{
set_up_port();
tt_ct=0;
h327_reset_tang_tcttd_if();
while(true)
{
b327_32led_std_pst_tsp_tat_3bt_if();
if(tt_ct==0) xuat_32led_don_1dw(0);
if(tt_ct==1) h327_32led_std_pst_if();
if(tt_ct==2) h327_32led_std_tsp_if();
delay_ms(200);
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: Nhấn các nút để thực hiện các yêu cầu và mạch đáp ứng ngay nhưng
sau khi nhấn thì phải nhả phím thì mới thực hiện yêu cầu tiếp theo.
3.3.4 Tối ưu thời gian delay 20ms của hàm chống dội nút nhấn
Ở các hàm kiểm tra nếu có phím nhấn thì phải delay 20ms để qua khoảng thời gian dội
phím sẽ làm chậm quá trình xử lý các yêu cầu khác một cách đáng kể.
Để giải quyết vấn đề này là ta chia nhỏ quá trình kiểm tra phím thành 40 lần, mỗi lần chỉ
delay 500µs rồi thoát về thực hiện các yêu cầu khác của chương trình chính và sau đó quay lại
kiểm tra tiếp. Nếu phím vẫn còn nhấn trong 40 lần kiểm tra tương đương 20ms thì xem như có
nhấn phím. Nếu các yêu cầu khác mất nhiều thời gian thì nên giảm số lần nhỏ hơn 40.
Cách này được xem như là cách thứ 2.
Các chương trình giống nhau cho các phím nhưng chỉ trình bày phím bt0.
int1 phim_bt0_c2(usi16 dl)
{
if (!input(bt0))
{
dl_btn++; delay_us(500);
if(dl_btn>=dl)
{
dl_btn=0;
Bài mẫu 328. Giống bài 327, chỉ khác là dùng hàm kiểm tra phím nhấn theo cách 2.
Lưu tên file “bai_328_32led_3y_cau_up_dw_if_c2”.
a. Mục đích: Giống bài 327, chỉ khác là dùng hàm kiểm tra phím nhấn theo cách 2.
b. Lưu đồ, giải thuật: Giống bài 327
c. Chương trình chính:
#include <tv_kit_vdk_18f6722_all.c>
#include <bai_327_tv.c>
void b328_32led_std_pst_tsp_tat_3bt_if()
{
if(phim_bt0_c2(2)==co_nhan)
{
if(tt_ct<2)
{
tt_ct++;
h327_reset_tang_tcttd_if();
}
}
if(phim_bt1_c2(2)==co_nhan)
{
if(tt_ct>0)
{
tt_ct--;
h327_reset_tang_tcttd_if();
}
}
}
void main()
{
set_up_port();
tt_ct=0;
Bài tập 330. Giống bài 329 nhưng 4 yêu cầu (2), (3), (4) (5) được viết chung lại thành
1 hàm có thêm 1 thông số chọn chiều (dir) có giá trị 0, 1, 2, 3 để chọn 4 chiều tương ứng
4 yêu cầu. Số thứ tự các yêu cầu vẫn không đổi.
Lưu tên file “bai_330_32led_6yeu_cau_3btn_ct”.
Bài tập 331. Hãy viết thêm vào bài 330 yêu cầu thứ (6) là điều khiển 32 led sáng dồn
phải sang trái và yêu cầu thứ (7) là sáng dồn trái sang phải dùng lệnh if với thời gian trễ
là 10ms.
Lưu tên file “bai_331_32led_8yeu_cau_3btn_ct”.
Bài tập 332. Hãy viết thêm vào bài 331 yêu cầu thứ (8) là điều khiển 32 led sáng dồn
từ ngoài vào, yêu cầu thứ (9) là sáng dồn từ trong ra, yêu cầu thứ (10) là điều khiển 16
led trái và 16 led phải sáng dồn phải sang trái song song, yêu cầu thứ (11) giống thứ (10)
nhưng từ trái sang phải dùng lệnh if với thời gian trễ là 10ms.
Lưu tên file “bai_332_32led_8yeu_cau_3btn_ct”.
Bài tập 333. Hãy viết thêm vào bài 332 yêu cầu thứ (12) là điều khiển 32 led sáng hết
rồi điểm sáng thứ nhất bên phải dịch phải mất dần, tương tự cho điểm sáng thứ 2, thứ
3, … cho đến điểm sáng cuối cùng. Yêu cầu thứ (13) giống (12) nhưng dịch trái mất dần,
dùng lệnh if với thời gian trễ là 10ms.
Lưu tên file “bai_333_32led_14yeu_cau_3btn_ct”.
Bài tập 334. Hãy viết thêm vào bài 333 yêu cầu thứ (14) là điều khiển 32 led sáng hết
rồi có 2 điểm sáng dịch từ vào giữ mất dần, yêu cầu thứ (15) có 2 điểm sáng dịch ra mất
dần, yêu cầu thứ (16) là điều khiển 2 nhóm 16 led sáng hết có 2 điểm sáng dịch phải mất
dần, yêu cầu thứ (17) giống (16) nhưng dịch trái mất dần, dùng lệnh if với thời gian trễ là
10ms.
Lưu tên file “bai_334_32led_18yeu_cau_3btn_ct”.
Bài tập 335. Hãy viết thêm vào bài 334 yêu cầu thứ (18) đến (33) là điều khiển 32 led
có k điểm sáng dịch trái, k có giá trị từ 1 đến 8 tương ứng 1 đến 16 led sáng.
Ví dụ cho k bằng 4 thì có 4 điểm sáng dịch trái: ban đầu 32 led tắt. Dịch trái 1 bit lần
1: 1 điểm sáng xuất hiện bên phải. Dịch trái 1 bit lần 2: thêm 1 điểm sáng xuất hiện bên
phải là 2 led, tương tự lần 3 thì 3 led sáng, lần 4 thì 4 led sáng. Đến đây đã đủ 4 led sáng
và 32 lần dịch tiếp theo sẽ dịch 4 điểm sáng này sang trái cho đến khi mất dần hết rồi lặp
lại. Tương tự cho các giá trị khác của k. Dùng lệnh if với thời gian trễ là 20ms.
Lưu tên file “bai_335_32led_34yeu_cau_3btn_ct”.
Bài tập 336. Hãy viết thêm vào bài 335 yêu cầu thứ (34) đến (49) là điều khiển 32 led
có k điểm sáng dịch trái, k có giá trị từ 1 đến 8 tương ứng 1 đến 16 led sáng.
Ví dụ cho k bằng 4 thì có 4 điểm sáng dịch trái: ban đầu 32 led tắt. Dịch trái 1 bit lần
1: 1 điểm sáng xuất hiện bên phải. Dịch trái 1 bit lần 2: thêm 1 điểm sáng xuất hiện bên
phải là 2 led, tương tự lần 3 thì 3 led sáng, lần 4 thì 4 led sáng. Đến đây đã đủ 4 led sáng
và 32 lần dịch tiếp theo sẽ dịch 4 điểm sáng này sang trái cho đến khi mất dần hết rồi lặp
lại. Tương tự cho các giá trị khác của k. Dùng lệnh if với thời gian trễ là 20ms.
Lưu tên file “bai_336_32led_50yeu_cau_3btn_ct”.
Bài tập 337. Hãy viết thêm vào bài 336 yêu cầu thứ (50) đến (81) là điều khiển 32 led
chia thành 2 nhóm 16 led trái và 16 led phải, có k điểm sáng dịch vào, dịch ra, dịch trái,
dịch phải – 4 chiều, k có giá trị từ 1 đến 8 tương ứng 1 đến 8 led sáng.
Lưu tên file “bai_337_32led_82yeu_cau_3btn_ct”.
Bài tập 339. Hãy viết chương trình thực hiện 82 yêu cầu giống bài 344 nhưng chạy tự
động từ thứ (0) đến (81).
Lưu tên file “bai_339_32led_chay_td_82yc”.
a. Mục đích: Biết viết chương trình chạy 82 yêu cầu điều khiển 32 led chạy tự động.
b. Lưu đồ, giải thuật: Giống bài 338, chỉ thêm vào các yêu cầu khác:
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
#include <chuong3_32led_if_no_delay.c>
void main()
{
set_up_port();
while(true)
#include <tv_04_18f6722_8led_7doan.c>
#include <tv_05_18f6722_lcd.c>
#include <tv_06_18f6722_adc.c>
#include <tv_ds18b20.c>
#include <tv_dht11.c>
#include <tv_rotary_encoder.c>
//!#include <tv_oled_ssd1306.c>
#include <tv_HX711.c>
Các bạn có thể xem chi tiết từng thư viện.
Còn nhiều thông tin trong các thư viện, do quá nhiều nên không trình bày hết, bạn có thể
xem trong từng file.
Hình 4-1. Sơ đồ nguyên lý giao tiếp vi điều khiển với module 4 led 7 đoạn
Trong mạch sử dụng 4 IC thanh ghi MBI5026 để mở rộng port điều khiển 8 led 7 đoạn.
Phần vi điều khiển PIC giao tiếp với IC thanh ghi dịch
Có 4 tín hiệu điều khiển là:
MBI_SDI dùng để dịch dữ liệu vào nối tiếp.
MBI_SCK dùng để cấp xung clock.
MBI_LE1 dùng điều khiển nạp dữ liệu song song.
MBI_OE dùng để cho phép xuất dữ liệu.
Phần IC thanh ghi dịch giao tiếp với 4 led 7 đoạn
Mỗi IC MBI526 có 16 bit kết nối với 2 led 7 đoạn, 4 IC điều khiển được 8 led 7 đoạn.
Số lượng byte dữ liệu điều khiển module 8 led 7 đoạn là 4 word.
Khả năng mở rộng
Trong kit thực hành dùng 4 IC để điều khiển 8 led, sau này các ứng dụng thực tế cần nhiều
led hơn thì bạn cứ kết nối thêm IC thanh ghi nối tiếp vào một cách dễ dàng.
70 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
4.1.2 Hàm xuất dữ liệu của module 8 led 7 đoạn
Phần này trình bày các hàm xuất dữ liệu và các hàm giải mã của module 8 led 7 đoạn. Các
hàm lưu trong file “tv_04_18f6722_8led_7doan”.
a. Định nghĩa: Mảng chứa dữ liệu hiển thị của module 8 led 7 đoạn.
usi8 led_7d[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
b. Hàm 401: Xuất dữ liệu 8 byte dữ liệu của mảng led_7d ra 8 led.
void xuat_8led_7doan()
{
si8 i;
for(i=7;i>-1;i--) spi_write2(~led_7d[i]);
output_high(mbi_le1); output_low(mbi_le1);
}
Hàm này gửi 8 phần tử của mảng ra 4 IC theo chuẩn nối tiếp SPI.
c. Hàm 402: Giải mã 2 số hex tùy chọn vị trí hiển thị và số vô nghĩa.
void giaima_bcd_2so_vitri_vn(usi8 x,y, int1 xvn)
{
led_7d[y] = ma7doan[x%16];
led_7d[y+1] = ma7doan[x/16];
if(xvn==true)
{
if (led_7d[y+1]==maso0) led_7d[y+1]=0xff;
}
}
Giải mã biến x thành 2 số BCD, vị trí lưu là y và tùy chọn xóa vô nghĩa hoặc không. Hàm
này dùng để chia tách hiển thị 2 số BCD hoặc số thập lục phân và tùy chọn xóa vô nghĩa.
d. Hàm 403: Giải mã 2 số BCD tùy chọn vị trí hiển thị và số vô nghĩa.
void giaima_bin_2so_vitri_vn(usi8 x,y, int1 xvn)
{
led_7d[y] = ma7doan[x%10];
led_7d[y+1] = ma7doan[x/10%10];
if(xvn==true)
{
if (led_7d[y+1]==maso0) led_7d[y+1]=0xff;
}
}
e. Hàm 404: Giải mã 3 số BCD tùy chọn vị trí hiển thị và số vô nghĩa.
void giaima_bin_3so_vitri_vn(usi16 x, usi8 y, int1 xvn)
{
led_7d[y] = ma7doan[x%10];
led_7d[y+1] = ma7doan[x/10%10];
led_7d[y+2] = ma7doan[x/100%10];
if(xvn==true)
Thực hành vi điều khiển PIC 71
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
{
if (led_7d[y+2]==maso0)
{
led_7d[y+2]=0xff;
if (led_7d[y+1]==maso0) led_7d[y+1]=0xff;
}
}
}
f. Hàm 405: Giải mã 5 số BCD tùy chọn vị trí hiển thị và số vô nghĩa.
void giaima_bin_4so_vitri_vn(usi16 x, usi8 y, int1 xvn)
{
led_7d[y] = ma7doan[x%10];
led_7d[y+1] = ma7doan[x/10%10];
led_7d[y+2] = ma7doan[x/100%10];
led_7d[y+3] = ma7doan[x/1000%10];
if(xvn==true)
{
if (led_7d[y+3]==maso0)
{
led_7d[y+3]=0xff;
if (led_7d[y+2]==maso0)
{
led_7d[y+2]=0xff;
if (led_7d[y+1]==maso0) led_7d[y+1]=0xff;
}
}
}
}
Giải mã 7 đoạn 4 số chục và đơn vị của biến x, vị trí lưu là y và tùy chọn xóa vô nghĩa.
g. Hàm 406: Giải mã 5 số BCD tùy chọn vị trí hiển thị và số vô nghĩa.
void giaima_bin_5so_vitri_vn(usi16 x, usi8 y, int1 xvn)
{
led_7d[y] = ma7doan[x%10];
led_7d[y+1] = ma7doan[x/10%10];
led_7d[y+2] = ma7doan[x/100%10];
led_7d[y+3] = ma7doan[x/1000%10];
led_7d[y+4] = ma7doan[x/1000%10];
if(xvn==true)
{
if (led_7d[y+4]==maso0)
{
led_7d[y+4]=0xff;
if (led_7d[y+3]==maso0)
{
void main()
{
set_up_port();
while(true)
{
b401_hien_thi_8so_8l7d(); while(true);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: 8 led sáng từ số 0 đến 7.
Bài tập 403. Hãy viết lưu đồ và trình điều khiển 8 LED 7 đoạn hiển thị 8 số từ 0 đến 7
một giây, sau đó hiển thị 8 số từ 8 đến F một giây, rồi lặp lại.
Lưu tên file là “bai_403_16so_luan_phien”.
Bài tập 404. Hãy viết lưu đồ và trình điều khiển 8 LED 7 đoạn theo yêu cầu: chuỗi
“CAFE-COCA-COLA” dịch từ phải sang trái từng ký tự, ban đầu tắt hết, delay tùy ý.
Lưu tên file là “bai_404_chuoi_std_pst”.
void b406_up_dw_g_han()
{
if(phim_up_c2(150)==co_nhan)
{
if(g_han<99)
{
g_han++;
b406_hienthi_4led7doan();
74 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
}
}
if(phim_dw_c2(150)==co_nhan)
{
if(g_han>0)
{
g_han--;
b406_hienthi_4led7doan();
}
}
}
void main()
{
set_up_port();
g_han = 50;
b406_hienthi_4led7doan();
while(true)
{
b406_up_dw_g_han();
}
}
a. Tiến hành biên dịch và nạp.
b. Quan sát kết quả: Ban đầu hiển thị giá trị 50: khi nhấn UP và giữ thì giá trị tăng, nhấn
DW và giữ thì giá trị giảm. Do chỉ chỉnh giới hạn và không thực hiện yêu cầu điều
khiển nào khác nên khi gọi hàm chống dội phím theo cách 2 thì tham số truyền 150 là
phù hợp.
Bài tập 407. Chương trình cài giới hạn từ 0 đến 99 dùng 2 nút UPC và UPD. UPC:
chỉnh hàng chục và UPD: chỉnh hàng đơn vị và cuộn tròn, dùng chế độ nhấn và giữ, có
xóa vô nghĩa. Giá trị mặc nhiên ban đầu là 50.
Lưu tên file là “bai_407_cai_gh_0_99_2bt_up”.
4.4 ĐẾM XUNG DÙNG COUNTER HIỂN THỊ TRÊN LED 7 ĐOẠN
Vi điều khiển PIC 18F6722 có 5 timer T0, T1, T2, T3 và T4.
T0, T1, T3 là timer/counter 16 bit, cả 3 đều có bộ chia trước. T2, T4 là timer 8 bit có bộ
chia trước và chia sau phục vụ cho các ứng dụng đặc biệt.
4.4.1 Tóm tắt timer/counter T0
Phần này thực hiện đếm xung ngoại dùng timer T0 vì nguồn xung từ cảm biến trên bộ thí
nghiệm đã cấp cho Timer T0 nên ta chỉ khảo sát timer T0.
Vi điều khiển PIC 18F6722 có timer T0 có thể hoạt động ở 2 chế độ 8 bit hoặc 16 bit. Chế
độ 8 bit thì giống họ vi điều khiển PIC16.
Hình 4-5. Sơ đồ nguyên lý module thu phát hồng ngoại tạo xung
Led phát sẽ nối với điện trở lên nguồn 5V để led luôn hoạt động phát ra ánh sáng hồng
ngoại. Transistor có ngõ ra nối với điện trở và nối lên nguồn, đóng vai trò là điện trở tải để lấy
tín hiệu.
Tín hiệu ngõ ra được nối với 2 cổng not của IC 74HC14 có chức năng đệm và schmitt
trigger sửa dạng xung cho vuông và sau đó có thể đưa trực tiếp đến ngõ vào counter.
Khi không có sản phẩm nào che giữa led phát và led thu thì transistor được phân cực và
ngõ ra transistor bằng 0, qua 2 cổng not thì cũng bằng 0.
Khi bạn che ánh sáng giữa led phát và transistor thì transistor tắt, ngõ ra lên 1, qua 2 cổng
Not cũng bằng 1.
Mỗi lần 1 sản phẩm đi qua thì tạo ra 1 xung, xung sẽ đưa đến counter để đếm và hiển thị
trên led.
4.4.4 Các ứng dụng đếm xung ngoại dùng counter T0
Phần này thực hành các bài đếm xung ngoại dùng counter T0 và hiển thị kết quả đếm trên
module 8 led 7 đoạn.
Bài mẫu 411. Chương trình đếm sản phẩm hiển thị trên 4 led 7 đoạn dùng counter T0,
giới hạn đếm từ 0 đến 50. Khi bằng 50 thì quay về 0. Chỉ cập nhật khi kết đếm khác với
kết quả đang hiển thị. Buzzer kêu bip khi kết thúc 1 chu kỳ đếm. Giới hạn 50 hiển thị ở 2
led 7, 6. Giá trị đếm T0 hiển thị ở 2 led 1, 0. Có xóa vô nghĩa.
Lưu tên file là “bai_411_t0_dem_xung ”.
a.Mục đích: Biết lập trình đếm xung ngoại dùng counter T0, hiển thị led 7 đoạn.
b.Lưu đồ, giải thuật: Khởi tạo port, timer T0 ở chế độ counter, đọc giá trị T0 đem giải
mã, hiển thị và xử lý giới hạn.
c. Chương trình con “bai_411_t0_tv”:
unsigned int8 t0, t0_tam,g_han;
void b411_hienthi_4led7doan()
{
giaima_bin_2so_vitri_vn(t0,0,kx_vn);
Thực hành vi điều khiển PIC 77
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
giaima_bin_2so_vitri_vn(g_han,6,kx_vn);
xuat_8led_7doan();
}
void b411_dem_sp_t0()
{
t0 = get_timer0();
if(t0_tam!=t0)
{
t0_tam = t0;
b411_hienthi_4led7doan();
if (t0>=g_han)
{
set_timer0(0);
buzzer_on_off(300);
}
}
}
d. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
#include <bai_411_t0_tv.c>
void main()
{
set_up_port();
setup_timer_0(t0_ext_l_to_h|t0_div_1);
set_timer0(0); t0_tam = 1; g_han=50;
while(true)
{
b411_dem_sp_t0();
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: Dùng giấy che giữa led phát và led thu thì mạch cảm biến hồng
ngoại sẽ tạo ra xung, kết quả giá trị trên led sẽ tăng lên 1.
g. Yêu cầu mở rộng: (1). Muốn đếm từ 0 đến 300 thì thay đổi như thế nào? (2). Muốn
thay đổi hệ số chia là 2 hoặc 4 thì làm như thế nào? (3). Muốn thay đổi mức tích cực
của xung vào thì làm như thế nào?
Bài tập 412. Giống bài 411 nhưng có thêm 2 nút nhấn điều khiển Run, Stop. Sau khi
nạp hoặc nhấn Stop thì counter ngừng đếm, có xung cũng không đếm, 16 led đơn phải
tắt. Khi nhấn Run thì cho phép đếm khi có xung, 16 led đơn phải sáng. Gợi ý: sử dụng
chế độ cho phép hoặc không cho phép của timer T0.
Lưu tên file là “bai_412_dem_xung_t0_stop_run_32led”.
Bài tập 414. Kết hợp bài 412 với bài 406 để thay đổi giới hạn bằng 2 nút nhấn. Giới
hạn mặc nhiên ban đầu là 50.
Lưu tên file là “bai_414_dem_xung_t0_stop_run_32led_gh”.
Bài mẫu 415. Chương trình đếm giây chính xác dùng timer T3 tạo ngắt.
Hiển thị trên 8 led 7 đoạn: giây ở 2 led thứ 1, 0.
Lưu tên file “bai_415_dem_giay_t3”.
a. Mục đích: Biết sử dụng timer T3 định thời và ngắt để đếm giây chính xác.
b. Lưu đồi, giải thuật: Dùng timer T3 đếm thời gian 0,1 giây thì báo ngắt để tăng biến
đếm ngắt. Khi biến đếm ngắt bằng 10 thì tương đương 1 giây.
#int_timer3
void timer3_ct_con_ngat()
{
bdn++;
set_timer3(3036);
}
void h415_dem_giay_timer3()
{
if (bdn>=10)
{
bdn = bdn - 10;
if (giay<59) giay++;
else giay=0;
giaima_bin_2so_vitri_vn(giay,0,kx_vn);
xuat_8led_7doan();
}
}
void main()
{
set_up_port();
enable_interrupts(global);
enable_interrupts(int_timer3);
setup_timer_3(t3_internal|t3_div_by_8);
set_timer3(3036);
bdn=0; giay=0;
while(true)
{
h415_dem_giay_timer3();
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Giây sẽ đếm chính xác hiển thị trên 2 led 7 đoạn.
f. Tính toán về tần số:
Tần số cấp cho timer: Thạch anh cấp cho vi điều khiển có tần số 20MHz qua bộ chia 4
còn 5MHz để cấp cho các timer. Xung này qua bộ chia trước có hệ số chia là 8 nên tần số còn
lại là 5MHz/8 = 0.625MHz hay bằng 625,000Hz.
Bài tập 416. Chương trình đếm phút giây chính xác dùng timer T3 tạo ngắt.
Hiển thị trên 8 led 7 đoạn: phút ở 2 led thứ 4, 3 và giây ở 2 led thứ 1, 0.
Lưu tên file “bai_416_dem_phut_giay_t3”.
Bài tập 417. Chương trình đếm giờ phút giây chính xác dùng timer T3 tạo ngắt. Hiển
thị trên 8 led 7 đoạn: giờ ở 2 led thứ 7, 6, phút ở 2 led thứ 4, 3 và giây ở 2 led thứ 1, 0.
Lưu tên file “bai_417_dem_gio_phut_giay_t3”.
Bài mẫu 418. Chương trình đếm giờ phút giây chính xác dùng timer T3 tạo ngắt.
Hiển thị trên 8 led 7 đoạn: giờ ở 2 led thứ 7, 6, phút ở 2 led thứ 4, 3 và giây ở 2 led thứ
1, 0. Có thêm 3 nút UP, DW và MOD để chỉnh thời gian. Nút MOD chọn lần lượt 4 chế
độ: (0) là không cho chỉnh, (1) cho chỉnh giờ, (2) cho chỉnh phút, (3) cho chỉnh giây.
Khi cho chỉnh: nhấn và giữ nút UP sẽ chỉnh tăng, nhấn và giữ nút DW sẽ chỉnh giảm,
cuộn tròn giá trị. Sau một thời gian nếu không chỉnh tăng hay giảm thì sẽ tự thoát khỏi
chế độ chỉnh.
Lưu tên file “bai_418_gio_phut_giay_3key_t3”.
a.Mục đích: Biết thêm cách lập trình để chỉnh thời gian.
b.Lưu đồ, giải thuật: Sử dụng timer để định thời 0.1 giây và báo ngắt giống các bài
trước. Thêm biến giá trị mode và khi nhấn phím mod thì thay đổi giá trị mode để
chọn đối tượng cần chỉnh. Nhấn phím UP hoặc DW để thay đổi đối tượng đang chọn.
c. Chương trình con “bai_418_gio_phut_giay_3key_tv.c”.
signed int8 bdn,giay,phut,gio;
signed int8 gt_mod,tg_chinh;
#int_timer3
void timer3_ct_con_ngat()
{
void h418_gpg_khoi_tao_ngat_timer3()
{
enable_interrupts(global);
enable_interrupts(int_timer3);
setup_timer_3(t3_internal|t3_div_by_8);
set_timer3(3036);
bdn=0; giay=0; phut=0;
}
void h418_gpg_hien_thi_binh_thuong()
{
giaima_bin_2so_vitri_vn(giay,0,kx_vn);
giaima_bin_2so_vitri_vn(phut,3,kx_vn);
giaima_bin_2so_vitri_vn(gio,6,kx_vn);
xuat_8led_7doan();
}
void h418_gpg_hien_thi_chop_tat()
{
if(bdn==0)
h418_gpg_hien_thi_binh_thuong();
if(bdn==5)
{
if((gt_mod==1)&&(input(bt0))&&(input(bt1)))
{
led_7d[7]=0xff; led_7d[6]=0xff;
}
if((gt_mod==2)&&(input(bt0))&&(input(bt1)))
{
led_7d[4]=0xff; led_7d[3]=0xff;
}
if((gt_mod==3)&&(input(bt0))&&(input(bt0)))
{
led_7d[1]=0xff; led_7d[0]=0xff;
}
xuat_8led_7doan();
}
}
void h418_gpg_tang_theo_bdn()
{
if (giay<59) giay++;
82 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
else
{
giay =0;
if(phut<59) phut++;
else
{
phut=0;
if(gio<24) gio++;
else gio=0;
}
}
}
void h418_gpg_chinh_tang()
{
switch (gt_mod)
{
case 1: if (gio==23) gio=0;
else gio++;
break;
case 2: if (phut==59) phut=0;
else phut++;
break;
case 3: if (giay==59) giay=0;
else giay++;
break;
default: break;
}
}
void h418_gpg_chinh_giam()
{
switch (gt_mod)
Thực hành vi điều khiển PIC 83
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
{
case 1: if (gio==0) gio=23;
else gio--;
break;
case 2: if (phut==0) phut=59;
else phut--;
break;
case 3: if (giay==0) giay=59;
else giay--;
break;
default: break;
}
}
void main()
{
set_up_port();
h418_gpg_khoi_tao_ngat_timer3();
while(true)
{
b418_gpg_3bt(400,250);
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: Giờ phút giây đếm bắt đầu từ 00. Tiến hành nhấn phím MOD để
chọn chỉnh giờ, khi đó giờ chớp tắt, nhấp phím UP để tăng giờ hoặc nhấn DW để
giảm giờ cho đến giá trị mong muốn. Tương tự có thể chọn chỉnh phút và giây.
Khi chọn mà không chỉnh thì sau 20 giây thì sẽ tự động thoát khỏi chế độ chỉnh.
Bài này dùng hàm kiểm tra phím nhấn theo cách 2 mới thực hiện tốt, không làm chậm
quá trình đếm giây khi còn nhấn phím.
Hình 4-8. Chọn chế độ 8/16 phím, đơn phím hay đa phím
4.6.3 Giao tiếp theo chuẩn 2 dây của bàn phím cảm ứng TTP229
Bộ thực hành vi điều khiển được thiết kế giao tiếp theo dạng trực tiếp cho 1 số phím và
theo chuẩn 2 dây nối tiếp. Dạng trực tiếp thì giống như nút nhấn đơn đã thực hành ở chương 3
và đã viết ở dạng hàm con.
Phần này trình bày giao tiếp nối tiếp 2 dây chế độ 16 phím có dạng sóng như hình 4-9.
Chuẩn giao tiếp 2 dây: thì IC TTP229 sẽ nhận clock xung vào ở chân SCL và sẽ xuất dữ
liệu ra ở chân SDO.
Ban đầu 2 tín hiệu đều ở mức 1.
4.6.5 Các bài thực hành điều khiển dùng bàn phím cảm ứng TTP229
Bài mẫu 421. Viết chương trình đọc bàn phím touch hiển thị mã phím trên 5 led đơn
và giải mã hiển thị trên 2 led 7 đoạn thứ 1, 0.
Lưu tên file “bai_421_touch_ma_phim”.
Mục đích: Biết đọc mã phím của bàn phím cảm ứng TTP229.
a.
Lưu đồ, giải thuật: Đọc mã phím so sánh nằm trong giới hạn 16 phím thì xem như có
b.
phím nhấn thì tiến hành xuất ra led đơn và giải mã xuất ra led 7 đoạn.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
unsigned int8 mp8;
void b421_ttp229_doc_16phim()
{
mp8 = key_tip229_cdoi_c2(10);
if((mp8>0)&&(mp8<17))
{
xuat_32led_don_4byte(0,0,0,mp8);
giaima_bin_2so_vitri_vn(mp8,0,kx_vn);
xuat_8led_7doan();
}
}
void main()
{
set_up_port();
while(true)
{
b421_ttp229_doc_16phim();
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Tiến hành chạm phím và quan sát kết quả trên led đơn và 7 đoạn.
Thực hành vi điều khiển PIC 89
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
f. Hãy cho biết tại sao không hiển thị ra 4 led đơn mà phải là 5 led đơn?
Bài tập 422. Hãy viết chương trình đọc bàn phím touch và hiển thị mã phím trên 1 led
7 đoạn thứ 0: các phím từ 1 đến 9 thì vẫn hiển thị tương ứng 1 đến 9, phím 10 đến 15 thì
hiển thị tương ứng A đến F, phím 16 thì hiển thị số 0.
Lưu tên file “bai_422_touch_ma_phim_hex”.
Bài mẫu 423. Hãy viết chương trình đọc bàn phím touch và hiển thị mã phím trên 8
led 7 đoạn dịch trái: khi nhấn thì phím sẽ xuất hiển ở led thứ 0 và các số trước đó dịch
sang trái 1 led. Ban đầu 8 led tắt. Thêm delay 500ms giữa 2 lần nhấn để giảm tốc độ.
Lưu tên file “bai_423_touch_ma_phim_dich_trai”.
Mục đích: Biết dữ liệu dịch trái mảng chứa mã 7 đoạn khi nhấn phím.
a.
Lưu đồ, giải thuật: Tạo mảng có 8 phần tử hiển thị trên 8 led tương ứng. Gọi hàm
b.
quét phím: nếu có nhấn thì dịch mảng sang trái 1 phần tử, giải mã hiển thị mã phím
mới và lưu vào phần tử cuối cùng bên phải – chính là phần tử thứ 7.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
unsigned int8 mp8;
void h423_dpst_8led_7doan()
{
for(int i=7; i>0; i--)
led_7d[i] = led_7d[i-1];
}
void b423_doc_16phim_single_dpst_8led()
{
mp8 = key_tip229_cdoi_c2(10);
if((mp8>0)&&(mp8<17))
{
h423_dpst_8led_7doan();
led_7d[0] = ma7doan[mp8%16];
xuat_8led_7doan();
delay_ms(500);
}
}
void main()
{
set_up_port();
while(true)
{
Bài tập 424. Hãy viết chương trình giống bài 423 nhưng theo chiều dịch từ trái sang
phải. Bài 423 xem như chọn lối vào phải, bài 424 xem như chọn lối vào trái.
Lưu tên file “bai_424_touch_ma_phim_dich_phai”.
Bài tập 425. Hãy viết chương trình giống bài 423 nhưng chỉ dịch các phím số từ 0 đến
9. Các phím còn lại làm phím chức năng: Phím 10 khi nhấn thì không cho dịch nữa, phím
11 khi nhấn thì cho phép dịch tiếp, phím 12 thì xóa hết và tắt, phím 13 thì undo 4 cấp,
phím 15 redo lại sau khi nhấn undo. Dùng thêm 32 led đơn để chỉ thị các chế độ.
Lưu tên file “bai_425_touch_ma_phim_dich_undo”.
Bài tập 426. Hãy viết chương trình điều khiển 8 led đơn từ 0 đến 7 theo yêu cầu:
Các phím từ 1 đến 8 sẽ làm 8 led sáng, các phím từ 8 đến 16 thì làm tắt 8 led.
Xem như 1 cặp phím điều khiển ON/OFF 1 led, 8 cặp cho 8 led độc lập nhau.
Lưu tên file “bai_426_touch_on_off_8led”.
Bài tập 427. Hãy viết chương trình điều khiển 16 led đơn từ 0 đến 15 theo yêu cầu:
Phím 1 điều khiển ON/OFF led LD0, … tương tự cho 15 phím còn lại.
Lưu tên file “bai_427_touch_on_off_16led”.
4.6.6 Các bài thực hành cài giới hạn bằng bàn phím cảm ứng TTP229
Bài mẫu 428. Hãy viết chương trình định thời 2 số có cài bằng bàn phím touch.
Có 1 mạch đếm giây từ 00 đến 99 hiển thị ở 2 led 7, 6. Ban đầu hiển thị số 00.
Thời gian cài đặt hiển thị ở 2 led 1, 0. Ban đầu hiển thị số 00.
Chức năng các phím: Dùng các phím từ “0” đến “9” để nhập thời gian cài đặt 2 số
trong phạm vi từ 05 dến 99 lối vào phải.
Phím “10” khi nhấn thì không cho thay đổi và nếu số cài nhỏ hơn 5 thì tự động cho
bằng 5 và cho mạch đếm giây bắt đầu đếm từ 00, nếu 32 led đơn tắt thì tắt.
Thực hành vi điều khiển PIC 91
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
Khi giá trị đếm giây bằng giá trị cài thì 32 led đơn sáng – mạch đếm giây ngừng.
Phím “11” có chức năng tắt 32 led đơn.
Phím “12” có chức năng hủy quá trình đang đếm sau khi nhấn phím “10”.
Các phím còn lại không quan tâm.
Lưu tên file “bai_428_touch_dinh_thoi_2so”.
a. Mục đích: Biết lập trình cho một hệ thống định thời nhỏ.
b. Lưu đồ giải thuật:
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
usi8 mp8,giay,giay_cai,bdn;
int1 tt_ena_dis=0, tt_on_off=0;
#int_timer3
void timer3_ct_con_ngat()
{
bdn++;
set_timer3(3036);
}
void h428_dem_giay_dinh_thoi_timer3()
{
if(tt_on_off==tt_on)
{
if (bdn>=10)
{
bdn = 0;
giay++;
}
if((giay==giay_cai)&&(tt_on_off==tt_on))
{
sang_32led();
void h428_hien_thi_dinh_thoi_giay_2so()
{
led_7d[1] = ma7doan[bcd_8led[1]];
led_7d[0] = ma7doan[bcd_8led[0]];
giaima_bin_2so_vitri_vn(giay,6,kx_vn);
xuat_8led_7doan();
}
void h428_cai_giay_dinh_thoi_2so()
{
mp8 = key_tip229_cdoi_c2(10);
if((mp8>0)&&(mp8<17))
{
mp8 = mp8%16;
if((mp8<10)&&(tt_ena_dis!=enable))
{
bcd_8led[1] = bcd_8led[0];
bcd_8led[0] = mp8;
delay_ms(200);
}
else if(mp8==10)
{
tt_on_off = tt_on;
tt_ena_dis = enable;
giay_cai=bcd_8led[1]*10 +bcd_8led[0];
if(giay_cai<5)
{
giay_cai = 5;
bcd_8led[1]=0; bcd_8led[0]=5;
}
giay=0;
tat_32led();
timer3_xung_noi_on(co_reset);
}
else if(mp8==11) tat_32led();
else if(mp8==12)
{
tt_on_off = tt_off;
Thực hành vi điều khiển PIC 93
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
tt_ena_dis = disable;
timer3_xung_noi_off(no_reset);
giay=0;
}
}
}
void b428_dinh_thoi_giay_2so()
{
h428_cai_giay_dinh_thoi_2so();
h428_dem_giay_dinh_thoi_timer3();
h428_hien_thi_dinh_thoi_giay_2so();
}
void main()
{
set_up_port();
enable_interrupts(global);
enable_interrupts(int_timer3);
bdn=0; giay=0;
while(true)
{
b428_dinh_thoi_giay_2so();
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Nhập giây cài từ các phím số 0 đến 9. Sau đó nhấn phím 10 để bắt
đầu đếm giây cho đến khi bằng gây cài thì đếm giây ngừng và 32 led đơn sáng. Có
thể nhập lại thời gian cài khác.
Bài tập 429. Hãy viết chương trình giống bài 438 nhưng đếm và cài đều là 3 số.
Lưu tên file “bai_429_touch_dinh_thoi_3so”.
Bài tập 430. Giống bài 414 nhưng dùng bàn phím cảm ứng để thay đổi giới hạn. Giới
hạn mặc nhiên ban đầu là 50. Thay phím đơn Stop bằng phím A và phím đơn Run bằng
phím D.
Lưu tên file là “bai_430_dem_xung_t0_stop_run_32led_gh_touch”.
Hình 4-12. Dạng sóng theo chiều kim đồng hồ - chiều thuận
Nếu B = A thì núm xoay ngược chiều kim đồng hồ. Xem hình 4-13.
Hình 4-13. Dạng sóng ngược chiều kim đồng hồ - chiều nghịch
4.7.3 Giao tiếp vi điều khiển với bộ mã hóa xoay vòng
96 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
Trong bộ kit thực hành thì vi điều khiển giao tiếp với module này bằng 3 port.
Tín hiệu A, B và SW nối với pin_b5, pin_e4 và pin_f0.
4.7.4 Thư viện của module mã hóa xoay vòng
Trong thư viện “tv_01_18f6722_define” đã định nghĩa các port giao tiếp với 3 tín hiệu của
bộ mã hóa xoay vòng.
a. Các định nghĩa: Các tên của module mã hóa xoay vòng.
#define rtenc_a pin_b5
#define rtenc_b pin_e4
#define rtenc_sw pin_f0
Trong thư viện “tv_rotary_encoder.c” có khai báo các biến và các hàm.
b. Hàm 410: Biến vị trí, vị trí trước và vị trí hiện tại.
signed int8 rti;
signed int8 vt_tr=0,vt_ht=5;
c. Hàm 411: Hàm xác định vị trí.
void vitri_rotary_360()
{
if((input(rtenc_a)==0)&&(input(rtenc_b)==0)) vt_ht=0;
else if((input(rtenc_a)==1)&&(input(rtenc_b)==0)) vt_ht=1;
else if((input(rtenc_a)==1)&&(input(rtenc_b)==1)) vt_ht=2;
else if((input(rtenc_a)==0)&&(input(rtenc_b)==1)) vt_ht=3;
}
Giải thích:Hàm có chức năng xác định 4 trạng thái của bộ mã hóa xoay và gán giá trị vị trí
hiện tại tương ứng.
d. Hàm 412: Hàm xác định chiều xoay và giá trị thay đổi trong giới hạn.
void doc_rotary_360(signed int8 ght, signed int8 ghd)
{
vitri_rotary_360();
if(vt_tr==0)
{
if(vt_ht==1) rti++;
else if(vt_ht==3) rti--;
}
else if(vt_tr==1)
{
if(vt_ht==2) rti++;
else if(vt_ht==0) rti--;
}
else if(vt_tr==2)
{
if(vt_ht==3) rti++;
else if(vt_ht==1) rti--;
}
else if(vt_tr==3)
{
Thực hành vi điều khiển PIC 97
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
if(vt_ht==0) rti++;
else if(vt_ht==2) rti--;
}
vt_tr=vt_ht;
if(rti>ght) rti = ght;
if((rti)<(ghd)) rti = ghd;
}
Giải thích: Đọc vị trí hiện tại, so sánh với vị trí trước đó để xác định chiều tăng hay giảm, cập
nhật vị trí mới, so sánh giới hạn biên trên và biên dưới.
4.7.5 Các bài thực hành ứng dụng bộ mã hóa xoay vòng
Bài mẫu 431. Viết chương trình đọc vị trí của bộ mã hóa xoay hiển thị trên các led 7
đoạn trong phạm vi từ [+100,-100].
Lưu tên file “bai_431_rotary_vitri_7doan”.
a. Mục đích: Biết đọc vị trí của bộ mã hóa xoay và hiển thị giá trị xoay thay đổi theo
chiều tăng giảm và giới hạn thay đổi.
b. Lưu đồ, giải thuật: Căn cứ vào dạng xung để biết chiều xoay tăng giảm.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
void hien_thi_7doan()
{
signed int8 rti_t;
if(rti<0)
{
rti_t = (-rti); led_7d[3] = 0xbf;
}
else
{
rti_t = rti; led_7d[3] = 0xb9;
}
giaima_bin_3so_vitri_vn(rti_t,0,cx_vn);
led_7d[7] = ma7doan[vt_ht];
led_7d[5] = ma7doan[vt_tr];
xuat_8led_7doan();
}
void main()
{
set_up_port();
rti=0;
hien_thi_7doan();
vitri_rotary_360();
vt_tr=vt_ht;
hien_thi_7doan();
Bài tập 432. Hãy viết chương trình điều khiển 32 led đơn: khi xoay theo chiều thuận
thì 32 led std pst, khi sáng hết và nếu xoay tiếp thì tắt dần. Tương tự thì xoay chiều nghịch
thì làm 32 led std_tsp.
Lưu tên file “bai_432_rotary_std_32led”.
void main()
{
set_up_port();
h418_gpg_khoi_tao_ngat_timer3();
while(true)
{
b418_gpg_3bt(30,30);
b339_32led_tong_hop_tu_dong_if();
delay_ms(20);
}
}
e. Tiến hành biên dịch và nạp.
Thực hành vi điều khiển PIC 99
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
f. Quan sát kết quả: Vừa đếm giờ phút giây có thể chỉnh được và điều khiển 32 led đúng
82 yêu cầu. Để chỉnh được thời gian của đồng hồ thì phải giảm thời gian của phím
mod và phím UP và Dw xuống để đáp ứng nhanh vì bài này vi điều khiển phải thực
hiện thêm các yêu cầu điều khiển 32 led.
Hình 5-1. Giao tiếp vi điều khiển với LCD qua thanh ghi dịch MBI5026
Bộ thực hành sử dụng IC thanh ghi MBI5026 để mở rộng port điều khiển LCD.
Phần vi điều khiển PIC giao tiếp với IC thanh ghi dịch MBI5026:
Có 4 tín hiệu điều khiển là:
MBI_SDI dùng để dịch dữ liệu nối tiếp.
MBI_SCK dùng để cấp xung clock.
MBI_LE3 điều khiển nạp dữ liệu song song từ TG dịch sang TG lưu trữ.
MBI_OE dùng để cho phép xuất dữ liệu.
Hai tín hiệu MBI_SDI và MBI_SCK nối với IC thông qua 2 jumper đã được gắn sẵn đề
phòng khi có vấn đề về phần cứng thì cách ly để tìm hư hỏng.
Có 1 SW2 để cấp nguồn cho LCD, SW đã chuyển sang vị trí ON để cấp nguồn.
Phần IC thanh ghi dịch MBI5026 giao tiếp với LCD:
Có 16 tín hiệu ngõ ra với các chức năng như sau:
Từ out0 đến out7: giao tiếp với bus 8 dữ liệu của LCD theo chế độ 8 bit (vẫn có thể
thực hành được chế độ 4 bit).
lcd_puts(2,0,hang2);
lcd_puts(3,0,hang3);
}
void main()
{
Bài mẫu 502. Chương trình hiển thị 2 chuỗi ở hàng 0 và 1, sau đó dịch trái với thời
gian trễ giây.
Lưu tên file “bai_502_lcd_ht_2hang_dich_trai”.
a.Mục đích: Biết dịch chuỗi ký tự trên các hàng của LCD.
b.Lưu đồ, giải thuật: Khởi tạo LCD, hiển thị 2 hàng 0 và 1. Sau đó tiến hành gọi hàm
điều khiển cursor display của LCD or thêm lựa chọn “cd_move_left”
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
void main()
{
set_up_port();
lcd_setup();
lcd_goto_xy(0,0);
lcd_data("khoa dien - dien tu ");
lcd_goto_xy(1,0);
lcd_data("bm dientucong nghiep");
delay_ms(1000);
while(true)
{
lcd_command(lcd_shift_left);
delay_ms(1000);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Hiển thị 2 hàng chuỗi và sau đó dịch chuyển xuống hai hàng dưới
rồi dịch lại 2 hàng trên.
Bài tập 503. Hãy viết chương trình hiển thị 4 hàng thông tin tùy ý.
Khi nhấn BT0 thì chỉ nội dung của hàng thứ 0 dịch trái cuộn tròn. Khi nhấn BT1 thì
ngừng. Nhấn BT2 thì dịch phải cuộn tròn.
Các hàng còn lại đứng yên. Thời gian delay 1s.
Bài tập 504. Hãy viết chương trình hiển thị 4 hàng thông tin tùy ý.
Khi nhấn BT0 lần 1 thì chỉ nội dung của hàng thứ 0 dịch trái cuộn tròn. Khi nhấn lần
2 thì ngừng. Khi nhấn lần 3 thì dịch phải cuộn tròn. Khi nhấn lần 4 thì ngừng. Lần 5 lặp
lại của lần 1.
Các hàng còn lại đứng yên. Thời gian delay 1s.
Lưu tên file “bai_504_lcd_hang0_dich_trai_phai_1btn”.
5.3.2 Các ứng dụng kết hợp bàn phím cảm ứng và LCD
Phần này thực hành các bài kết hợp LCD và bàn phím cảm ứng để cài giới hạn.
Bài tập 505. Hãy viết chương trình có chức năng khi nhấn phím bất kỳ của bàn phím
cảm ứng thì mã phím đó xuất hiện tại tận cùng bên phải của hàng 1, các ký tự đã nhấn sẽ
dịch sang trái. Các ký tự hàng còn lại không thay đổi. Giống các bài 423.
Hàng 0 hiển thị thông tin : “hay nhan phim bat ky”
Lưu tên file là “bai_505_lcd_ touch_dich_hang1”
a. Mục đích: Biết kết hợp bàn phím ma trận với LCD.
b. Lưu đồ, giải thuật: Quét bàn phím, nếu có thì tiến hành dịch mảng hàng 1 sang trái 1
vị trí, giải mã ASCII của mã phím nhấn và lưu vào phần tử cuối của mảng.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
unsigned int8 hang1[20];
unsigned int8 mp,i;
void xoa_hang_1()
{
for(i=0;i<20;i++) hang1[i]=" ";
}
void lcd_dich_ht_mp()
{
for(i=0;i<19;i++) hang1[i]=hang1[i+1];
mp = mp%16;
if(mp<10) hang1[19]=(mp+0x30);
else hang1[19]=(mp+0x37);
lcd_goto_xy(1,0);
for (i=0;i<20;i++) lcd_data(hang1[i]);
}
void main()
{
set_up_port();
lcd_setup();
Thực hành vi điều khiển PIC 107
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
lcd_goto_xy(0,0);
lcd_data("hay nhan phim bat ky");
xoa_hang_1();
while(true)
{
mp = key_tip229_cdoi_c2(10);
if(mp!=0xff)
{
lcd_dich_ht_mp();
delay_ms(200); //de giam toc do
}
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Hãy tiến hành nhấn phím thì sẽ xuất hiện ở hàng 1 và các ký tự
trước đó dịch sang trái là đúng.
f. Giải thích chương trình: tại sao cộng 0x30 và 0x37?
Bài tập 506. Hãy viết chương trình có chức năng khi mới cấp điện thì 3 hàng 1, 2, 3
hiển thị ký tự trắng, khi nhấn phím bất kỳ của bàn phím ma trận 4x4 thì mã phím đó xuất
hiện tại tận cùng bên phải của hàng 1, nhấn nửa thì dịch sang trái, cho đến khi được 20
kí tự mà nhấn nửa thì xuống hàng 2, khi đủ 20 ký tự thì dịch xuống hàng 3.
Hàng 0 hiển thị thông tin: “ hay nhan phim bat ky”
Lưu tên file là “bai_506_lcd_mtp4x4_dich_3hang_123”
Bài tập 507. Hãy viết chương trình có chức năng hiển thị 3 hàng thông tin bên dưới.
Trong đó XX là thời gian cài đặt 2 số từ 0 đến 59 bằng các phím số từ 0 đến 9 của bàn
phím ma trận. Khi nhấn phím A thì 32 led đơn nếu chưa tắt thì tắt, thời gian đếm giây YY
bắt đầu từ 0 cho đến khi bằng XX thì 32 led sáng, buzzer kêu đúng 5 giây rồi tắt. Nhấn
phím C để tắt 32 led. Khi đang đếm mà nhấn phím B thì ngừng, nhấn lại để đếm tiếp.
Phím E thì xóa YY về 0 và ngừng. Trong quá trình đang đếm thì không cho thay đổi giá
trị XX. Khi buzzer kêu thì ZZZ sẽ hiển thị chữ “ ON”, khi buzzer hết kêu thì hiển thị chữ
“OFF”.
Hàng 0 hiển thị thông tin : “Dieu Khien Buz: ZZZ”
Hàng 1 hiển thị thông tin : “Thoi gian cai: XX”
Hàng 2 hiển thị thông tin : “Thoi gian dem: YY”
Lưu tên file là “bai_507_lcd_mtp4x4_buzzer_on_off”
5.3.3 Đếm xung ngoại dùng timer T0 hiển thị trên LCD
Bài tập 509. Hãy hiệu chỉnh bài 412 thêm phần hiển thị trên LCD.
Hàng 0 hiển thị giá trị cài, hàng 1 hiển thị giá trị đếm.
Lưu tên file là “bai_509_lcd_8l7d_dem_sp_t0_ud”
Vùng nhớ CGRAM này có địa chỉ từ 0×40 đến 0×7F cho phép lưu 64 byte dữ liệu.
Mỗi ký tự hiển thị trên LCD là một ma trận gồm 8 byte nên vùng nhớ CGRAM cho phép
lưu được 8 ký tự.
Bảng 5-2. Vùng nhớ CGRAM
Vùng thứ Địa chỉ cuối B7 B6 B5 B4 B3 B2 B1 B0 Địa chỉ đầu Địa chỉ ký tự
0 0×47 Vùng nhớ 8 byte để lưu ký tự tự tạo 0×40 0
1 0×4F 0×48 1
2 0×57 0×50 2
3 0×5F 0×58 3
4 0×67 0×60 4
5 0×6F 0×68 5
6 0×77 0×70 6
7 0×7F 0×78 7
Bài mẫu 511. Chương trình hiển thị ký tự hay biểu tượng tự tạo trên LCD.
Hàng 0 hiển thị thông tin: “ HIEN THI TRAI TIM ”.
Lưu tên file “bai_511_lcd_cgram_trai_tim”.
Mục đích: Biết lập trình hiển thị các ký tự mong muốn.
a.
Lưu đồ, giải thuật: Khai báo mảng của ký tự trái tim, khởi tạo LCD, copy mảng mã
b.
trái tim từ vi điều khiển sang vùng nhớ CGRAM của LCD, gọi mã của trái tim.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
const unsigned char
hang2[]={0x0a,0x15,0x11,0x11,0x0a,0x04,0,0};
signed int8 i;
void main()
{
set_up_port();
lcd_setup();
lcd_goto_xy(0,0);
110 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
lcd_data(" hien thi trai tim ");
lcd_command(0x40);
for(i=0;i<8;i++) lcd_data(hang2[i]);
lcd_goto_xy(1,0); lcd_data(0);
while(true);
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Hiển thị trái tim ở đầu hàng 1 là đúng.
Hình 5-2. Hình ảnh các đoạn cho số lớn trên LCD
Các con số thứ tự đi kèm là trình tự khai báo trong mảng.
Mã hex của các đoạn tương ứng:
Hình 5-3. Tìm mã của các đoạn cho số lớn trên LCD
Bước 2: Kết hợp các đoạn để xây dựng các con số từ 0 đến 9
Để sáng con số lớn thì ta kết hợp các đoạn để được các con số từ 0 đến 9, mỗi con số sẽ
chiếm 6 vị trí như sau:
Bài mẫu 512. Chương trình hiển thị ký tự số 0 lớn trên LCD.
Lưu tên file “bai_512_lcd_lcd_so_to_0”.
Mục đích: Biết lập trình hiển thị số to có kích thước lớn trên màn hình LCD.
a.
Lưu đồ, giải thuật: Khai báo mảng 8 đoạn, khởi tạo LCD, copy mảng 8 đoạn từ vi
b.
điều khiển sang vùng nhớ CGRAM của LCD, gọi hiển thị số 0 to.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
void main()
{
set_up_port();
lcd_setup();
lcd_goto_xy(0,0);
lcd_data("hien thi so 0 hang 3");
lcd_khoi_tao_cgram_so_to();
lcd_hien_thi_so_to(0,2,0);
while(true);
}
Bài tập 513. Hãy viết chương trình hiển thị số 0123 lớn trên LCD.
Lưu tên file “bai_513_lcd_cgram_so_to_0123”.
Bài tập 514. Hãy hiệu chỉnh bài 508 phần hiển thị sản phẩm số to trên LCD.
Lưu tên file “bai_514_lcd_cgram_dsp_t0_so_to”.
Bài tập 515. Giống bài 514 nhưng chu kỳ đếm thứ nhất số nhỏ, chu kỳ thứ hai số to và
lặp lại. Giảm giới hạn đếm xuống ví dụ là 15 để thay đổi cho nhanh.
Lưu tên file “bai_515_lcd_cgram_dsp_t0_so_to_nho”.
Bài tập 516. Thêm vào bài 515: Chu kỳ đếm thứ 3 thì hàng chục số nhỏ, đơn vị số to.
Chu kỳ thứ 4 thì hàng chục số to, đơn vị số nhỏ và lặp lại.
Lưu tên file “bai_516_lcd_cgram_dsp_t0_4mod_so_to_nho”.
i2c_write(ds13_addr_rd);
for(i=0;i<j;i++) time_r[i]=i2c_read();
void main()
{
set_up_port();
ds1307_kiem_tra_ma();
while(true)
{
ds1307_doc_time(8);
if(giay_tam!=giay_ds)
{
giay_tam=giay_ds;
h518_gpg_hien_thi_binh_thuong();
}
delay_ms(500);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Đồng hồ hiển thị giờ phút giây trên 8 led. Nếu sai thời gian thực thì
hãy hiệu chỉnh lại các thông số cho đúng và thay đổi mã để cập nhật tự động. Khi đã
Thực hành vi điều khiển PIC 117
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
đếm đúng rồi thì bạn hãy nhớ thời gian đang đếm và tắt nguồn kit thực hành, sau vài
giây thì mở lại thì đồng hồ vận tiếp tục đếm là kit và chương trình hdong tốt. Nếu
chạy lại giờ cài đặt từ đầu thì xem lại chương trình và nguồn pin cấp cho IC.
Bài tập 519. Hãy hiệu chỉnh lại bài 518 sao cho có thể chọn hiển thị giờ phút giây hoặc
ngày tháng năm và thứ bằng nút nhấn bt3. Bình thường hiển thị “giờ phút giây”, nhấn bt3
lần 1 thì chuyển sang hiển thị “ngày tháng năm”, nhấn bt3 lần 2 thì chuyển sang hiển thị
“thu ”, nhấn bt3 lần 3 thì trở lại “giờ phút giây”.
Lưu tên file là “ bai_519_clock_ds1307_8l7d_full”.
Bài mẫu 520. Chương trình đổng hồ số thời gian thực dùng IC DS1307, hiển thị trên
8 led 7 đoạn và trên LCD 20×4. Mở rộng bài 518, thêm phần hiển thị giờ phút giây số to,
ngày tháng năm số nhỏ và thứ là text trên LCD.
Lưu tên file “bai_520_ds1307_clock_8l7d_lcd”.
a. Mục đích: Giống bài 518, chỉ khác là hiển thị đầy đủ giờ phút giây, ngày tháng năm
và thứ trên LCD.
b. Lưu đồ, giải thuật: Đã trình bày ở bài 518, chỉ thêm phần hiển thị trên LCD.
c. Chương trình con: “bai_520_ds1307_tv”
void ds1307_hthi_text_lcd()
{
lcd_goto_xy(0,0);
lcd_data("CLOCK DS1307 ");
}
void ds1307_hthi_thu_lcd()
{
lcd_goto_xy(3,0);
switch (time_r[3])
{
case 1: lcd_data("Sunday: "); break;
case 2: lcd_data("Monday: "); break;
case 3: lcd_data("Tuesday: "); break;
case 4: lcd_data("Wednesday:"); break;
case 5: lcd_data("Thursday: "); break;
case 6: lcd_data("Friday: "); break;
case 7: lcd_data("Saturday: "); break;
default: break;
}
}
void ds1307_hthi_ntn_lcd()
{
lcd_hthi_byte(time_r[4],3,12);
lcd_data("-");
void ds1307_hthi_giay_lcd_soto()
{
lcd_hien_thi_so_to(giay_ds/16,1,14);
lcd_hien_thi_so_to(giay_ds%16,1,17);
}
void ds1307_hthi_phut_lcd_soto()
{
lcd_hien_thi_so_to(phut_ds/16,1,7);
lcd_hien_thi_so_to(phut_ds%16,1,10);
}
void ds1307_hthi_gio_lcd_soto()
{
lcd_hien_thi_so_to(gio_ds/16,1,0);
lcd_hien_thi_so_to(gio_ds%16,1,3);
}
void ds1307_hthi_lcd_soto()
{
ds1307_hthi_giay_lcd_soto();
if(giay_ds==0)
{
ds1307_hthi_phut_lcd_soto();
if(phut_ds==0)
{
ds1307_hthi_gio_lcd_soto();
if(gio_ds==0)
{
ds1307_hthi_ntn_lcd();
ds1307_hthi_thu_lcd();
}
}
}
}
d. Chương trình chính:
#include <tv_kit_vdk_18f6722_all.c>
#include <bai_520_clock_ds1307_8l7d_lcd_tv.c>
usi8 giay_tam;
void h518_gpg_hien_thi_binh_thuong()
{
giaima_bcd_2so_vitri_vn(giay_ds,0,kx_vn);
void main()
{
set_up_port();
ds1307_kiem_tra_ma();
lcd_setup();
lcd_khoi_tao_cgram_so_to();
lcd_goto_xy(0,0);
ds1307_hthi_text_lcd();
ds1307_hthi_thu_lcd();
ds1307_hthi_giay_lcd_soto();
ds1307_hthi_phut_lcd_soto();
ds1307_hthi_gio_lcd_soto();
ds1307_hthi_ntn_lcd();
while(true)
{
ds1307_doc_time(8);
if(giay_tam!=giay_ds)
{
giay_tam=giay_ds;
h518_gpg_hien_thi_binh_thuong();
ds1307_hthi_lcd_soto();
}
delay_ms(500);
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: Giờ phút giây, ngày tháng năm và thứ hiển thị thêm trên LCD.
Bài tập 521. Giống bài 520 có thêm 3 nút mod, up và dw để chỉnh thời gian.
Lưu tên file “bai_521_clock_ds1307_lcd_3key”.
Bài tập 522. Giống bài 521 thêm chức năng reng chuông giờ học, với yêu cầu như sau:
Các thông số reng chuông (dùng buzzer thay cho chuông):
07-00-00 reng 3 hồi chuông. 07-50-00 reng 1 hồi chuông.
08-40-00 reng 1 hồi chuông. 08-50-00 reng 2 hồi chuông.
5.6 KẾT HỢP 3 MODULE: 32 LED, 8 LED 7 ĐOẠN, LCD, NÚT NHẤN
Phần này thực hành kết hợp các module để thấy được khả năng kết hợp và mở rộng.
Bài mẫu 525. Kết hợp các module: đếm xung ngoại dùng T0 hiển thị trên led 7 đoạn,
đồng hồ thời gian thực hiển thị trên LCD, vừa điều khiển 32 led đơn sáng 82 yêu cầu tự
động và đếm xung ngoại hiển thị số to trên LCD.
Lưu tên file “bai_525_th_lcd_8l7d_32led_t0_t3_ds13”.
a. Mục đích: Biết kết hợp 32 led đơn, 8 led 7 đoạn, nút nhấn, LCD, timer và counter.
b. Lưu đồ, giải thuật: Chỉ tổng hợp các bài đã thực hành.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
#include <chuong3_32led_if_no_delay.c>
#include <bai_520_clock_ds1307_8l7d_lcd_tv.c>
#include <bai_411_t0_tv.c>
usi8 giay_tam;
void main()
{
set_up_port();
ds1307_kiem_tra_ma();
lcd_setup();
lcd_khoi_tao_cgram_so_to();
lcd_goto_xy(0,0);
ds1307_hthi_text_lcd();
ds1307_hthi_thu_lcd();
ds1307_hthi_giay_lcd_soto();
ds1307_hthi_phut_lcd_soto();
ds1307_hthi_gio_lcd_soto();
ds1307_hthi_ntn_lcd();
setup_timer_0(t0_ext_l_to_h|t0_div_1);
Bài tập 526. Hãy mở rộng bài 525 thêm nút nhấn MOD1, MODE2, UP và DW để
chỉnh giới hạn và thời gian.
Lưu tên file “bai_526_th_lcd_8l7d_32led_t0_t3_ds13”.
Chương 6: THỰC
HÀNH
CHUYỂN ĐỔI TƯƠNG TỰ
SANG SỐ - ADC, CÁC CẢM
BIẾN
Bài mẫu 601. Đo nhiệt độ trung bình 100 lần từ cảm biến LM35A. Hiển thị phần
nguyên 2 số: trên 2 led 7 đoạn thứ 0, 1 và hiển thị số to trên LCD ở bên trái hàng 1, 2.
Hiển thị 2 số lẻ số nhỏ nằm kế số to sau dấu chấm thập phân. Tự động mở đèn gia tăng
nhiệt độ khi nhiệt độ đo nhỏ hơn 31ºC và tắt đèn khi lớn hơn 34ºC. Buzzer kêu khi nhiệt
độ lớn hơn 34ºC và tắt buzzer khi nhỏ hơn 34ºC. Có nút BT3 để tắt buzzer.
void main()
{
set_up_port();
lcd_setup();
lcd_khoi_tao_cgram_so_to();
lcd_goto_xy(0,0);
lcd_data("LM35A");
while(true)
{
h601_adc_lm35a_doc_xuly(solan);
h601_adc_lm35a_ht_lcd(1,0,1,1);
h601_adc_lm35a_ht_7doan(6,1);
delay_ms(200);
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: xem nhiệt độ đo hiển thị trên led 7 đoạn và trên LCD đúng bằng
nhiệt độ môi trường thì chương trình đã viết đúng.
g. Giải thích:
Gọi hàm chuyển đổi ở trên với biến “solan” và chọn kênh của cảm biến LM35A,
trả về kết quả sau khi chuyển đổi gán cho biến “lm35a”. Chia cho hệ số chênh lệch
độ phân giải. Gọi hàm tách phần nguyên và phần thập phân.
Nếu phần nguyên thay đổi so với trước đó thì tiến hành cập nhật cho biến tạm, giải
mã hiển thị số to trên LCD và hiển thị luôn số thập phân nếu các bit tương ứng
cho phép theo các tọa độ trên LCD và led 7 đoạn. Hiển thị thêm trên led 7 đoạn.
Bài tập 602. Giống bài 601 nhưng dùng cảm biến LM35B. Hiển thị phần nguyên 2 số:
trên 2 led 7 đoạn thứ 3, 2 và hiển thị số to trên LCD ở bên phải hàng 1, 2. Hiển thị 2 số lẻ
số nhỏ nằm kế số to sau dấu chấm thập phân.
Hàng 0 hiển thị “LM35B” ở bên phải.
Lưu tên file “bai_602_lcd_7doan_lm35b_den_buz_bt3”.
Bài tập 603. Kết hợp 2 bài bài 601 và 602 nhưng đo trung bình 50 lần.
Điều khiển đèn chỉ khi nhiệt độ cả 2 lớn hơn 34ºC hoặc nhỏ hơn 31ºC.
Lưu tên file “bai_603_lcd_7doan_lm35a_b_den_buz_bt3”.
jy = h601_adc_read(20,2);
float_to_ng_2so_tp(jy);
vry = so_ng;
}
void b605_joystick_ht_7doan()
{
giaima_bin_4so_vitri_vn(vrx,4,cx_vn);
giaima_bin_4so_vitri_vn(vry,0,cx_vn);
xuat_8led_7doan();
}
void b605_joystick_ht_lcd()
{
if(vrx_t!=vrx)
{
vrx_t=vrx;
lcd_gm_ht_4so_to_xvn(vrx,0,8,cx_vn);
}
if(vry_t!=vry)
{
vry_t=vry;
lcd_gm_ht_4so_to_xvn(vry,2,8,cx_vn);
}
}
d. Chương trình chính:
#include <tv_kit_vdk_18f6722_all.c>
#include <bai_605_joystick_tv.c>
void main()
{
set_up_port();
lcd_setup();
lcd_khoi_tao_cgram_so_to();
lcd_goto_xy(0,0);
lcd_data("JOYSTICK");
lcd_goto_xy(1,4);
lcd_data("VRX:");
lcd_goto_xy(3,4);
Bài mẫu 606. Thêm vào bài 605 là dùng nút nhấn của Joystick để điều khiển tắt mở 16
led đơn.
Lưu tên file “bai_606_lcd_7doan_joystick_16led_btn”.
Bài tập 607. Kết hợp 2 bài 603 và 605: đo nhiệt độ dùng 2 cảm biến LM35 chỉ hiển thị
trên LCD, đọc giá trị 2 biến trở của Joystick hiển thị trên 8 led 7 đoạn.
Tổng hợp và hiệu chỉnh hai bài đã làm.
Lưu tên file “bai_607_lcd_7doan_joystick_lm35”.
Bài tập 608. Giống bài 607 nhưng nhiệt độ dùng 2 cảm biến LM35 hiển thị ở hàng 0
và 1, giá trị 2 biến trở của Joystick hiển thị ở hàng 2 và 3. Bố trí cho hợp lý.
Lưu tên file “bai_608_lcd_7doan_joystick_lm35”.
Hình 6-4. Dạng sóng của cảm biến khoảng cách GP2D12
Hình 6-5. Đồ thị chuyển đổi của cảm biến khoảng cách GP2D12
float_to_ng_2so_tp(kc);
kc_ng = so_ng;
kc_tp = so_tp;
if(kc_t!=kc_ng)
{
kc_t=kc_ng;
lcd_gm_ht_2so_to_xvn(kc_ng,2,0,kx_vn);
Thực hành vi điều khiển PIC 133
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
giaima_bin_2so_vitri_vn(kc_ng,3,cx_vn);
xuat_8led_7doan();
}
if(http) lcd_hien_thi_2so_tp_nho(kc_tp,3,6);
}
d. Chương trình chính:
#include <tv_kit_vdk_18f6722_all.c>
#include <bai_609_gp2d12_tv.c>
void main()
{
set_up_port();
lcd_setup();
lcd_khoi_tao_cgram_so_to();
h609_lcd_cbkc_gp2d12();
while(true)
{
b609_adc_cbkc_gp2d12(10,1);
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: Bạn hãy dùng tay để gần cảm biến GP2D12 và xem giá trị khoảng
cách từ cảm biến đến tay của bạn hiển thị trên LCD theo đơn vị cm.
Bài tập 610. Giống bài 609 chỉ khác là tính diện tích hình chữ nhật dùng cảm biến
GP2D12. Bạn để tay ở vị trí nào đó trước cảm biến ví dụ là 12,5 (cm) hiển thị ở hàng 1,
xong nhấn bt0 để lưu giá trị này và xem như là chiều dài D. Tiếp theo cảm biến sẽ đo tiếp
và hiển thị ở hàng 2. Bạn cũng để tay trước cảm biến ví dụ là 20cm, xong bạn nhấn bt1
để lưu giá trị này và xem như là chiều rộng R. Bạn nhấn bt2 thì sẽ hiển thị diện tích hình
chữ nhật ở hàng 3. Nhấn bt3 thí xóa hết và bắt đầu lại từ đầu.
Lưu tên file “bai_610_gp2d12_tinh_dtich”.
Bài tập 611. Giống bài 609 chỉ khác là điều khiển 32 sáng tắt dần phải sang trái nhanh
chậm theo khoảng cách. Lấy giá trị đo được làm thời gian delay ví dụ khoảng cách là
75cm thì thời gian delay là 75ms. Giải thuật lập trình làm sao cho đáp ứng nhanh tất cả
các yêu cầu.
Lưu tên file “bai_611_gp2d12_dk_32led_std”.
Bài tập 612. Giống bài 609 chỉ khác là thêm phần điều khiển buzzer báo động như sau:
khi khoảng cách từ 70 đến 80cm thì tắt buzzer. Từ 60 đến 69cm thì buzzer kêu 1s tắt 7
giây, lặp lại. Từ 50 đến 59cm thì buzzer kêu 1s tắt 6 giây, lặp lại. Từ 40 đến 49cm thì
buzzer kêu 1s tắt 5 giây, lặp lại. Từ 30 đến 39cm thì buzzer kêu 1s tắt 4 giây, lặp lại. Từ
134 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
20 đến 29cm thì buzzer kêu 1s tắt 3 giây, lặp lại. Từ 10 đến 19cm thì buzzer kêu 1s tắt 2
giây, lặp lại. Giải thuật lập trình làm sao cho đáp ứng nhanh tất cả các yêu cầu.
Lưu tên file “bai_612_lcd_gp2d12_dk_td_buzzer”.
Hình 6-6. Hình cảm biến siêu âm và góc phát thu sóng
Cảm biến HC-SR 04 có 4 chân: chân cấp nguồn Vcc, chân kích (trigger), chân nhận tín
hiệu dội (echo) và chân GND.
Sau này có loại HC-SR 05 có thêm 1 tín hiệu out.
Giản đồ thời gian các tín hiệu:
Để đo khoảng cách dùng cảm biến siêu âm thì hệ thống điều khiển phải kích tín hiệu chân
trigger tạo ra 1 xung có mức logic 1 tối thiểu là 10µs. Tín hiệu tương thích chuẩn TTL. Sau đó
thì mạch cảm biến sẽ tạo ra một chuỗi 8 xung phát ra ở biến tử phát, sau khi gặp vật cản nằm
trong giới hạn đo thì sóng sẽ phản xạ về và tín hiệu echo lên mức 1 với thời gian ở mức 1 tỷ lệ
thuận với khoảng cách đo.
Hệ thống phải đo thời gian tín hiệu echo ở mức logic 1 theo đơn vị thời gian là µs, lấy thời
gian đo được chia cho 58 sẽ được khoảng cách cần đo theo đơn vị cm, chia cho 148 sẽ được
khoảng cách theo đơn vị inch – các hệ số này do nhà cung cấp cho chúng ta – dựa vào tốc độ
sóng phát đi và phản xạ về.
set_timer3(0);
while(!(input(echo)));
setup_timer_3(t3_internal|t3_div_by_8);
while(input(echo));
setup_timer_3(t3_disabled);
kcs = get_timer3();
}
void b613_cbkc_hc04()
{
usi16 kc_ng,kc_tp,kc_t;
h613_tao_xung_trigger();
kcs=kcs*1.6;
kcs=(kcs/58);
float_to_ng_2so_tp(kcs);
kc_ng = so_ng;
kc_tp = so_tp;
if(kc_t!=kc_ng)
{
kc_t=kc_ng;
lcd_gm_ht_2so_to_xvn(kc_ng,2,0,kx_vn);
giaima_bin_2so_vitri_vn(kc_ng,3,cx_vn);
xuat_8led_7doan();
}
lcd_hien_thi_2so_tp_nho(kc_tp,3,6);
}
a. Chương trình chính:
#include <tv_kit_vdk_18f6722_all.c>
#include <bai_613_hcsr04_tv.c>
void main()
{
set_up_port();
Bài tập 614. Kết hợp 2 bài: 613: đo khoảng cách dùng HCSR-04 và 609 đo khoảng
cách dùng GP2D12 hiển thị trên LCD. Hàng 0, 1 cho GP2D12, hàng 2, 3 cho HCSR04.
Lưu tên file “bai_614_lcd_hcsr_04_gp2d2_do_kcach”.
Bài tập 616. Giống bài 615 nhưng mỗi yêu cầu thực hiện trong 10 giây sau đó tự động
chuyển sang yêu cầu kế. Bắt đầu từ yêu cầu 1. Hiển thị đếm 10 giây ở vị trí nào còn trống
trên LCD hoặc ở led đơn.
Lưu tên file “bai_616_tong_hop_lm35_joy_hcsr_gp2d12_auto”.
Hình 6-11. Cấu trúc 2 thanh ghi lưu nhiệt độ của vi mạch DS18B20
Các bit dấu (S) có giá trị là 0 nếu là số dương và bằng 1 nếu là số âm.
Nếu cấu hình ở độ phân giải 12 bit thì tất cả các bit trong thanh ghi đều lưu dữ liệu.
Nếu cảm biến cấu hình ở độ phân giải 11 bit thì bỏ bit thứ 0 (BIT 0).
Nếu cảm biến cấu hình ở độ phân giải 10 bit thì bỏ 2 bit thứ 1 và 0 (BIT 1, 0).
Nếu cảm biến cấu hình ở độ phân giải 9 bit thì bỏ 3 bit thứ 2, 1 và 0 (BIT 2, 1, 0).
6.5.5 Hoạt động cảnh báo quá nhiệt của vi mạch DS18B20
Sau khi vi mạch DS18B20 thực hiện xong chuyển đổi nhiệt độ thì giá trị nhiệt độ được so
sánh với các giá trị nhiệt độ ngưỡng dưới và ngưỡng trên do người dùng thiết lập trong 2 thanh
ghi TH và TL – có cấu trúc như hình 6-12.
Hình 6-12. Cấu trúc 2 thanh ghi lưu nhiệt độ báo động của vi mạch DS18B20
Bit S là bit dấu để thiết lập giá trị dương và âm. Giá trị lưu trong 2 thanh ghi TH và TL
không bị mất khi mất điện do có lưu trong bộ nhớ EEPROM. Có thể đọc giá trị của 2 thanh ghi
TH và TL chính là byte thứ 2 và thứ 3 trong vùng nhớ scratchpad.
Chỉ có các bit từ bit thứ 11 đến bit thứ 4 (phần nguyên) của 2 thanh ghi nhiệt độ được dùng
để so sánh với giá trị lưu trong 2 thanh ghi TH và TL.
Nếu nhiệt độ đo thấp hơn hoặc bằng giá trị lưu trong thanh ghi TL hoặc cao hơn hoặc bằng
giá trị lưu trong thanh ghi TH thì cờ báo động quá nhiệt trong vi mạch DS18B20 sẽ lên 1. Cờ
Hình 6-16. Byte thanh ghi điều khiển của vi mạch DS18B20
Bảng 6-1. Độ phân giải và thời gian chuyển đổi
Hình 6-17. Lưu đồ các lệnh liên quan đến ROM của cảm biến DS18B20
Hình 6-18. Lưu đồ của các lệnh chức năng của DS18B20
Hình 6-19. Dạng sóng của xung reset và xung hiện diện
Khi DS18B20 gởi xung hiện diện để đáp ứng xung reset thì đồng thời xác định với thiết bị
chủ là cảm biến sẵn sàng hoạt động.
Trong quá trình khởi động thì thiết bị chủ (hoạt động ở chế độ phát TX) tạo xung reset bằng
cách kéo tín hiệu bus xuống mức thấp trong khoảng thời gian tối thiểu là 470µs. Sau đó thiết bị
chủ thả nỗi tín hiệu bus và hoạt động ở chế độ nhận (hoạt động ở chế độ nhận R X) để trao quyền
điều khiển cho cảm biến DS18B20.
Khi thả nỗi thì điện trở kéo lên sẽ kéo bus về mức logic 1. Khi DS18B20 phát hiện cạnh
lên của xung thì nó sẽ đợi từ 15µs đến 60µs và sau đó phát đi 1 xung hiện diện bằng cách kéo
bus xuống mức logic 0 trong khoảng thời gian từ 60µs đến 240µs.
6.5.14 Các khe thời gian đọc/ghi
Thiết bị chủ ghi dữ liệu vào DS18B20 trong các khe thời gian ghi và đọc dữ liệu từ
DS18B20 trong các khe thời gian đọc. Một bit dữ liệu được phát lên bus trong 1 khe thời gian.
Khe thời gian ghi
Có 2 loại khe thời gian ghi là: khe thời gian ghi mức 1 (ghi dữ liệu mức 1 vào DS18B20)
và khe thời gian ghi mức 0 (ghi dữ liệu mức 0 vào cảm biến DS18B20). Tất cả các khe thời gian
có lượng thời gian tối thiểu là 60µs và thời gian tín hiệu khôi phục lại từ mức 0 về mức 1 do
điện trở kéo lên tối thiểu là 1 µs.
Cả 2 khe thời gian ghi dữ liệu mức logic 1 và 0 đều được khởi động bởi thiết bị chủ kéo
bus xuống mức 0 như hình 6-20.
Để tạo ra khe thời ghi dữ liệu mức logic 1 thì sau khi phát xung kéo bus xuống mức 0 thì
thiết bị chủ phải thã nổi bus trong vòng 15µs. Khi thã nổi bus thì điện trở kéo lên sẽ kéo bus về
mức 1.
Để tạo ra khe thời ghi dữ liệu mức logic 0 thì sau khi phát xung kéo bus xuống mức 0 thì
thiết bị chủ tiếp tục giữ bus ở mức 0 trong suốt khe thời gian (ít nhất là 60µs).
DS18B20 sẽ lấy mẫu từ bus với các khoảng thời gian kéo dài từ 15µs đến 60µs sau khi
khởi động khe thời gian ghi.
Nếu bus ở mức cao trong suốt thời gian lấy mẫu thì mức 1 sẽ được ghi vào DS18B20, nếu
ở mức 0 thì mức 0 được ghi vào.
Khe thời gian đọc
Hình 6-21. Chi tiết dạng sóng khe thời gian đọc mức 1 của thiết bị chủ
DS18B20 truyền mức 1 bằng cách để bus trở về mức 1 và truyền mức 0 thì kéo bus ở luôn
mức 0. Khi đang truyền mức 0, DS18B20 sẽ thả nỗi bus khi gần kết thúc khe thời gian và bus
sẽ được kéo lên mức 1 bởi điện trở kéo lên.
150 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
Ngõ ra dữ liệu từ DS18B20 có hiệu lực trong vòng 15 µs tính từ khi có cạnh xuống của
xung khởi tạo khe thời gian đọc. Do đó thiết bị chủ phải thả nỗi bus và sau đó tiến hành lấy mẫu
trạng thái bus trong vòng 15 µs tính từ lúc bắt đầu khe thời gian.
Hình 6-21 minh họa tổng thời gian TINIT, TRC và TSAMPLE phải nhỏ hơn 15µs đối với khe
thời gian đọc.
Hình 6-22 minh họa các giới hạn thời gian lớn nhất bằng cách giữ TINIT và TRC càng nhỏ
có thể có và định vị thời gian lấy mẫu của thiết bị chủ trong khe thời gian đọc hướng về điểm
gần kết thúc chu kỳ khe thời gian.
touch_present();
touch_write_byte(skip_rom);
touch_write_byte(convert_t);
}
c. Hàm 606: Hàm đọc nhiệt độ từ DS18B20, trả về giá trị nhiệt 16 bit.
unsigned int16 ds18b20_read_temp()
{
unsigned int8 bl,bh;
unsigned int16 w;
touch_write_byte(skip_rom);
touch_write_byte(read_scratchpad);
bl = touch_read_byte();
bh = touch_read_byte();
152 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
w = make16(bh,bl);
touch_present();
touch_write_byte(skip_rom);
touch_write_byte(convert_t);
return w;
}
d. Hàm 607: Hàm đọc mã Rom của vi mạch DS18B20, hiển thị tại hàng x, cột y.
void ds18b20_doc_rom(usi8 x,y)
{
unsigned int8 rom_code[8];
unsigned int8 xh,xl;
signed int8 i;
if(touch_present())
{
touch_write_byte(read_rom);
for(i=0;i<8;i++)
rom_code[i] = touch_read_byte();
lcd_goto_xy(x,y);
for(i=7;i>-1;i--)
{
xh=rom_code[i]/16;
if(xh>9) xh=xh+0x37;
else xh=xh+0x30;
xl=rom_code[i]%16;
if(xl>9) xl=xl+0x37;
else xl=xl+0x30;
lcd_data(xh);
lcd_data(xl);
}
}
else ds18b20_no_ds18b();
}
Giải thích: Gọi hàm kiểm tra hiện diện, gửi lệnh đọc Rom rồi tiến hành đọc 8 byte mã.
Sau đó tiến hành hiển thị 8 byte trên LCD tại tọa độ (x,y).
void h617_ds18b20a_ht_lcd()
{
if(ds18a_ngt!=ds18a_ng)
{
ds18a_ngt=ds18a_ng;
lcd_gm_ht_2so_to_xvn(ds18a_ng,2,0,kx_vn);
lcd_data(".");
}
if(ds18a_tpt!=ds18a_tp)
{
ds18a_tpt=ds18a_tp;
lcd_gm_ht_4so_nho_xvn(ds18a_tp*625,3,7,kx_vn);
}
}
void h617_ds18b20a_ht_7doan()
{
led_7d[7]=0xff;
giaima_bin_2so_vitri_vn(ds18a_ng,5,kx_vn);
led_7d[4]=0x9c;
giaima_bin_2so_vitri_vn((ds18a_tp*625)/100,2,kx_vn);
xuat_8led_7doan();
}
void b617_ds18b20_doc_nhiet_do()
{
if(touch_present())
{
ds18a_w = ds18b20_read_temp();
ds18a_ng = ds18a_w>>4;
ds18a_tp = ds18a_w & 0x000f;
154 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
h617_ds18b20a_ht_lcd();
h617_ds18b20a_ht_7doan();
}
else ds18b20_no_ds18b();
}
d. Chương trình chính:
#include <tv_kit_vdk_18f6722_all.c>
#include <bai_617_ds18b20_tv.c>
void main()
{
set_up_port();
lcd_setup();
lcd_khoi_tao_cgram_so_to();
lcd_goto_xy(0,0);
lcd_data("DS18B20");
ds18b20_khoi_tao();
while(true)
{
b617_ds18b20_doc_nhiet_do();
so_sanh_nd_dk_buzzer(ds18a_ng);
delay_ms(200);
if(!input(bt3)) buzzer_off();
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: Sẽ hiển thị nhiệt độ môi trường và mở đèn để gia tăng nhiệt độ.
Hiển thị mã ROM của vi mạch DS18B20 trên LCD ở hàng 1 với byte cuối cùng là
28. Khi quá 34ºC thì đèn tắt, buzzer kêu, nhấn BT3 để tắt buzzer.
Hãy ghi lại mã ROM của vi mạch DS18b20 thứ nhất (A). Đảo 2 Jumper rồi cũng ghi
lại mã ROM của vi mạch DS18b20 thứ hai (B).
Bài tập 618. Giống bài 617 nhưng hiển thị thêm nhiệt độ so sánh trên và dưới ở cuối
hàng 2 và 3. Có thêm nút BT0 để chỉnh nhiệt độ so sánh trên tăng 1 đơn vị, trong phạm
vi +5 và cuộn tròn. Tương tự cho BT1 chỉnh nhiệt độ dưới.
Lưu tên file “bai_618_ds18b20_lcd_7doan_den_buz_rom_3bt”.
Bài tập 620. Tổng hợp các yêu cầu: thêm vào bài 615 yêu cầu thứ 4
Yêu cầu 4: Đo nhiệt độ dùng DS18B20 và hiển thị trên LCD và trên 8 led 7 đoạn.
Thêm nút nhấn BT0 để chọn yêu cầu thứ 4.
Lưu tên file “bai_620_tong_hop_lm35_joy_hcsr_gp2d12_ds18_btn”.
Bài tập 621. Giống bài 620 nhưng mỗi yêu cầu thực hiện trong 10 giây sau đó tự động
chuyển sang yêu cầu kế. Bắt đầu từ yêu cầu 1. Hiển thị đếm 10 giây ở vị trí nào còn trống
trên LCD hoặc ở led đơn.
Lưu tên file “bai_621_tong_hop_lm35_joy_hcsr_gp2d12_ds18_auto”.
Hình 6-26. Định dạng 5 byte của DHT11 gửi đến MCU
Không có tín hiệu bắt đầu từ MCU thì DHT11 sẽ không đưa ra tín hiệu phản hồi cho MCU.
Sau khi dữ liệu được thu thập thì DHT11 sẽ chuyển sang chế độ ngủ cho đến khi nhận
được tín hiệu bắt đầu từ MCU.
b. MCU gửi tín hiệu Start đến DHT11
Mức logic tự do của bus giao tiếp thường ở mức điện áp cao.
Khi giao tiếp giữa MCU và DHT11 bắt đầu, bên MCU sẽ điều khiển bus giao tiếp dữ liệu
từ mức ‘1’ xuống mức ‘0’ và kéo dài ít nhất 18ms để đảm bảo DHT11 phát hiện tín hiệu này
của MCU, sau đó MCU sẽ thả nỗi bus và “điện trở kéo lên” sẽ làm tín hiệu lên mức ‘1’ trong
khoảng 20-40µs, trong khoảng thời gian này MCU sẽ đợi đáp ứng từ DHT11. Xem hình 6-27.
Hình 6-27. Biểu đồ thời gian tín hiệu Start của MCU và đáp ứng của DHT11
c. DHT11 đáp ứng lại MCU
Khi DHT11 phát hiện tín hiệu bắt đầu, nó sẽ phản hồi bằng cách kéo tín hiệu bus từ ‘1’
xuống ‘0’, tín hiệu này kéo dài 80µs. Sau đó, DHT11 kéo bus lên mức ‘1’ và duy trì khoảng
80µs để chuẩn bị cho quá trình DHT gửi dữ liệu. Xem hình 7-28.
d. DHT11 gửi dữ liệu 40 bit cho MCU
Hình 6-28. Biểu đồ thời gian DHT11 gửi dữ liệu bit ‘0’
Nếu thời gian ở mức ‘1’ nằm trong khoảng 70µs thì xem như gửi bit ‘1’, hình 6-29.
Hình 6-29. Biểu đồ thời gian DHT11 gửi dữ liệu bit ‘1’
Thời gian DHT11 gửi bit ‘0’ và bit ‘1’ không đều nhau.
Hình 6-30. Biểu đồ thời gian của 1 chu kỳ giao tiếp giữa MCU và DHT11
Giải pháp cho MCU để biết mức dữ liệu bit ‘0’ và bit ‘1’: MCU sẽ đếm thời gian theo đơn
vị µs bắt đầu từ khi tín hiệu lên mức ‘1’ cho đến khi tín hiệu xuống mức ‘0’ thì ngừng đếm và
giả sử đếm được Cµs. Lấy C so sánh với M: nếu nhỏ hơn M thì xem như đó là bit ‘0’, ngược lại
là bit ‘1’. M có thể là 40 cho đến 60 đều được.
6.6.5 Thư viện của DHT11
160 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
Phần này trình bày các thư viện của DHT11.
a. Các định nghĩa: Các lệnh.
#define dht11_pin_low() output_drive(dht11); output_low(dht11)
#define dht11_pin_high() output_drive(dht11); output_high(dht11)
#define dht11_pin_float() output_float(dht11)
#define dht11_pin_read() input_state(dht11)
Giải thích: Định nghĩa các lệnh để điều khiển chân giao tiếp của vi điều khiển với DHT11.
b. Hàm 608: Tạo trạng thái “start”.
void dht11_start()
{
dht11_pin_low();
delay_ms(18);
dht11_pin_high();
dht11_pin_float();
delay_us(40);
}
c. Hàm 609: Kiểm tra đáp ứng từ DHT11.
int1 dht11_check_response()
{
unsigned int8 cnt=0;
int1 tt=1, tt1=1;
do
{
if(dht11_pin_read()==0) cnt++;
else tt=0;
}while ((cnt<200)&&(tt==1));
cnt=0; tt1=1;
do
{
if(dht11_pin_read()==1) cnt++;
else tt1=0;
}while ((cnt<200)&&(tt1==1));
return tt;
}
Giải thích: Hàm có 2 vòng lặp do while.
Vòng lặp thứ nhất chờ bus lên mức 1: hàm chỉ thoát khi bus giao tiếp lên mức 1
thì xem như có DHT11 hoặc khi biến đếm cnt bằng 200 thì xem như không có
DHT11.
Vòng lặp thứ hai chờ bus xuống mức 0: hàm chỉ thoát khi bus giao tiếp xuống mức
0 thì xem như có DHT11 hoặc khi biến đếm cnt bằng 200 thì xem như không có
DHT11.
Bài mẫu 622. Chương trình đọc nhiệt độ và độ ẩm từ vi mạch DHT11 hiển thị trên led
7 đoạn và LCD.
Lưu tên file “bai_622_dht11_lcd_7doan”.
void h617_ds18b20a_ht_lcd()
{
if(ds18a_ngt!=ds18a_ng)
{
ds18a_ngt=ds18a_ng;
lcd_gm_ht_2so_to_xvn(ds18a_ng,2,0,kx_vn);
lcd_data(".");
}
if(ds18a_tpt!=ds18a_tp)
{
ds18a_tpt=ds18a_tp;
lcd_gm_ht_4so_nho_xvn(ds18a_tp*625,3,7,kx_vn);
}
}
void h617_ds18b20a_ht_7doan()
{
led_7d[7]=0xff;
giaima_bin_2so_vitri_vn(ds18a_ng,5,kx_vn);
led_7d[4]=0x9c;
giaima_bin_2so_vitri_vn((ds18a_tp*625)/100,2,kx_vn);
xuat_8led_7doan();
}
void b617_ds18b20_doc_nhiet_do()
{
if(touch_present())
{
ds18a_w = ds18b20_read_temp();
ds18a_ng = ds18a_w>>4;
ds18a_tp = ds18a_w & 0x000f;
h617_ds18b20a_ht_lcd();
h617_ds18b20a_ht_7doan();
}
else ds18b20_no_ds18b();
}
d. Chương trình chính:
Thực hành vi điều khiển PIC 163
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
#include <tv_kit_vdk_18f6722_all.c>
#include <bai_622_dht11_tv.c>
void main()
{
set_up_port();
lcd_setup();
lcd_khoi_tao_cgram_so_to();
lcd_goto_xy(0,1);
lcd_data("HUMI");
lcd_goto_xy(0,8);
lcd_data("DHT11");
lcd_goto_xy(0,15);
lcd_data("TEMP");
lcd_goto_xy(1,7);
lcd_data("CHECK");
lcd_goto_xy(2,9);
lcd_data("SUM");
while(true)
{
b621_dht11_read_temp_humi();
delay_ms(200);
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: Giá trị độ ẩm và nhiệt độ sẽ hiển thị trên 6 led chính giữa của
module 8 led và 5 byte đọc về cùng byte tính toán để so sánh hiện thị trên LCD.
Bài tập 623. Tổng hợp các yêu cầu: thêm vào bài 619 yêu cầu thứ 5
Yêu cầu 5: Đo nhiệt độ và độ ẩm dùng DHT11 hiển thị trên LCD và led 7 đoạn.
Dùng nút nhấn BT0 làm nút UP và BT1 làm nút DW để chọn 5 yêu cầu.
Lưu tên file “bai_623_th_lm35_joy_hcsr_gp2d12_ds18_dht11_btn”.
Bài tập 624. Giống bài 620 nhưng mỗi yêu cầu thực hiện trong 10 giây sau đó tự động
chuyển sang yêu cầu kế. Bắt đầu từ yêu cầu 1. Hiển thị đếm 10 giây ở vị trí nào còn trống
trên LCD hoặc ở led đơn.
Lưu tên file “bai_624_th_lm35_joy_hcsr_gp2d12_ds18_dht11_auto”.
Hình 6-33. Biểu đồ thời gian một chu kỳ chuyển đổi của HX711
Khi dữ liệu ra chưa sẵn sàng cho trao đổi thì chân DOUT ở mức 1. Chân SCK sẽ mức 0.
Khi chân DOUT về mức 0 thì có nghĩa là dữ liệu đã sẵn sàng.
Bằng cách cấp từ 25 đến 27 xung ở chân SCK thì dữ liệu sẽ dịch ra từ chân DOUT.
Mỗi xung SCK thì dịch 1 bit dữ liệu và bắt đầu với bit đầu tiên là MSB và truyền cho hết
24 bit. Ở xung SCK thứ 25 thì chân DOUT sẽ trở lại mức 1.
Dạng sóng hoạt động của mạch như hình 6-33.
Bảng các thông số thời gian của SCK và DOUT.
Bảng 6-6. Thông số thời gian của SCK và DOUT
Thứ Ký Chú ý Tối Trung Tối Đơn
tự hiệu thiểu bình đa vị
1. T1 DOUT ở mức 0 đến khi có cạnh lên 0.1 µs
của SCK
2. T2 Cạnh lên của DOUT 0.1 µs
3. T3 Thời gian SCK ở mức 1 0.2 1 50 µs
4. T4 Thời gian SCK ở mức 0 0.2 1 µs
Lựa chọn hệ số KĐ và kênh ngõ vào thì được điều khiển bởi số lượng xung SCK, hãy xem
bảng 3. Khi số lượng xung SCK không được nhỏ hơn 25 và nhiều hơn 27 nằm trong một chu kỳ
chuyển đổi để tránh gây ra lỗi truyền dữ liệu nối tiếp.
Bảng 6-7. Thông số số lượng xung lựa chọn hệ số khuếch đại
Thứ tự Số lượng xung SCK Kênh ngõ vào Hệ số KĐ
1. 25 A 128
2. 26 B 32
Hình 6-34. Biểu đồ thời gian vào chế độ ngủ của HX711
Khi đó mạch nguồn ổn áp bên trong chip được dùng cho HX711 và chuyển đổi bên ngoài
sẽ chuyển sang chế độ công suất thấp.
Khi SCK trở lại mức 0 thì chip sẽ được reset và trở lại chế độ hoạt động bình thường.
Sau khi reset hoặc sau khi thoát khỏi chế độ ngủ thì ngõ vào mặc nhiên được chọn là kênh
A và hệ số KĐ là 128.
6.7.6 Các đặc tính điện quan trọng của HX711
Để sử dụng HX711 thì phải tham khảo bảng các đặc tính điện quan trọng.
Bảng 6-8. Các đặc tính điện quan trọng của HX711
Thứ Thông số Chú ý Tối thiểu Trung bình Tối đa Đơn
tự vị
1. Dãy điện áp ngõ V(imp) – ±0.5 (AVDD/GAIN) V
vào vi sai toàn V(inn)
giai đo
2. Ngõ vào ở chế AGND+1.2 AGND-1.3 V
độ chung
3. Tốc độ dữ liệu Dao động nội, 10 HZ
ngõ ra RATE = 0
4. Dao động nội, 80 HZ
RATE = 1
Hình 6-38. Kết nối cảm biến Load-cell với module HX711
Giá trị điện trở thay đổi rất nhỏ hàng µV nên cần phải có mạch khuếch đại thật tốt và ổn
định và mạch ADC với độ phân giải cao 24 bit để chuyển đổi. Module Hx711 chuyên dùng để
đáp ứng công việc này.
6.7.9 Kết nối cảm biến Load-cell với module HX711
//xuat_32led_don_1dw(kq);
kq = (8262712-kq)/180;
if(kq<0) kq = 0;
return(kq);
}
Giải thích: Hàm được viết dựa vào dạng sóng đã trình bày ở trên.
Cho tín hiệu hx_ck xuống mức 0, chờ tín hiệu hx_dt xuống mức 0.
Thực hiện vòng lặp for 24 lần để đọc 24 bit.
Đưa xung hx_ck về mức 1. Đưa xung hx_ck về mức 0.
Có nghĩa là tạo xung thứ 25. Cuối cùng là cân chỉnh kết quả theo quả cân mẫu.
Hằng số chia 8262712 và 180 tùy thuộc vào từng loại load-cell khác nhau.
6.7.11 Các chương trình đo khối lượng dùng cảm biến Load-cell và HX711
Phần này thực hành các bài cân khối lượng dùng cảm biến Load-cell và module HX711.
dht11_start();
presence = dht11_check_response();
if(!presence==true)
{
hum_bh = dht11_read();
hum_bl = dht11_read();
tem_bh = dht11_read();
tem_bl = dht11_read();
sum = dht11_read();
sum_ss = hum_bh+hum_bl+tem_bh+tem_bl;
if(sum==sum_ss)
{
giaima_bin_2so_vitri_vn(hum_BH,5,kx_vn);
led_7d[4]=0xbf;
led_7d[3]=0xbf;
giaima_bin_2so_vitri_vn(tem_bh,1,cx_vn);
xuat_8led_7doan();
if(hum_bht!=hum_bh)
{
hum_bht=hum_bh;
lcd_gm_ht_2so_to_xvn(hum_bh,1,0,kx_vn);
}
if(tem_bht!=tem_bh)
{
tem_bht=tem_bh;
lcd_gm_ht_2so_to_xvn(tem_bh,1,14,kx_vn);
}
lcd_hthi_byte(hum_bh,3,0);
lcd_hthi_byte(hum_bl,3,3);
lcd_goto_xy(3,15);lcd_data("(");
lcd_hthi_byte(sum_ss,3,16);
lcd_goto_xy(3,18);lcd_data(")");
}
else hien_thi_sai_dht11();
}
else hien_thi_no_dht11();
}
d. Chương trình chính:
#include <tv_kit_vdk_18f6722_all.c>
#include <bai_625_hx711_tv.c>
void main()
{
set_up_port();
lcd_setup();
lcd_khoi_tao_cgram_so_to();
lcd_goto_xy(0,0);
lcd_data("HX711: LOAD-CELL");
while(true)
{
b625_hx711_read();
b625_hx711_hien_thi();
b625_joystick_ht_7doan();
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: Nếu chưa cân chỉnh thì tiến hành cân chỉnh, nếu đã cân chỉnh thì
khi chưa có vật cần cân thì hiển thị số 0. Khi có vật thì sẽ hiển thị đúng khối lượng
vật cần cân. Có thể có sai số và có thể dao động xung quanh giá trị đo.
Bài tập 626. Giống bài 625 nhưng dùng thêm các nút nhấn UP và DW để cân chỉnh
giá trị chuẩn và hiển thị giá trị cân chỉnh trên LCD.
Lưu tên file “bai_626_hx711_lcd_7doan_load_cell_btn”.
Bài tập 628. Tổng hợp các yêu cầu: thêm vào bài 622 yêu cầu thứ 6
Yêu cầu 6: Đo khối lượng hiển thị trên LCD và led 7 đoạn.
Lưu tên file “bai_628_tong_hop_7cb_btn”.
Bài tập 629. Giống bài 628 nhưng mỗi yêu cầu thực hiện trong 10 giây sau đó tự động
chuyển sang yêu cầu kế. Bắt đầu từ yêu cầu 1. Hiển thị đếm 10 giây ở vị trí nào còn trống
trên LCD hoặc ở led đơn.
Lưu tên file “bai_629_tong_hop_7cb_auto”.
Bài mẫu 702. Giống bài 801 nhưng thêm phần hiển thị số bước trên 8 led 7 đoạn. Nếu
quay bước đủ thì 1 vòng là 200 bước.
Lưu tên file là “bai_702_step_motor_on_off_inv_hthi_sb”
a. Mục đích: Biết điều khiển động cơ bước bằng 3 nút nhấn và hiển thị số bước.
b. Lưu đồ, giải thuật: Giống bài 701, chỉ thêm phần hiển thị số bước. Mỗi lần quay một
bước thì tăng số bước lên 1 rồi giải mã hiển thị.
c. Chương trình:
#include <tv_kit_vdk_18f4550_all.c>
#include <tv_08_step_motor.c>
#include <bai_801_step_motor_on_off_inv_tv.c>
unsigned int16 sb;
void hthi_sobuoc_7doan()
{
md4l7d_giaima_4so_vitri_vn(sb,3,cx_vn);
xuat_4led_7doan_4so();
}
void main()
{
set_up_port_ic_chot();
stepmotor_delay=20;
stepmotor_tn = 1;
stepmotor_fh = 1;
sb=0;
hthi_sobuoc_7doan();
while(true)
{
step_motor_on_off_inv();
Bài tập 703. Hãy viết chương trình điều khiển động cơ bước giống bài 704 nhưng 3
led 7 đoạn (2,1,0) hiển thị số bước của 1 vòng, 2 led (5,4) còn lại hiển thị số vòng.
Lưu tên file là “bai_703_step_motor_on_off_inv_hthi_sb_sv”
Bài tập 704. Hãy viết chương trình điều khiển động cơ bước có thể thay đổi tốc độ
bằng 3 nút điều khiển: UP, DW, INV, STOP.
Khi nhấn UP thì động cơ quay và tăng tốc.
Khi nhấn DW thì động cơ quay và giảm tốc.
Chiều quay tùy thuộc vào phím INV.
Có 3 led 7 đoạn (2,1,0) hiển thị số bước, 2 led (5,4) hiển thị thời gian delay, led 7 hiển
thị số cấp từ 0 đến 9. Cấp 0 thì ngừng. Cấp 1 đến cấp 9: tương ứng với các khoảng thời
gian delay: 45, 40, 35, 30, 25, 20, 15, 10, 5 ms.
Lưu tên file là “bai_704_step_motor_up_dw_inv_stop_sb_sc_tg”
Bài tập 705. Hãy viết chương trình điều khiển động cơ quay theo số vòng được đặt
trước dùng bàn phím cảm ứng, dùng các phím số từ 0 đến 9 để nhập số vòng, để đơn giản
chỉ nhập 1 con số hiển thị ở 1 led 7 đoạn. Nhấn phím D thì động cơ quay thuận và số
vòng giảm dần đến khi bằng 0 thì ngừng. Khi chạy thì không cho phép nhập.
Lưu tên file là “bai_705_step_motor_touch_1so”
Bài tập 706. Hãy mở rộng bài trên là nhập được 2 số và thêm phím E cho phép chạy
ngược.
Lưu tên file là “bai_706_step_motor_touch_2so”
Bài tập 707. Điều khiển động cơ bước quay thuận hoặc ngược bằng cách dùng bộ mã
hóa xoay vòng (RT). Ban đầu sau khi nạp hoặc cấp điện hoặc bị reset thì hiển thị cấp 0.
Khi xoay phải RT thì động cơ quay thuận tăng tốc dần đến tối đa là +9 là lớn nhất.
Xoay ngược về từ +9 đến 0 thì động cơ giảm tốc dần cho đến khi bằng 0 thì ngừng.
186 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
Khi xoay trái RT thì động cơ quay ngược tăng tốc dần đến tối đa là -9 là lớn nhất. Xoay
ngược về từ -9 đến 0 thì động cơ giảm tốc dần cho đến khi bằng 0 thì ngừng.
Dùng thêm nút nhấn của RT làm nút Stop: khi nhấn thì động cơ ngừng.
Số cấp điều khiển hiển thị trên 1 led 7 đoạn. Thời gian delay giống bài trên hiển thị
trên 2 led 7 đoạn.
Có 8 led đơn bên trái báo trạng thái ngừng: tắt, chạy: sáng. Quay thuận: 8 led sáng, 8
led tắt, quay ngược: 8 led tắt, 8 led sáng của 16 led bên trái.
Lưu tên file là “bai_707_step_motor_tn_td_rotary”
Bài tập 708. Hãy hiệu chỉnh lại bài 703 thêm BT3 để chọn khiển động cơ quay bước
đủ hay nữa bước, ban đầu quay bước đủ.
Lưu tên file là “bai_703_step_motor_on_off_inv_hthi_sb_sv_fh_bt3”
Bài tập 712. Hãy viết chương trình điều khiển động cơ DC gồm nút nhấn ON và OFF,
kết hợp bài đếm giây chính xác hiển thị trên 2 led 7 đoạn. Khi nhấn ON và giây nằm trong
khoảng từ 05 đến 25 thì động cơ quay thuận, từ 35 đến đến 55 thì quay nghịch, các khoảng
còn lại thì động cơ ngừng. Khi nhấn OFF thì động cơ ngừng.
Lưu tên file là “bai_712_dc_motor_on_off_tn_theo_giay”.
Bài tập 713. Hãy viết chương trình điều khiển động cơ bước và DC gồm 3 nút nhấn
ON, OFF và INV. Khi nhấn ON thì cả 2 động cơ quay thuận. Nhấn INV thì cả 2 đảo
chiều. Khi nhấn OFF thì cả 2 động cơ ngừng. Chính là kết hợp bài 701 và 711.
Lưu tên file là “bai_713_step_dc_motor_on_off_inv”.
Chỉ biết được TOSC 50 ns còn các thông số PR 2, PVTMR2 thì chưa biết.
Phải chọn 1 thông số và tính thông số còn lại: chú ý PR 2 có giá trị 8 bit từ 0 đến 255, còn
PVTMR 2 có 3 giá trị là chia 1, chia 4 và chia 16.
Bài mẫu 715. Chương trình dùng CCP1 ở chế độ PWM để điều khiển động cơ quay
thuận thay đổi tốc độ bằng 2 nút điều khiển: UP, DW và nút STOP.
Khi nhấn UP thì động cơ quay thuận và tăng tốc lên, khi nhấn DW thì động cơ giảm
tốc, nhấn STOP thì ngừng. Số cấp điều khiển là 50 hiển thị trên 2 led 7 đoạn. Sử dụng
các thông số tính toán ở trên.
Lưu tên file là “bai_715_dc_motor_pwm_ccp1_up_dw_stop”.
Mục đích: Biết lập trình sử dụng CCP1 điều khiển động cơ DC quay thuận thay đổi
a.
tốc độ.
b. Lưu đồ, giải thuật: Khởi tạo CCP1, số cấp ban đầu bằng 0, tính toán và thiết lập hệ
số PWM theo số cấp để điều khiển ĐCDC quay thuận. Kiểm tra nếu nhấn UP thì tăng
số cấp, nhấn phím DW thì giảm số cấp, nhấn STOP thì số cấp bằng 0. Giải mã hiển
thị số cấp và giá trị PWM trên led 7 đoạn.
c. Chương trình con “bai_715_dc_motor_pwm_ccp1_tv”:
void hien_thi_7doan()
{
giaima_bin_4so_vitri_vn(pwm_duty,0,cx_vn);
giaima_bin_2so_vitri_vn(pwm_capso,5,cx_vn);
led_7d[4] = 0xbf;
xuat_8led_7doan();
}
void phim_up()
{
if(phim_up_c2(150)&&(pwm_duty<1000))
{
pwm_duty= pwm_duty+50;
set_pwm1_duty(pwm_duty);
pwm_capso++;
hien_thi_7doan();
}
}
void phim_dw()
{
if(phim_dw_c2(150)&&(pwm_duty>0))
{
pwm_duty= pwm_duty-50;
pwm_capso--;
hien_thi_7doan();
void phim_stop()
{
if(!input(stop))
{
pwm_duty=0;
pwm_capso=0;
hien_thi_7doan();
set_pwm1_duty(pwm_duty);
}
}
d. Chương trình chính
#include <tv_kit_vdk_18f6722_all.c>
#include <tv_07_18f6722_dc_motor.c>
signed int8 pwm_capso;
#include <bai_715_dc_motor_pwm_ccp1_tv.c>
void main()
{
set_up_port();
setup_ccp1(ccp_pwm);
setup_timer_2(t2_div_by_16,249,1);
pwm_duty=0; pwm_capso=0;
hien_thi_7doan();
while(true)
{
phim_dw(); phim_up(); phim_stop();
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: sau khi nạp xong thì nhấn nút UP động cơ sẽ tăng tốc, nhấn DW
thì giảm tốc, nhấn STOP thì động cơ ngừng. Chú ý: khi ở cấp tốc độ 1 hoặc 2 thì
moment chưa đủ làm động cơ quay nên ta tiếp tục tăng cấp cho đến khi đủ moment
quay động cơ. Có led hiển thị các cấp tốc độ.
Bài tập 716. Hãy lấy kết quả tính toán ở trên và lập trình theo yêu cầu.
Nút nhấn BT0 làm nút stop để ngừng động cơ.
Nút nhấn BT1 thì điều khiển động cơ chạy 35% tốc độ tối đa.
Nút nhấn BT2 thì điều khiển động cơ chạy 70% tốc độ tối đa.
Nút nhấn BT3 thì điều khiển động cơ chạy 100% tốc độ tối đa.
Hiển thị số cấp và giá trị PWM trên led 7 đoạn.
Thực hành vi điều khiển PIC 195
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
Lưu tên file là “bai_716_dc_pwm_ccp1_3_cap_tocdo”.
Bài tập 717. Chương trình điều khiển động DC có 2 nút: UP, DW.
Khi nhấn UP và giữ thì động cơ quay thuận và tự động tăng tốc lên cho đến khi cực
đại và nếu nhã thì động cơ ngừng.
Khi nhấn DW và giữ thì động cơ quay nghịch và tự động tăng tốc lên cho đến khi cực
đại và nếu nhã thì động cơ ngừng.
Số cấp điều khiển là 50 hiển thị trên 2 led 7 đoạn. Giá trị PWM hiển thị trên 4 led 7
đoạn. Sử dụng các thông số tính toán ở trên
Có 8 led đơn bên trái báo trạng thái ngừng: tắt, chạy: sáng. Quay thuận: 8 led sáng, 8
led tắt, quay ngược: 8 led tắt, 8 led sáng của 16 led bên trái.
Lưu tên file là “bai_717_dc_motor_up_dw_stop_auto”.
Mục đích: Biết lập trình điều khiển động cơ thay đổi tốc độ theo PWM, sử dụng CCP1
a.
và CCP2 để điều khiển thay đổi tốc độ theo cả 2 chiều.
b. Lưu đồ, giải thuật: Số cấp ban đầu bằng 0. Kiểm tra nếu nhấn và giữ phím UP thì mở
CCP1: tăng số cấp, tính toán và thiết lập hệ số PWM theo số cấp để điều khiển ĐCDC
quay thuận, delay và lặp lại. Nếu không còn nhấn UP thì cho số cấp bằng 0, tắt CCP1,
động cơ ngừng.
Tương tự nếu nhấn và giữ phím DW thì mở CCP2: tăng số cấp, tính toán và thiết
lập hệ số PWM theo số cấp để điều khiển ĐCDC quay nghịch, delay và lặp lại. Nếu
không còn nhấn DW thì cho số cấp bằng 0, tắt CCP1, động cơ ngừng
c. Chương trình con “”:
signed int8 pwm_capso;
void hien_thi_7doan()
{
giaima_bin_4so_vitri_vn(pwm_duty,0,cx_vn);
giaima_bin_2so_vitri_vn(pwm_capso,5,cx_vn);
led_7d[4] = 0xbf;
xuat_8led_7doan();
}
void motor_dc_stop()
{
pwm_capso=0;
dc_motor_pwm_ccp1_ccp2_stop();
hien_thi_7doan();
xuat_32led_don_2word(0,0);
}
void phim_up()
{
if(pwm_capso<50)
void phim_dw()
{
if(pwm_capso<50)
{
dcmotor_tn=0;
dc_motor_ktao_ccpx();
pwm_duty= pwm_duty+20;
dc_motor_set_pwmx_duty();
pwm_capso++;
hien_thi_7doan();
xuat_32led_don_2word(0xffff,0);
}
}
d. Chương trình chính:
#include <tv_kit_vdk_18f6722_all.c>
#include <tv_07_18f6722_dc_motor.c>
#include <bai_717_dc_motor_up_dw_stop_auto_tv.c>
void main()
{
set_up_port();
setup_timer_2(t2_div_by_16,249,1);
pwm_duty=0; pwm_capso=0;
hien_thi_7doan();
led_7d[4] = 0xbf;
while(true)
{
if(phim_up_c2(1)==co_nhan)
phim_up();
else if(phim_dw_c2(1)==co_nhan)
phim_dw();
else motor_dc_stop();
delay_ms(50);
Bài tập 718. Giống bài 717 nhưng khi nhả phím thì số cấp giảm dần giống như lúc tăng
khi nhấn dùng delay 50ms. Mục đích để khi nhả phím thì giảm tốc và khi nhấn thì tăng
trở lại ngay từ cấp đang chạy.
Lưu tên file là “bai_718_dc_motor_up_dw_stop_slow_auto”.
Bài tập 719. Giống bài 717 nhưng dùng bộ mã hóa xoay vòng (RT). Ban đầu sau khi
nạp hoặc cấp điện hoặc bị reset thì hiển thị cấp 0.
Khi xoay phải RT thì động cơ quay thuận tăng tốc dần đến tối đa là +20 là lớn nhất.
Xoay ngược về từ +20 đến 0 thì động cơ giảm tốc dần cho đến khi bằng 0 thì ngừng.
Khi xoay trái RT thì động cơ quay ngược tăng tốc dần đến tối đa là -20 là lớn nhất.
Xoay ngược về từ -20 đến 0 thì động cơ giảm tốc dần cho đến khi bằng 0 thì ngừng.
Dùng thêm nút nhấn của RT làm nút Stop: khi nhấn thì động cơ ngừng.
Lưu tên file là “bai_719_dc_motor_up_dw_stop_auto_rotary”.
Bài tập 720. Giống bài 715 nhưng thay đổi tốc độ động cơ 10 cấp từ 0 đến 9 được chọn
bằng 10 nút nhấn từ 0 đến 9 của bàn phím cảm ứng. Chọn chiều quay thuận hay nghịch
bằng phím A, ngừng là phím B.
Lưu tên file là “bai_720_dc_motor_up_dw_stop_touch”.
Hình 7-9. Hệ thống điều khiển vòng kín của động cơ Servo
Động cơ servo RC hoạt động trên cùng một nguyên tắc. Gồm một động cơ DC nhỏ được
kết nối với trục đầu ra thông qua các bánh răng. Trục đầu ra dẫn động một cánh tay servo và
cũng được kết nối với một chiết áp (nồi - Pot). Xem hình 7-10.
Hình 7-10. Các trục và bánh răng bên trong của động cơ Servo
Chiết áp cung cấp phản hồi vị trí cho bộ điều khiển servo nơi vị trí hiện tại của động cơ
được so sánh với vị trí đích. Khi có chênh lệch thì bộ phận điều khiển sẽ hiệu chỉnh lại vị trí
thực của động cơ sao cho khớp với vị trí mục tiêu.
7.4.2 Nguyên lý hoạt động của động cơ Servo
Có thể điều khiển động cơ servo bằng cách gửi một loạt xung đến đường tín hiệu.
Một động cơ servo tương tự thường nhận xung có chu kỳ khoảng 20 mili giây một lần (hay
tần số là 50Hz). Độ dài của xung xác định vị trí của động cơ servo. Xem hình 7-11.
Bài mẫu 721. Chương trình điều khiển động servo bằng 3 nút: BT0, BT1 và BT2.
Khi nhấn BT0 thì làm động cơ quay về góc 0 độ.
Khi nhấn BT1 thì làm động cơ quay trái lệch một góc 90 độ.
Khi nhấn BT2 thì làm động cơ quay trái lệch một góc 180 độ.
Lưu tên file là “bai_721_dc_servo_3btn”.
a. Mục đích: Biết lập trình điều khiển động cơ servo quay 3 vị trí bằng 3 nút nhấn.
b. Lưu đồ giải thuật: Ba nút nhấn có chức năng nạp 3 thời hằng tương ứng 3 góc quay.
Chương trình chính có chức năng tạo xung có tần số 50Hz với xung PWM theo thời
hằng đã nạp.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
unsigned int16 servo_pwm;
unsigned int16 i;
void phim_servo_goc_0()
{
if(phim_bt0_c1(1,1))
{
servo_pwm=1000;
xuat_32led_don_1dw(0xf);
}
}
void phim_servo_goc_90()
{
if(phim_bt2_c1(1,1))
{
servo_pwm=1850;
xuat_32led_don_1dw(0xf0);
}
}
void phim_servo_goc_180()
{
if(phim_bt1_c1(1,1))
{
servo_pwm=3710;
xuat_32led_don_1dw(0xf00);
Thực hành vi điều khiển PIC 201
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
}
}
void main()
{
set_up_port();
output_low(servo2);
servo_pwm=1000;
xuat_32led_don_1dw(0xf);
while(true)
{
quay_servo(servo_pwm);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Sau khi nạp xong thì vi điều khiển sẽ đưa động cơ về tọa độ góc 0
độ. Nhấn BT1 để quay 90 độ. Nhấn BT0 để về góc 0 độ. Nhấn BT2 để quay 180 độ.
Nhấn BT0 để về 0 độ là đúng yêu cầu.
f. Sai lệch so với lý thuyết: Chương trình trên thì quay góc 0 độ với độ rộng xung 1ms
là chính xác. Còn góc 90 độ thì xung 1,85 ms và góc 180 độ thì không đạt được, chỉ
đạt được khoảng 150 độ.
Bài tập 723. Hãy viết chương trình điều khiển 2 động cơ: DC và bước bằng 3 nút: UP,
DW, OFF.
#int_timer3
void interrupt_timer3()
{
set_timer3(3036); refresh = 1;
}
void tinh_3heso_duty()
{
xung = get_timer1();
set_timer1(0);
e = xungdat - xung;
tp = e;
td = (e-ecu)*10;
ti = ti+e*0.1;
ecu = e;
duty = duty + kp*tp + kd*td + ki*ti;
void phim_up()
{
if(!input(up)&&(xungdat<300))
{
delay_ms(20);
if(!input(up))
{
xungdat= xungdat+10; tocdo++;
lcd_gm_ht_2so_nho_xvn(tocdo,0,18,cx_vn);
delay_ms(200);
}
enable_interrupts(int_timer3);
}
}
void phim_dw()
{
if(!input(dw)&&(xungdat>0))
{
delay_ms(20);
if(!input(dw))
{
xungdat= xungdat-10; tocdo--;
lcd_gm_ht_2so_nho_xvn(tocdo,0,18,cx_vn);
delay_ms(200);
}
}
}
void main()
{
set_up_port();
lcd_setup();
lcd_goto_xy(0,0);
lcd_data("cap toc do:");
lcd_goto_xy(1,0);
lcd_data("toc do dco-rpm:");
lcd_goto_xy(2,0);
lcd_data("xung dat: ");
lcd_goto_xy(3,0);
lcd_data("xung dem: ");
204 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
setup_ccp1(ccp_pwm);
setup_timer_2(t2_div_by_16,249,1);
tocdo=0; duty=0;
setup_timer_1(t1_external_sync|t1_div_by_1);
set_timer1(0);
enable_interrupts(global);
enable_interrupts(int_timer3);
setup_timer_3(t3_internal|t3_div_by_8);
set_timer3(3036);
refresh = 1;
lcd_gm_ht_2so_nho_xvn(tocdo,0,18,cx_vn);
while(true)
{
phim_dw(); phim_up();
if(refresh) tinh_3heso_duty();
if(!input(stop))
{
disable_interrupts(int_timer3);
duty=0;
set_timer1(0);
tocdo=0;
xungdat =0;
xung =0;
lcd_gm_ht_2so_nho_xvn(tocdo,0,18,cx_vn);
set_pwm1_duty(0);
}
t1=(xung*40)/3;
lcd_gm_ht_4so_nho_xvn(t1,1,16,cx_vn);
lcd_gm_ht_3so_nho_xvn(xungdat,2,17,cx_vn);
lcd_gm_ht_3so_nho_xvn(xung,3,17,cx_vn);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: hàng 1 hiển thị cấp tốc độ, hàng 2 hiển thị tốc độ động cơ, hàng 3
hiển thị số xung cài đặt trước, hàng 4 hiển thị số xung đếm được từ encoder. Sau khi
nạp xong chương trình thì nhấn nút UP để tăng giá trị xung cái đặt lên 10 đơn vị,
động cơ sẽ chạy ổn định khi giá trị cài đặt là 30, hệ thống sẽ tự động điều chỉnh tốc
độ thực gần đúng với tốc độ cài.
f. Giải thích chương trình: trong chương trình sử dụng timer T1 đếm xung từ encoder,
sử dụng timer T3 làm bộ định thời đếm 100ms báo ngắt. Khi được 100ms thì đọc giá
trị của counter T1 rồi xóa giá trị của counter T1. Lấy giá trị vừa đọc tính toán sai lệch
Thực hành vi điều khiển PIC 205
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
giữa xung cài và xung đếm, tín hằng số tỷ lệ, hằng số vi phân, hằng số tích phân, cập
nhật lại giá trị và tính toán lại hệ số duty để thay đổi tốc độ động cơ cho phù hợp đúng
với giá trị cài đặt. Giới hạn cho hệ số duty là từ 0 đến 1000, giá trị 1000 tương ứng
với số xung cài đặt lớn nhất là 300. Tốc độ động cơ được tính toán bằng số xung đếm
được trong vòng 100ms nhân với 10 để được 1 giây, nhân tiếp với 60 để được 1 giây
rồi chia cho số xung của 1 vòng là 45 sẽ được tốc độ động cơ là số vòng trên phút.
Đơn giản 2 hệ số cho 15 nên phương trình còn lại là nhân 40 chia 3.
Để thấy được sự ổn định thì phải có tải thay đổi nhưng trong bộ thí nghiệm không có
kéo tải nên khó nhìn thấy chức năng của PID.
Hình 8-1. Sơ đồ nguyên lý giao tiếp vi điều khiển với 3 led ma trận
Kit có tích hợp module giao tiếp 3 led ma trận 2 màu xanh và đỏ, sử dụng 4 IC thanh ghi
dịch 16 bit để điều khiển hàng và cột.
Với 3 led ma trận 8×8 có 24 cột, mỗi ký tự 6 byte nên có thể hiển thị được 4 kí tự, việc
copy dữ liệu sẽ được chia ra cho từng ký tự độc lập để dễ điều khiển.
8.2.3 Các chương trình led ma trận quét hàng
Bài mẫu 801. Chương trình điều khiển LED ma trận hiển thị chữ abcd màu xanh theo
phương pháp quét hàng.
Lưu tên file là “bai_801_mtqh_abcd_xanh”
Mục đích: Biết cách điều khiển led quét hàng.
a.
Lưu đồ, giải thuật: Lấy số lượng ký tự của chuỗi cần hiển thị. Lấy mã ma trận cho
b.
từng ký tự lưu vào vùng nhớ hiển thị. Lấy từng bit thứ 0 của từng cột dữ liệu và lấy
đủ 24 cột tùy theo màu xanh và 24 bit cho màu đỏ. Gửi dữ liệu 48 bit đó (tương đương
3 word) cùng với word mã quét hàng ra 4 IC MBI. Kết quả hàng thứ 0 sáng. Làm
tương tự cho hàng thứ 1, 2, … cho đến hàng thứ 7 là kết thúc 1 chu kỳ quét hàng. Lặp
lại, kết quả ta nhìn thấy 4 ký tự sáng.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
const unsigned char chuoi_hthi[]={"ABCD"};
#include <tv_08_matran_led_qhang.c>
#define ck_quet 100
#define vt_quet 24
void main()
{
set_up_port();
lay_so_luong_ky_tu_chuoi();
lay_ma_ky_tu(slkt);
while(true)
{
ma_tran_quet_hang(ck_quet,vt_quet,mau_xanh);
ma_tran_quet_hang(ck_quet,vt_quet,mau_do);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: LED ma trận sáng chuỗi abcd rõ đẹp hơn so với quét cột.
Bài mẫu 803. Chương trình điều khiển LED ma trận hiển thị chữ abcd màu xanh rồi
màu đỏ.
Lưu tên file là “bai_803_mtqh_abcd_xanh_do”
a. Mục đích: Biết cách điều khiển led quét hàng hiển thị 2 màu.
b. Lưu đồ, giải thuật: Bài 801 hiển thị màu xanh, thực hiện tương tự cho màu đỏ.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
const unsigned char chuoi_hthi[]={"ABCD"};
#include <tv_08_matran_led_qhang.c>
#define ck_quet 100
#define vt_quet 24
void main()
{
set_up_port();
lay_so_luong_ky_tu_chuoi();
lay_ma_ky_tu(slkt);
while(true)
{
ma_tran_quet_hang(ck_quet,vt_quet,mau_xanh);
ma_tran_quet_hang(ck_quet,vt_quet,mau_do);
}
}
Bài mẫu 804. Chương trình điều khiển LED ma trận hiển thị chuỗi màu xanh dịch từ
phải sang trái.
Lưu tên file là “bai_804_mtqh_chuoi_xanh_dich”
a. Mục đích: Biết cách điều khiển led quét hàng hiển thị chuỗi dịch trái.
b. Lưu đồ, giải thuật: Giống bài đã thực hiện theo cách quét cột.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
const unsigned char chuoi_hthi[]=
{"*1234!** Let make sign better ****"};
Bài tập 805. Chương trình điều khiển LED ma trận hiển thị chữ ABCD dịch từ phải
sang trái màu xanh rồi đến màu đỏ.
Lưu tên file là “bai_805_mtqh_abcd_xanh_do_dich”
Bài tập 806. Chương trình điều khiển LED ma trận hiển thị chữ ABCD dịch từ phải
sang trái màu xanh rồi đến màu đỏ và màu cam.
Lưu tên file là “bai_806_mtqh_abcd_xanh_do_cam_dich”
Bài mẫu 807. Chương trình điều khiển LED ma trận đếm 1 số từ 0 đến 9.
Lưu tên file là “bai_807_mtqh_dem_1so_xanh”
a.Mục đích: Biết cách điều khiển led quét hàng hiển thị giá trị đếm 1 số.
b.Lưu đồ, giải thuật: Đếm 1 số, giải mã led ma trận cho biến đếm lưu vào vùng nhớ,
tiến hành quét hàng như bài 801.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
const unsigned char chuoi_hthi[]={"*1234!*"};
#include <tv_08_matran_led_qhang.c>
#define ck_quet 100
#define vt_quet 24
unsigned int8 i;
void main()
{
Bài tập 808. Hãy viết chương trình đếm 2 số từ 00 đến 99.
Lưu tên file là “bai_808_mtqh_dem_2so_xanh”
Bài tập 809. Hãy viết chương trình đếm 3 số từ 000 đến 999.
Lưu tên file là “bai_809_mtqh_dem_3so_xanh”
Bài tập 810. Hãy viết chương trình đếm sản phẩm dùng timer T0 hiển thị giá trị đếm
trên led ma trận, giới hạn đếm từ 00 đến 99.
Lưu tên file là “bai_810_mtqh_dem_sp_t0”
Bài tập 811. Hãy viết chương trình đo nhiệt độ hiển thị trên 2 led ma trận.
Lưu tên file là “bai_811_mtqh_adc_lm35”
Bài tập 812. Hãy viết chương trình đo nhiệt độ và đếm sản phẩm dùng T0 hiển thị 4 số
trên 3 led ma trận : 2 số bên trái hiển thị nhiệt độ, 2 số bên phải hiển thị T0.
Lưu tên file là “bai_812_mtqh_adc_lm35_t0”
Các mã dữ liệu A140H đến D75FH được dùng cho code BIG5 và A1A0H đến F7FFH cho
code GB.
Để hiển thị font HCGROM thì ghi 2 byte vào DDRAM để hiển thị 2 font 8×16. Một
byte tượng trưng cho 1 font ký tự. Dữ liệu của mỗi byte từ 02H đến 7FH.
Để hiển thị font CGRAM thì ghi 2 byte vào DDRAM để hiển thị 1 font 16×16. Chỉ
có các từ sau là cho phép 0000H, 0002H, 0004H, 0006H.
Để hiển thị font CGROM thì ghi 2 byte vào DDRAM để hiển thị 1 font 16×16. Các
từ sau A140H, D75FH là cho code BIG5 và A1A0H, F7FFH là cho code GB.
Byte cao D15 đến D7 được gởi đến GLCD trước và sau đó là byte thấp từ D7 đến D0. Hãy
tham khảo thêm bảng 6-3.
Bảng 9-3. Các font chữ 8x16 của GLCD
Thực hành vi điều khiển PIC 221
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
Trong hình trên thì để hiển thị ký tự kích thước 16×16 thì phải gởi 2 byte liên tiếp vào cùng
1 địa chỉ, ví dụ bạn phải gởi 2 byte cùng 1 địa chỉ 0×85 chứ không được gởi 1 byte ở địa chỉ
0×85 và 1 byte ở địa chỉ 0×86.
Vùng nhớ GDRAM
Vùng nhớ RAM hiển thị hình ảnh hỗ trợ không gian ánh xạ có kích thước 64×256 bit như
hình 6-3.
Địa chỉ vùng nhớ GDRAM được thiết lập bằng cách ghi 2 byte liên tiếp cho địa chỉ chiều
ngang và chiều dọc. Hai byte dữ liệu ghi vào GDRAM cho một địa chỉ. Bộ đếm địa chỉ tự động
tăng lên 1 để lưu 2 byte tiếp theo.
Trình tự thực hiện như sau:
222 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
Thiết lâp địa chỉ dọc (Y) cho GDRAM
Thiết lâp địa chỉ ngang (X) cho GDRAM
Ghi 8 bit D15 đến D8 vào GDRAM – byte thứ nhất
Ghi 8 bit D7 đến D0 vào GDRAM – byte thứ hai
Hình 9-3. Tung độ hiển thị GDRAM và địa chỉ tương ứng của GLCD
Hình 9-3 cho thấy địa chỉ theo chiều ngang x (horizontal address) là 16 (từ 0 đến 15) tính
theo word 16 bit, tính theo bit thì bằng 16×16 = 256 bit.
Địa chỉ theo chiều dọc y (vertical address) là 64 bit (từ 0 đến 63).
Để giúp các bạn dễ hiểu thì hình 9-3 được vẽ lại như hình 9-4.
0,0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 255, 0
0 X
3
0, 63
Y
0,0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 255, 0
0 X
1
0, 31
Y
0,0 0 1 2 3 4 5 6 7
0 X
1
8 9 10 11 12 13 14 15
Hình 9-6. Bộ nhớ GDRAM của GLCD 32×256 bố trí theo kích thước 64×128
Người ta cắt 8 vùng nhớ ở bên phải đem xuống đặt bên dưới, khi đó tính theo cách bố trí
này thì GLCD có kích thước 64×128.
Khi lập trình điều khiển 1 pixel hiển thị thì ta không thể tính theo kích thước 64×128 của
hình 9-6 được mà phải tính theo kích thước 32×256 của hình 9-5.
Muốn lập trình cho tương thích với kích thước 64×128 thì ta vẽ lại hình 9-6 như hình 9-7.
Giới hạn các tọa độ pixel: Khi lập trình điều khiển 1 pixel hiển thị theo kích thước (y×x =
64×128) thì y phải nằm trong giới hạn từ 0 đến 63 và x từ 0 đến 127.
Khi muốn điều khiển hiển thị 1 pixel thì ta tiến hành kiểm tra y: nếu y nằm trong phạm vi
nhỏ hơn 32 thì điểm pixel đó nằm ở 2 hàng trên (XL, YL), nếu lớn 32 thì ta phải trừ đi cho 32
và tăng kích thước của x lên 128 và khi đó chúng sẽ nằm ở 2 hàng dưới (XH, YH).
0,0 0 1 2 3 4 5 6 7 127, 0
0 XL
1
127, 31
0, 31 YL
128,0 255, 0
8 9 10 11 12 13 14 15
XH
0
1
128, 31 YH
(6) Set 0 0 1 0 AC5 AC4 AC3 AC2 AC1 AC0 Set GDRAM address to 72µs
GRAPHIC 0 0 1 0 0 0 AC3 AC2 AC1 AC0 address counter (AC).
RAM addr First set vertical address
and horizontal address by
consecutive writing.
Vertical address range
AC5 … AC0.
Horizontal address range
AC3 … AC0.
9.2 CÁC BÀI THỰC HÀNH HIỂN THỊ TEXT TRÊN GLCD
9.2.1 Sơ đồ mạch của GLCD
Bộ thực hành có kết nối một GLCD hai màu có kích thước 128×64 qua IC mở rộng port là
MBI5026 có sơ đồ như hình sau:
Có 8 bit DB7-DB0 nối với out7 đến out0 của MBI, năm tín hiệu điều khiển RST, NC, E,
RW, RS nối với năm ngõ ra từ out8 đến out12. Ba ngõ ra out còn lại nối chung và nối với Anode
của đèn backlight để điều khiển đèn sáng tắt theo yêu cầu để tiết kiệm nguồn và tăng tuổi thọ
của đèn và LCD.
Phần điều khiển GLCD đã trình bày ở phần LCD.
9.2.2 Thư viện hàm điều khiển cơ bản của GLCD
Thư viện GLCD có tên là “tv_09_18f6722_glcd.c” lưu các hàm điều khiển GLCD.
void h901_glcd_hien_thi_chuoi()
{
glcd_command(glcd_addr_line0);
glcd_data("Nhu co Bac ho ");
glcd_command(glcd_addr_line1);
glcd_data("trong ngay vui ");
glcd_command(glcd_addr_line2);
glcd_data("dai thang ");
glcd_command(glcd_addr_line3);
glcd_data("thuc hanh vdk");
}
void main()
{
set_up_port();
setup_glcd(glcd_text_mode);
while(true)
{
h901_glcd_hien_thi_chuoi();
while(true);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Hiển thị nội dung 4 hàng đã khai báo trong chương trình. Có thể
thay đổi nội dung hiển thị.
Bài tập 902. Hãy viết chương trình giống bài 601 nhưng có 2 nút điều khiển ON và
OFF. Khi nhấn ON thì hiển thị 4 hàng thông tin, nhấn OFF thì xóa hết.
Viết thêm hàm xóa 4 chuỗi trên GLCD bằng cách hiển thị 16 khoảng trắng cho 1 hàng.
Lưu tên file “bai_902_glcd_ht_chuoi_on_off”.
Bài mẫu 903. Chương trình đếm sản phẩm dùng timer0 hiển thị trên GLCD font 16×16.
Giới hạn đếm từ 0 đến 50.
Lưu tên file “bai_903_glcd_counter_t0”.
a. Mục đích: Biết lập trình đếm sản phẩm hiển thị trên GLCD ở chế độ text.
void b903_dem_sp_t0_glcd_8l7d()
{
t0 = get_timer0();
if(t0_tam!=t0)
{
t0_tam = t0;
b903_hienthi_4led7doan();
h903_glcd_gma_hthi(glcd_addr_line1,t0);
if (t0>=g_han)
{
set_timer0(0);
buzzer_on_off(300);
}
}
}
void main()
{
set_up_port();
setup_glcd(glcd_text_mode);
glcd_command(glcd_addr_line0);
glcd_data("dem san pham:");
setup_timer_0(t0_ext_l_to_h|t0_div_1|t0_8_bit);
set_timer0(0);
t0_tam = 1;
g_han=50;
while(true)
{
b903_dem_sp_t0_glcd_8l7d();
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: Hiển thị thông tin và giá trị đếm xung ngoại của timer0.
Bài tập 903. Hãy viết chương trình đếm sản phẩm dùng counter T0, hiển thị kết quả
đếm trên 8 led 7 đoạn, LCD và GLCD.
Mục đích: biết lập trình đếm sản phẩm và giải mã hiển thị trên nhiều module.
Lưu tên file là “bai_903_glcd_lcd_4led_dem_sp_t0”
9.3 CÁC BÀI THỰC HÀNH HIỂN THỊ HÌNH ẢNH TRÊN GLCD
9.3.1 Thư viện và hàm điều khiển liên quan đến hình ảnh của GLCD
Phần này thực hành các bài hiển thị hình ảnh số 2 màu trên GLCD.
Hình ảnh số có được từ nhiều nguồn thiết bị khác nhau như máy chụp ảnh hay ảnh chụp
trên màn hình máy tính hay do phần mềm vẽ tạo ra, … với nhiều tên mở rộng khác nhau, … và
muốn hiển thị ảnh trên GLCD thì ta phải dùng phần mềm chuyển đổi ảnh sang file nhị phân còn
gọi là file ảnh. Khi chuyển đổi phần mềm sẽ cung cấp hai thông số là chiều cao và rộng của file
nhị phân, kèm theo là file nhị phân của ảnh.
File nhị phân của ảnh trắng đen là một tập hợp các pixel của ảnh được lưu trữ thành từng
byte, mỗi byte lưu 8 pixel theo chiều bắt đầu từ pixel bên trái trái sang phải và từ trên xuống.
typedef union
{
unsigned int16 word;
unsigned int8 nbyte[2];
}dots;
typedef struct
{
int1 refresh;
dots pixel[glcd_doc][glcd_ngang];
} gd_ram;
gd_ram gdram_vdk;
b. Hàm 625: Thiết lập màu nền trắng hoặc xanh cho GLCD.
void glcd_mau_nen(int1 glcd_color)
{
int16 d;
if(glcd_color) d=0xffff; else d=0;
for (doc=0; doc < glcd_doc; doc++)
{
for (ngang=0; ngang < glcd_ngang; ngang++)
gdram_vdk.pixel[doc][ngang].word = d;
}
gdram_vdk.refresh = true;
}
c. Hàm 626: làm đổi màu 1 pixel trên GLCD ở hàng x và cột y.
void glcd_pixel(int8 x, int8 y, int1 color)
{
int8 b;
if(y>31){x += 128; y-= 32;};
doc = y;
ngang = x/16;
b = 15 - (x % 16);
x = x/16;
for (doc = y; doc <(y+cao); doc++)
{
if(doc>31)
{
hesox = 8+x;
hesoy = doc-32;
}
else {hesox = x; hesoy = doc;}
glcd_command( 0x80 |hesoy);
glcd_command( 0x80 |hesox);
void main()
{
set_up_port();
setup_glcd(glcd_text_mode);
delay_ms(1);
setup_glcd(glcd_graphic_mode);
glcd_mau_nen(0) ;
while(true)
{
glcd_xuat_anh(64,64,0,0);
gdram_vdk_to_gdram_glcd_all ();
while(true);
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: Sẽ nhìn thấy logo SPK màu trắng trên nền xanh của GLCD.
g. Thay đổi thông số: Thay đổi giá trị của x sang 8 hoặc 10 hoặc 12 và 16 thử xem sao.
Bài tập 906. Hãy hiển thị hai logo SPK trên màn hình GLCD.
Bài tập 907. Hãy hiển thị logo SPK bên trái và sau đó di chuyển sang bên phải với thời
gian delay là 1 giây cho đến khi dụng biên bên phải thì di chuyển ngược lại.
Lưu tên file “bai_907_glcd_ht_anh_spkt_dichuyen”.
Bài mẫu 911. Chương trình vẽ đường thẳng, đường tròn, hình vuông, hình chữ nhật,
hiển thị text trên GLCD.
Lưu tên file “bai_911_glcd_ve_cac_hinh”.
a. Mục đích: Biết lập trình sử dụng các hàm của thư viện để vẽ các hình trên GLCD.
b. Lưu đồ, giải thuật: Khởi tạo GLCD chế độ hình ảnh, gọi các hàm đã viết.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
#include <tv_09_18f6722_glcd.c>
#include <graphics.c>//duoi tv_pic_glcd
void b911_glcd_line_rect_bar_circle_text()
{
unsigned char glcd_text_cir[]={"graphic"};
setup_glcd(glcd_graphic_mode);
glcd_mau_nen(0);
glcd_line(0,10,30,30,sang);
glcd_bar(90,40,100,60,5,sang);
glcd_bar(70,40,70,60,5,sang);
gdram_vdk_to_gdram_glcd_all();
}
void main()
{
set_up_port();
setup_glcd(glcd_text_mode);
delay_ms(1);
setup_glcd(glcd_graphic_mode);
glcd_mau_nen(0) ;
while(true)
{
b911_glcd_line_rect_bar_circle_text();
while(true);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: Sẽ nhìn thấy text, đường thẳng và các hình trên GLCD.
f. Thay đổi thông số: Có thể thay đổi các thông số trong các hàm.
Bài mẫu 912. Đồng hồ số và kim: Đọc thời gian thực DS1307, chỉ hiển thị phần giây
dạng số và kim trên GLCD.
(64,0) 96
12
22
32 9 (96,32) 3
(ytinh) (x_ve,y_ve)
goc
(xt,yt) (xtinh)
setup_glcd(glcd_graphic_mode);
if(tt) glcd_line(xt,yt,x_ve,y_ve,tat);
tg45 = tg + 45;
if(tg45>60) tg45=tg45-60;
goc = tg45*6;
xtinh = bk*cos((goc*3.14)/180);
ytinh = bk*sin((goc*3.14)/180);
x_ve = xt + (signed int16)(xtinh);
y_ve = yt + (signed int16)(ytinh);
glcd_line(xt,yt,x_ve,y_ve, sang);
glcd_circle(xt,yt,4,co_fill,sang);
glcd_circle(xt,yt,2,no_fill,tat);
}
void glcd_ve_vong_tron_ht_so()
{
unsigned char glcd_text1[]={"clock:"}, glcd_12[]="12",;
unsigned char glcd_3[]="3",glcd_6[]="6",glcd_9[]="9";
setup_glcd(glcd_graphic_mode);
glcd_mau_nen(0) ;
glcd_text57(0,0,glcd_text1, 1, 1);
glcd_text57(xt-5,yt-28,glcd_12, 1,1);
glcd_text57(xt-3,yt+22,glcd_6, 1,1);
glcd_text57(xt-28,yt-3,glcd_9, 1,1);
glcd_text57(xt+24,yt-3,glcd_3, 1,1);
glcd_circle(xt,yt,bks+8,no_fill,sang);
//glcd_circle(xt,yt,bks,no_fill,sang);
glcd_ve_kim_1(bks,giay,0);
}
void glcd_dong_ho_so()
{
const signed int8 maglcd[]={"0123456789"};
glcd_command(glcd_text_mode);
glcd_command(glcd_addr_line1+3);
glcd_data(maglcd[giay/10]);
glcd_data(maglcd[giay%10]);
}
d. Chương trình chính:
#include <tv_kit_vdk_18f6722_all.c>
#include <tv_09_18f6722_glcd.c>
void main()
{
set_up_port();
setup_glcd(glcd_text_mode);
delay_ms(1);
setup_glcd(glcd_graphic_mode);
glcd_mau_nen(0) ;
ds1307_kiem_tra_ma();
glcd_ve_vong_tron_ht_so(giay_ds);
while(true)
{
ds1307_doc_time(8);
if (giay_tam!=giay_ds)
{
giay_tam=giay_ds;
giay_bin=(giay_ds/16)*10+(giay_ds%16);
glcd_ve_kim(bks,giay_bin,1);
gdram_vdk_to_gdram_glcd_all();
glcd_dong_ho_so(giay_bin);
}
}
}
e. Tiến hành biên dịch và nạp.
f. Quan sát kết quả: Sẽ nhìn thấy hình tròn và kim giây di chuyển trên GLCD. Có thêm
hiển thị các con số 12, 3, 6, 9 như đồng hồ thực tế. Có vẽ thêm 2 vòng tròn ở tâm cho
dễ nhìn. Có thêm phần hiển thị đếm giây bằng số.
Bài tập 913. Đồng hồ số và kim: Giống bài 912, thêm phần kim phút. Nên dùng
glcd_bar() cho kim phút, chiều dài ngắn hơn kim giây.
Lưu tên file “bai_913_glcd_dong_ho_phut_giay”.
Bài tập 914. Đồng hồ số và kim: thêm phần kim giờ. Nên dùng glcd_bar() cho kim giờ
và phút, chiều dài kim giờ ngắn hơn kim phút.
Lưu tên file “bai_914_glcd_dong_ho_gio_phut_giay”.
(xa,ya)
3 pixel 9 pixel 3 pixel
3 pixel
a
(xf,yf) (xb,yb)
9 pixel
f b
30 pixel
(xg,yg)
g
3 pixel
(xe,ye)
e c
9 pixel
(xd,yd)
d
3 pixel
17 pixel
Bài tập 916. Hãy phát triển bài 915 làm sao có thể giải mã hiển thị bất kỳ số nào từ 0
đến F. Hãy phân tích hình và lập trình. Thực hiện giống bài số to của LCD.
Lưu tên file “bai_916_glcd_so_tu_tao”.
Bài tập 917. Hãy viết chương trình đếm xung ngoại dùng timer0 và giải mã hiển thị
với các số đã xây dựng ở bài 915.
Lưu tên file “bai_917_glcd_dem_xung_so_tu_tao”.
Hình 9-16. Đọc nhiều byte liên tục của IC Eeprom AT24C256.
9.5.2 Mạch điện giao tếp với IC nhớ EEPROM AT24C256
Vi điều khiển PIC18F6722 với bộ nhớ Eeprom AT24C256 như đã trình bày ở chương 1.
9.5.3 Thư viện IC nhớ EEPROM AT24Cxx
Thực hành các bài ghi đọc bộ nhớ nối tiếp Eeprom AT24C256
Thư viện của AT24Cxx theo chuẩn I2C là: “tv_07_i2c_at24cxx”
a. Định nghĩa: Địa chỉ ghi và địa chỉ đọc của IC AT24Cxx.
#define addr_wr_24xxx 0xa0
#define addr_rd_24xxx 0xa1
b. Hàm 705: Reset IC AT24Cxx.
void at24_reset()
{
i2c_start();
i2c_stop();
}
c. Hàm 708: Ghi 1 byte dữ liệu vào địa chỉ của ô nhớ.
void at24_ghi_1byte(usi16 addr,usi8 data_1byte)
{
i2c_start();
i2c_write(at24_addr_wr);
i2c_write(addr>>8);
i2c_write(addr);
i2c_write(data_1byte);
i2c_stop();
void b406_up_dw_g_han()
{
if(phim_up_c2(150)==co_nhan)
{
if(g_han<99)
{
g_han++;
b406_hienthi_4led7doan();
at24_ghi_1byte(100,g_han);
}
}
if(phim_dw_c2(150)==co_nhan)
{
if(g_han>0)
{
g_han--;
b406_hienthi_4led7doan();
at24_ghi_1byte(100,g_han);
}
}
}
void main()
{
set_up_port();
g_han = at24_doc_1byte(100);
b406_hienthi_4led7doan();
while(true)
{
b406_up_dw_g_han();
}
}
d. Tiến hành biên dịch và nạp.
248 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
e. Quan sát kết quả: Sau khi nạp xong thì sẽ hiển thị giá trị mặc nhiên cho lần đầu. Sau
đó tiến hành thay đổi giá trị bằng UP hoặc DW. Tắt điện kit thực hành, sau vài giây
thì mở lại, led hiển thị giá trị của lần thay đổi sau cùng là đúng. Địa chỉ 100 có thể
thay đổi trong phạm vi từ 0 đến 8191.
Bài mẫu 922. Chương trình ghi dữ liệu 64 byte bắt đầu từ con số 100 vào trang bộ nhớ
thứ 0. Địa chỉ tăng từ 0 đến 63 và con số ghi vào cũng tăng từ 100 đến 163.
Sau khi ghi xong thì tiến hành đọc lại dữ liệu vừa hiển thị trên 8 led đơn và led 7 đoạn,
địa chỉ cũng hiển thị trên 16 led đơn.
Lưu tên file là “bai_922_at24_wr_rd_page”
a. Mục đích: Biết lập trình ghi dữ liệu 1 trang vào và đọc ra của bộ nhớ AT24C64.
b. Lưu đồ, giải thuật: Ghi dữ liệu một trang: Thiết lập địa chỉ trang cần ghi, tiến hành
ghi dữ liệu 64 byte liên tục. Đọc dữ liệu một trang: Thiết lập địa chỉ trang cần dọc,
tiến hành đọc dữ liệu 64 byte liên tục.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
unsigned int8 i,dt_doc,page;
if(pagex>511) pagex=0;
addr_mem = (pagex)*64;
at24_khoi_tao_ghi(addr_mem);
for(i=0;i<64;i++)
{
dt_ghi= i + 100;
i2c_write(dt_ghi);
xuat_32led_don_4byte(addr_h,addr_l|i,0,dt_ghi);
md4l7d_giaima_3so_vitri_vn(dt_ghi,3,kx_vn);
xuat_4led_7doan_4so();
delay_ms(x);
}
i2c_stop();
}
Bài tập 923. Hãy viết chương trình có chức năng sau:
Hãy mở rộng bài 601 đo nhiệt độ và có tắt mở đèn … thêm phần lưu giá trị nhiệt độ
của 1 chu kỳ: từ lúc mở đèn gia tăng nhiệt đến lúc tắt đèn để giảm nhiệt cho đến khi mở
đèn lại. Lưu 256 mẫu vào bộ nhớ Eeprom và vẽ lại đồ thị trên GLCD.
Lưu tên file là “bai_923_at24_lcd_7doan_lm35a_den_buz_bt3_glcd”
Hình 9-19. Cấu trúc thanh ghi điều khiển của IC PCF8591
Nếu chế độ tự động tăng được yêu cầu trong các ứng dụng thì phải sử dụng bộ dao động
nội bộ và cờ cho phép ngõ ra tương tự phải bằng 1 (bit thứ 6 của thanh ghi điều khiển). Điều này
cho phép bộ dao động nội bộ chạy liên tục, với cách này sẽ ngăn chặn lỗi chuyển đổi do dao
Hình 9-24. Dạng sóng chuyển đổi A/D ở chế độ đơn cực và vi sai
9.6.10 Điện áp tham chiếu của IC PCF8591
Thực hành vi điều khiển PIC 257
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
Đối với cả hai chuyển đổi D/A và A/D đều sử dụng điện áp tham chiếu bên ngoài cấp cho
các chân VREF và AGND. Chân AGND được nối với mass tương tự hoặc có thể nối với nguồn
điện áp DC để chỉnh điện áp lệch nếu bị lệch.
9.6.11 Bộ dao động của IC PCF8591
Bộ dao động trên chip tạo ra các tín hiệu đồng hồ cần thiết cho chuyển đổi A/D và làm tươi
bộ khuếch đại đệm. Khi sử dụng dao động này chân EXT phải nối với VSS (GND). Tần số dao
động xuất hiện tại chân OSC.
Nếu chân EXT kết nối với VDD thì ngõ ra dao động OSC sẽ chuyển sang trạng thái trở
kháng cao cho phép nhận tín hiệu đồng hồ từ bên ngoài đưa đến chân OSC.
9.6.12 Địa chỉ thanh ghi của IC PCF8591
Byte địa chỉ của IC PCF8591 như hình 9-25:
Bài mẫu 925. Chương trình đọc nhiệt độ từ 2 cảm biến LM35A và LM35B nối với
kênh AN0, AN1 của IC PCF8591 giao tiếp chuẩn I2C, hiển thị kết quả đo trên module 4
led 7 đoạn và LCD. Điều khiển đèn gia tăng nhiệt, buzzer và nút BT3 giống bài 601.
Lưu tên file là “bai_925_pcf_lcd_7doan_lm35ab_den_buz_bt3”
a. Mục đích: Biết lập trình dùng ADC giao tiếp chuẩn I2C để đọc nhiệt độ từ 2 cảm biến
LM35 hiển thị trên led 7 đoạn và LCD.
b. Lưu đồ, giải thuật: Chọn kênh, tiến hành đọc dữ liệu, cộng dồn kết quả, chia trung
bình, hiển thị. Tương tự cho kênh còn lại.
c. Chương trình con “bai_925_pcf_tv”:
void pcf_lm35a_ht_lcd(usi8 x,y)
260 Thực hành vi điều khiển PIC
Sư phạm kỹ thuật tphcm Nguyễn Đình Phú
{
if(pcf_lm35at!=pcf_lm35a)
{
pcf_lm35at=pcf_lm35a;
lcd_gm_ht_2so_to_xvn(pcf_lm35a,x,y,kx_vn);
}
}
void pcf_lm35b_ht_lcd(usi8 x,y)
{
if(pcf_lm35bt!=pcf_lm35b)
{
pcf_lm35bt=pcf_lm35b;
lcd_gm_ht_2so_to_xvn(pcf_lm35b,x,y,kx_vn);
}
}
void pcf_do_ht_2_lm35()
{
pcf_lm35a=pcf_doc_chan(pcf_chan0,solan);
pcf_lm35b=pcf_doc_chan(pcf_chan1,solan);
pcf_lm35a_ht_lcd(1,0);
pcf_lm35b_ht_lcd(1,10);
giaima_bin_2so_vitri_vn(pcf_lm35a,1,kx_vn);
giaima_bin_2so_vitri_vn(pcf_lm35b,3,kx_vn);
xuat_8led_7doan();
}
d. Chương trình chính:
#include <tv_kit_vdk_18f6722_all.c>
#define solan 50
unsigned int8 pcf_lm35a,pcf_lm35b;
unsigned int8 pcf_lm35at=0,pcf_lm35bt=0;
#include <bai_925_pcf_tv.c>
void main()
{
set_up_port();
lcd_setup();
lcd_khoi_tao_cgram_so_to();
lcd_goto_xy(0,0);
lcd_data("PCF-LM35A");
lcd_goto_xy(0,10);
lcd_data("PCF-LM35B");
Bài tập 926. Mở rộng bài 926: thêm vào hiển thị thời gian thực giờ phút giây, ngày
tháng năm thứ ở hàng thứ 3. Vừa truy xuất DS1307 và PCF8591 theo chuẩn I2C.
Lưu tên file “bai_926_pcf_lcd_7doan_lm35ab_den_buz_bt3_clock”.
lcd_goto_xy(0,0);
lcd_data("PCF-LM35A");
lcd_goto_xy(0,10);
lcd_data("PCF-LM35B");
pcf_dac = 210;
while(true)
{
pcf_do_ht_2_lm35();
so_sanh_nd_dk_buzzer(pcf_lm35b);
delay_ms(500);
if(!input(bt3)) buzzer_off();
pcf_xuat_dac(pcf_dac);
if(pcf_dac==0) pcf_dac=210;
else pcf_dac++;
xuat_32led_don_4byte(0,0,0,pcf_dac);
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: sau khi nạp xong thì ta nhìn thấy giá trị số hiển thị trên module led
7 đoạn tăng dần và trên led đơn cũng vậy. Hãy quan sát led màu xanh lá nằm bên
phải IC PCF8591 gần biến trở nút áo sẽ thấy cường độ sáng tăng dần. Khi đạt 255 thì
led sáng nhất sau đó giá trị số về lại 210 thì led tắt. Điện áp tương tự ra bắt đầu từ giá
trị 1 tương ứng 10mV nhưng phải dùng đồng hồ thì mới thấy.
Bài tập 928. Hãy thêm vào chương trình 927 sao cho khi tăng lên đến 255 thì giá trị số
giảm dần về 210 rồi lặp lại.
Lưu tên file là “bai_928_dac_pcf8591_up_dw.c”
Hình 9-30. Phạm vi nhận biết của cảm biến chuyển động
Sơ đồ chân của cảm biến PIR như hình 9-24:
Hình 9-31. Sơ đồ chân và tên các chân của cảm biến chuyển động
Hình 9-32. Sơ đồ kết nối tải của cảm biến chuyển động
Trong bộ thí nghiệm thì cảm biến PIR được nối đến chân RA3 của vi điều khiển PIC.
9.8.2 Vi điều khiển giao tiếp với cảm biến PIR
Trong bộ thực hành thì cảm biến PIR nối với port RD3 của vi điều khiển như hình 9-26:
Hình 9-33. Sơ đồ của cảm biến chuyển động PIR với vi điều khiển
9.8.3 Các chương trình điều khiển dùng cảm biến PIR
Bài mẫu 931. Chương trình điều khiển đèn tự động sáng khi phát hiện có người chuyển
động hoặc tắt đèn khi không có người chuyển động dùng cảm biến PIR.
Lưu tên file là “bai_931_pir_dk_den.c”
Thực hành vi điều khiển PIC 265
Khoa điện – điện tử Bộ môn điện tử công nghiệp - ys
Mục đích: biết lập trình dùng cảm biến PIR để điều khiển tắt mở đèn.
a.
Lưu đồ, giải thuật: Kiểm tra tín hiệu ra của cảm biến để biết trạng thái phát hiện người
b.
rồi xử lý.
c. Chương trình:
#include <tv_kit_vdk_18f6722_all.c>
int1 tt_triac=0;
void kiemtra_pir_mo_den()
{
if(input(pir)&&(tt_triac==0))
{
triac_2_off(); tt_triac=1;
xuat_32led_don_1dw(0XFFFFFFFF);
}
else if(!input(pir)&&(tt_triac==1))
{
triac_2_on(); tt_triac=0;
xuat_32led_don_1dw(0);
}
}
void main()
{
set_up_port();
tt_triac=0;
while(true)
{
kiemtra_pir_mo_den();
}
}
d. Tiến hành biên dịch và nạp.
e. Quan sát kết quả: sau khi nạp xong thì nếu cảm biến PIR phát hiện không có chuyển
động (đèn màu trắng gần cảm biến PIR tắt) thì đèn triac tắt, nếu có chuyển động (đèn
màu trắng sáng) thì đèn triac sáng. Nếu phát hiện chuyển động đèn đã sáng thì các
bạn hãy ngồi im không nhúc nhích cho đến khi đèn tắt, sau đó trợn mắt to hết cỡ xem
nó có phát hiện không, nếu không thì hãy liết mắt qua lại mà nó cũng không mở thì
hãy chuyển động để nó phát hiện và mở đèn. Có thể dùng báo động bằng âm thanh
nhưng ồn nên dùng đèn để báo hiệu.