Vi điều khiển xuất mức logic 1 để điều khiển đèn B sáng, mức logic 0 để điều khiển đèn Btắt.. Nếu có người xuất hiện trong vùng hoạt động của cảm biến ngay lập tức đèn B sáng, loa được đ
Trang 2Vi điều khiển xuất mức logic 1 để điều khiển đèn B sáng, mức logic 0 để điều khiển đèn B
tắt
Ban đầu đèn tắt, loa không kêu Nếu có người xuất hiện trong vùng hoạt động của cảm biến
ngay lập tức đèn B sáng, loa được điều khiển phát ra
âm thanh với tần số chính xác 5Khz, Duty
Cycle = 40% (dùng timer tạo xung) Trạng thái này được duy trì cho dù người đó có còn trong
vùng hoạt động của cảm biến nữa hay không
Bất cứ khi nào nhấn nút RST thì đèn tắt, loa không kêu
a Vẽ lưu đồ chương trình (1 điểm)
b Viết chương trình cho vi điều khiển thực hiện đúng yêu cầu trên (2 điểm)
Câu 2: (3.5 điểm)
Cho hệ thống đếm sản phẩm: Vi điều khiển
Pic16F887 kết nối một cảm biến phát hiện sản
phẩm, LCD 16x2, hai nút nhấn thường hở UP, DW Bình thường ngõ ra cảm biến là 0V, khi có
sản phẩm chắn ngang cảm biến ngõ ra sẽ lên mức 5V
Trang 3Giao diện hiển thị của LCD như sau:
Giá trị đặt AA là số sản phẩm của một thùng cần đónggói Giá trị AA có thể điều chỉnh
được bởi hai nút nhấn UP (tăng 1 đơn vị), DW (giảm
1 đơn vị) AA nằm trong phạm vi
[20-30] Mặc định AA = 20
Giá trị BB là số phẩm đếm được
Khi sản phẩm đếm được BB bằng AA thì LCD sẽ nhấp nháy (sáng 0.5s, tắt 0.5s) chỉ hai dòng
chữ như sau:
a Vẽ mạch nguyên lý kết nối (1 điểm) (phần cứng
kết nối sinh viên tùy chọn chân thích
hợp, LCD có thể giao tiếp với vi điều khiển theo kiểu 8bit dữ liệu hoặc 4 bit dữ liệu Khối
cảm biến chỉ cần vẽ khối, không cần vẽ chi tiết mạch cảm biến)
b Viết chương trình thực hiện yêu cầu trên (2.5 điểm)
Câu 3: (3.5 điểm)
Cho hai vi điều khiển Pic16F887 (được đặt tên
VDKA và VDKB) giao tiếp truyền dữ liệu
Trang 4nối tiếp bất động bộ, 8 bit dữ liệu, tốc độ baud = 2400.
Cả hai vi điều khiển đều sử dụng thạch
Trang 5đo được Dữ liệu kênh đo và nhiệt độ đo được nhận từVDKA gởi qua.
Yêu cầu:
a Vẽ mạch nguyên lý kết nối (1 điểm)
b Viết chương trình cho VDKA (1.5 điểm)
c Viết chương trình cho VDKB (1 điểm)
Trang 6ĐÁP ÁN
CÂU 1: 3 ĐIỂM
a Vẽ lưu đồ chương trình (1 điểm)
- Về hình thức: lưu đồ có đầy đủ các phần Bắt đầu, xử
// Cấu hình vi điều khiển
#pragma config FOSC = HS, WDTE = OFF, PWRTE = OFF, BOREN = ON, LVP = OFF, CPD = OFF, WRT = OFF,
CP = OFF
// Định nghĩa tần số
Trang 7#define _XTAL_FREQ 12000000
// Hàm khởi tạo
void init() {
// Cấu hình các chân I/O
TRISB0 = 1; // Chân RB0 (Cảm biến A) là đầu vào TRISB1 = 0; // Chân RB1 (Đèn B) là đầu ra
TRISB2 = 0; // Chân RB2 (Loa) là đầu ra
TRISB3 = 1; // Chân RB3 (Nút nhấn RST) là đầu vào
// Cấu hình Timer2 để tạo xung PWM
T2CON = 0x04; // Prescaler 1:1, bật Timer2
PR2 = 59; // Đặt giá trị chu kỳ PWM (tạo tần số 5kHz với Fosc = 12MHz)
CCPR1L = 24; // Đặt chu kỳ làm việc 40% (40% của PR2 = 24)
CCP1CON = 0x0C; // Chế độ PWM
TMR2ON = 1; // Bật Timer2
// Ban đầu tắt đèn và loa
RB1 = 0;
Trang 8RB1 = 1; // Bật đèn
CCP1CONbits.CCP1M = 0b1100; // Bật chế độ PWM
Trang 9PWM và kiểm tra trạng thái của cảm biến cũng như nút nhấn Khi có người xuất hiệntrong vùng cảm biến, đèn sẽ sáng và loa phát ra âm thanh 5kHz với Duty Cycle
40% Khi nhấn nút RST, đèn và loa sẽ tắt
Trang 10CÂU 2: 3.5 điểm
a Vẽ mạch nguyên lý kết nối: 1 điểm Sinh viên có thể chọn cách kết nối phù hợp
- Vẽ kết nối đúng với LCD : 0.5 điểm
- Vẽ kết nối cho vdk các chân cấp nguồn, reset, thạch anh, nút nhấn, cảm biến sản
phẩm: 0.5 điểm
b) Viết chương trình thực hiện yêu cầu:
Dưới đây là chương trình C cho vi điều khiển
PIC16F887 thực hiện yêu cầu trên:
#include <xc.h>
Trang 11#include <stdio.h>
#include "lcd.h"
// Cấu hình vi điều khiển
#pragma config FOSC = HS, WDTE = OFF, PWRTE = OFF, BOREN = ON, LVP = OFF, CPD = OFF, WRT = OFF,
Trang 12TMR0 = 256 - 60; // Tạo khoảng thời gian 0.5s với FOSC = 12MHz và prescaler 1:256
Trang 13TRISB1 = 1; // Chân RB1 (Nút nhấn UP) là đầu vào TRISB2 = 1; // Chân RB2 (Nút nhấn DW) là đầu vào TRISB3 = 0; // Chân RB3 (LCD điều khiển) là đầu ra
// Khởi tạo LCD
lcd_init();
// Khởi tạo Timer0
OPTION_REG = 0x87; // Prescaler 1:256
TMR0 = 256 - 60; // Tạo khoảng thời gian 0.5s
TMR0IE = 1; // Cho phép ngắt Timer0
GIE = 1; // Cho phép ngắt toàn cục
Trang 14if (RB1 == 0) {
if (AA < 30) {
AA++;
delay_ms(200); // Tránh sự kiện nhấn lặp lại
Trang 15while (RB0 == 1); // Chờ sản phẩm đi qua cảm biến
delay_ms(100); // Tránh sự kiện lặp lại
không mong muốn
Trang 16TMR0IE = 1; // Bật ngắt Timer0 để nhấp nháy LCD
khoảng [20-30], cảm biến đếm sản phẩm
BB và hiển thị lên LCD Khi BB bằng AA, LCD sẽ nhấp nháy
Trang 17chân DP ta luôn nối VCC (bởi vì mã 7 đoạn của số 3,
4 hai đoạn này giống nhau):
0.5 điểm
Trang 18b) Chương trình cho VDKA:
#include <xc.h>
#include <stdio.h>
// Cấu hình vi điều khiển
#pragma config FOSC = HS, WDTE = OFF, PWRTE = OFF, BOREN = ON, LVP
= OFF, CPD = OFF, WRT = OFF, CP = OFF
#define _XTAL_FREQ 12000000 // Định nghĩa tần số
// Hàm khởi tạo UART
void uart_init() {
Trang 19TXSTA = 0x24; // Cấu hình truyền:
BRGH = 1, TXEN = 1
RCSTA = 0x90; // Cấu hình nhận: SPEN
= 1, CREN = 1
SPBRG = 77; // Tốc độ baud 2400 bps với FOSC = 12MHz
}
// Hàm gửi dữ liệu qua UART
void uart_send(char data) {
while (!TXIF); // Chờ đến khi bộ đệm truyền trống
TXREG = data; // Gửi dữ liệu
}
// Hàm đo nhiệt độ từ cảm biến LM35
unsigned int read_temp(unsigned char
Trang 20GO_nDONE = 1; // Bắt đầu chuyển đổi ADC
while (GO_nDONE); // Chờ đến khi
chuyển đổi hoàn tất
return (ADRESH << 8) + ADRESL; // Lấy giá trị ADC
Trang 21Chuyển đổi giá trị ADC sang nhiệt độ
uart_send(channel); // Gửi kênh nhiệt độ
uart_send(temp); // Gửi giá trị
Trang 22#include <xc.h>
// Cấu hình vi điều khiển
#pragma config FOSC = HS, WDTE = OFF, PWRTE = OFF, BOREN = ON, LVP
= OFF, CPD = OFF, WRT = OFF, CP = OFF
#define _XTAL_FREQ 12000000 // Định nghĩa tần số
// Bảng mã hiển thị cho LED 7 đoạn
const char led_7seg[] = {0x3F, 0x06,
Trang 23RCSTA = 0x90; // Cấu hình nhận: SPEN
= 1, CREN = 1
SPBRG = 77; // Tốc độ baud 2400 bps với FOSC = 12MHz
// Hàm hiển thị giá trị trên LED 7 đoạn
void display_led(unsigned char led,
unsigned char value) {
switch (led) {
case 1:
PORTB = led_7seg[value % 10]; // LED 1 hiển thị hàng đơn vị
break;
case 2:
Trang 24PORTB = led_7seg[value / 10]; // LED 2 hiển thị hàng chục
break;
case 3:
PORTB = led_7seg[value]; // LED
3 hiển thị kênh nhiệt độ
Trang 25init(); // Gọi hàm khởi tạo
while (1) {
channel = uart_receive(); // Nhận kênh nhiệt độ từ VDKA
temp = uart_receive(); // Nhận giá trịnhiệt độ từ VDKA
display_led(3, channel); // Hiển thị kênh nhiệt độ
display_led(1, temp % 10); // Hiển thịhàng đơn vị nhiệt độ
display_led(2, temp / 10); // Hiển thị hàng chục nhiệt độ
}
}
Phần mã nguồn này bao gồm việc khởi tạo UART cho VDKA và VDKB, đọc nhiệt độ từ cảm biến LM35, gửi và nhận dữ liệu giữa hai vi điều khiển, và hiển thị giá trị trên LED 7 đoạn