Lập trình giao diện phần cứng vi điều khiển: Bàn phím ma trận, IC thời gian thực và hiển thị LCD

1. Lập trình giao diện phần cứng vi điều khiển

Trong lĩnh vực điện tử hiện đại, vi điều khiển đóng vai trò nền tảng trong việc phát triển các hệ thống nhúng và ứng dụng IoT. Kỹ năng lập trình giao diện phần cứng là yếu tố quyết định khả năng giao tiếp hiệu quả giữa vi điều khiển và các thiết bị ngoại vi. Bài viết này sẽ hướng dẫn cách lập trình điều khiển các thành phần phần cứng phổ biến bao gồm bàn phím ma trận, IC thời gian thực DS1302 và màn hình LCD1602.

1.1 Tổng quan về giao diện phần cứng

Giao diện phần cứng là phương thức kết nối vật lý và logic giữa vi điều khiển với các thiết bị ngoại vi như cảm biến, cơ cấu chấp hành và màn hình hiển thị. Việc lập trình đúng cách các giao interface này cho phép vi điều khiển đọc dữ liệu từ bên ngoài, gửi tín hiệu điều khiển và thực hiện các chức năng phức tạp về xuất nhập.

1.2 Tầm quan trọng của lập trình giao diện

Việc nắm vững kỹ thuật lập trình giao diện ảnh hưởng trực tiếp đến tốc độ phản hồi và hiệu suất của chương trình. Điều này quyết định đến chất lượng và trải nghiệm người dùng của sản phẩm cuối cùng. Phần tiếp theo sẽ minh họa cách sử dụng ngôn ngữ C để thao tác với các cổng cơ bản.

1.3 Ví dụ lập trình cơ bản

Dưới đây là ví dụ về cách điều khiển đèn LED nhấp nháy thông qua cổng GPIO:

// Ham tao tre
void taoTre(unsigned int miliGiay) {
    unsigned int i, j;
    for (i = 0; i < miliGiay; i++)
        for (j = 0; j < 120; j++);
}

void main() {
    // Cau hinh ban dau
    P1 = 0x00;
    
    while(1) {
        P1_0 = 1;  // Bat den LED
        taoTre(500);
        P1_0 = 0;  // Tat den LED
        taoTre(500);
    }
}

Ví dụ trên cho thấy lập trình giao diện phần cứng thực chất là việc cấu hình các thanh ghi đặc biệt của vi điều khiển. Phần tiếp theo sẽ đề cập đến các kỹ thuật tương tác phần cứng phức tạp hơn.

2. Kỹ thuật quét bàn phím ma trận

2.1 Nguyên lý hoạt động của bàn phím ma trận

Bàn phím ma trận được cấu tạo từ các phím được sắp xếp theo hàng và cột. Phương pháp này cho phép xác định phím được nhấn thông qua tọa độ hàng-cột, đồng thời giảm đáng kể số lượng chân I/O cần thiết.

2.1.1 Cơ chế nhận diện phím

Mỗi phím được đặt tại giao điểm của một hàng và một cột. Khi không có phím nào được nhấn, các điểm giao đó ở trạng thái trở kháng cao. Khi phím được nhấn, mạch giữa hàng và cột tương ứng sẽ được nối tắt, tạo ra sự thay đổi mức điện áp có thể phát hiện được.

2.1.2 Kết nối phần cứng

Mỗi phím nối giữa một đường hàng và một đường cột. Các đường này được kết nối trực tiếp đến các chân GPIO của vi điều khiển. Cần lưu ý các thông số điện như điện dung và trở kháng để đảm bảo mạch hoạt động ổn định ở tần số mong muốn.

2.2 Lập trình phần mềm cho bàn phím ma trận

2.2.1 Thuật toán quét phím

Để phát hiện trạng thái các phím, cần sử dụng thuật toán quét cụ thể. Phương pháp quét tuần tự theo hàng hoạt động bằng cách lần lượt đặt từng hàng ở mức thấp và đọc trạng thái các cột.

// Ham quet ban phim ma tran
int quetBanPhim() {
    unsigned char hang, cot;
    unsigned int maskHang, maskCot;
    
    for (hang = 0; hang < 4; hang++) {
        maskHang = (1 << hang);
        
        // Dat tat ca cac hang ve muc cao truoc
        PORT_HANG = 0xFF;
        // Dat hang hien tai ve muc thap
        PORT_HANG &= ~maskHang;
        
        // Kiem tra tat ca cac cot
        for (cot = 0; cot < 4; cot++) {
            maskCot = (1 << cot);
            if ((PORT_COT & maskCot) == 0) {
                // Phat hien muc thap o cot, xac dinh phim
                return (hang * 4) + cot;
            }
        }
    }
    return -1;  // Khong co phim nao duoc nhan
}

Giải thích thuật toán: Hàm quetBanPhim thực hiện quét lần lượt từng hàng bằng cách đặt mức thấp và kiểm tra trạng thái các cột. Khi phát hiện cột nào ở mức thấp, tọa độ phím được xác định.

2.2.2 Xử lý nhiễu và tối ưu phản hồi

Do hiện tượng rebound (dao động tiếp xúc), phím có thể tạo ra nhiều lần chuyển đổi trạng thái trong thời gian ngắn. Việc xử lý nhiễu là cần thiết để đảm bảo hoạt động ổn định.

// Ham xu ly nhieu phim
int xuLyNhieu(int trangThai) {
    if (trangThai) {
        taoTreMs(15);  // Tre 15ms
        if (trangThai == docTrangThai()) {
            // Cho den khi phim duoc tha
            while(docTrangThai() == trangThai);
            return 1;  // Xac nhan phim duoc nhan
        }
    }
    return 0;  // That bai do nhieu
}

Phân tích: Hàm xuLyNhieu thực hiện kiểm tra hai lần với khoảng trễ ngắn. Nếu trạng thái giống nhau sau khoảng trễ, phím được xác nhận là đã được nhấn thực sự.

Các chiến lược tối ưu bao gồm: triển khai chức năng nhấn giữ và nhấn đúp trong phần mềm, hoặc bổ sung mạch RC bên ngoài để cải thiện độ ổn định.

3. Giao tiếp và sử dụng IC thời gian thực DS1302

DS1302 là IC đồng hồ thời gian thực phổ biến với ưu điểm tiêu thụ điện năng thấp, độ chính xác cao và dễ dàng giao tiếp. Chương này sẽ hướng dẫn cấu trúc, giao thức giao tiếp và cách sử dụng DS1302 trong các dự án vi điều khiển.

3.1 Tổng quan về IC DS1302

3.1.1 Cấu trúc và tính năng

DS1302 bao gồm các khối chức năng: bộ dao động, bộ đếm thời gian, cổng I/O nối tiếp và logic điều khiển. IC hỗ trợ định dạng 24 giờ và 12 giờ, có thể cấu hình đọc ghi dữ liệu thời gian ở dạng nhị phân hoặc BCD. Ngoài ra, DS1302 còn cung cấp ngõ ra sóng vuông có thể lập trình.

Các tính năng chính:

  • Thiết kế tiết kiệm năng lượng với pin dự phòng
  • Giao tiếp nối tiếp đơn giản với vi điều khiển
  • Có ngõ ra xung clock lập trình được
  • Hỗ trợ định dạng BCD và nhị phân cho thời gian và ngày tháng

3.1.2 Kết nối phần cứng với vi điều khiển

DS1302 sử dụng ba chân để giao tiếp: SCLK (xung clock), I/O (dữ liệu vào/ra) và RST (reset). Các chân này cần được kết nối tương thích với mức điện áp của vi điều khiển.

// Cau hinh chan cho DS1302
void khoiTaoDS1302() {
    // Dat cac chan SCLK, IO, RST la dau ra
    SCLK_PIN = 0;    // Chan SCLK
    IO_PIN = 0;      // Chan I/O
    RST_PIN = 0;     // Chan RST
}

3.2 Giao thức giao tiếp và lập trình

3.2.1 Phân tích giao thức nối tiếp

DS1302 sử dụng giao thức truyền thông nối tiếp đồng bộ. Dữ liệu được truyền theo từng bit theo xung clock SCLK. Mỗi lần giao tiếp bắt đầu bằng một byte lệnh, theo sau là byte dữ liệu tương ứng.

3.2.2 Đọc và ghi dữ liệu thời gian

Để đọc hoặc ghi dữ liệu thời gian, cần gửi byte lệnh chứa các bit điều khiển, địa chỉ thanh ghi và bit bảo vệ ghi.

// Doc du lieu thoi gian tu DS1302
void docThoiGian() {
    unsigned char giay, phut, gio, thu, ngay, thang, nam;
    
    // Dung bo dem thoi gian de doc
    guiByteLenh(DIA_CHI_GIAY, 0x80);
    giay = docByte(DIA_CHI_GIAY);
    phut = docByte(DIA_CHI_PHUT);
    gio = docByte(DIA_CHI_GIO);
    thu = docByte(DIA_CHI_THU);
    ngay = docByte(DIA_CHI_NGAY);
    thang = docByte(DIA_CHI_THANG);
    nam = docByte(DIA_CHI_NAM);
    
    // Xu ly chuyen doi BCD sang dang thap phan
}

// Cai dat thoi gian cho DS1302
void datThoiGian(unsigned char gio, unsigned char phut, unsigned char giay) {
    guiByteLenh(DIA_CHI_GIAY, giay & 0x7F);
    guiByteLenh(DIA_CHI_PHUT, phut & 0x7F);
    guiByteLenh(DIA_CHI_GIO, gio | 0x80);  // Kich hoat che do 24h
}

Lưu ý: Các hàm guiByteLenh và docByte cần được triển khai dựa trên kết nối phần cứng cụ thể.

4. Điều khiển hiển thị với LCD1602

4.1 Nguyên lý hiển thị và kỹ thuật giao tiếp

4.1.1 Khởi tạo và cấu hình màn hình

LCD1602 là module hiển thị ký tự có khả năng hiển thị 16 ký tự mỗi dòng, với 2 dòng. Để sử dụng LCD1602, cần thực hiện quá trình khởi tạo để cấu hình chế độ hiển thị.

Quá trình khởi tạo bao gồm:

  1. Chọn chế độ truyền dữ liệu (4 bit hoặc 8 bit)
  2. Cấu hình chế độ hiển thị (bật/tắt hiển thị, con trỏ)
  3. Thiết lập hướng di chuyển con trỏ và ký tự
#include <reg51.h>

#defineCong LCD P2

// Ham tre
void tre(unsigned int ms) {
    unsigned int i, j;
    for (i = ms; i > 0; i--)
        for (j = 110; j > 0; j--);
}

// Gui lenh den LCD
void guiLenh(unsigned char lenh) {
    CongLCD = lenh;
    RS = 0;   // Chon thanh ghi lenh
    RW = 0;   // Chon che do ghi
    EN = 1;   // Tao xung enable
    tre(1);
    EN = 0;
}

// Khoi tao LCD
void khoiTaoLCD() {
    guiLenh(0x38);  // Che do 8 bit, 2 dong, font 5x7
    guiLenh(0x0C);  // Bat hien thi, tat con tro
    guiLenh(0x06);  // Tang dia chi tu dong
    guiLenh(0x01);  // Xoa man hinh
    tre(2);
}

Giải thích: Hàm guiLenh gửi các mã lệnh đến LCD, trong khi khoiTaoLCD thực hiện chuỗi lệnh khởi tạo theo thứ tự. Mỗi lệnh cần có khoảng trễ để LCD xử lý xong.

4.1.2 Cơ chế hiển thị ký tự và đồ họa

Sau khi khởi tạo, có thể hiển thị ký tự bằng cách gửi mã ký tự tương ứng. LCD sử dụng bộ tạo ký tự nội (CGROM) để chuyển mã thành ma trận điểm ảnh.

// Hien thi mot ky tu
void hienThiKyTu(unsigned char kiTu) {
    CongLCD = kiTu;
    RS = 1;   // Chon thanh ghi du lieu
    RW = 0;
    EN = 1;
    tre(1);
    EN = 0;
}

Để hiển thị đồ họa tùy chỉnh, cần ghi trực tiếp dữ liệu ma trận điểm vào bộ nhớ CGRAM của LCD. Mỗi ký tự tùy chỉnh chiếm 8 byte dữ liệu ma trận điểm 5x8.

// Hien thi hinh anh tuy chinh
unsigned char mangHinh[] = {0x00, 0x00, 0x10, 0x08, 0x08, 0x10, 0x00, 0x00};

// Dat dia chi va hien thi hinh
void hienThiHinhTuyChinh() {
    unsigned char i;
    guiLenh(0x80);  // Dat dia chi DDRAM dong 1
    for (i = 0; i < 8; i++) {
        hienThiKyTu(mangHinh[i]);
    }
}

5. Ứng dụng tổng hợp trong dự án vi điều khiển

5.1 Nền tảng lập trình C51

5.1.1 Cú pháp C51 và cấu hình môi trường

C51 là phiên bản ngôn ngữ C dành cho họ vi điều khiển 8051, có các đặc điểm riêng như thao tác bit và truy cập thanh ghi đặc biệt.

  • Cú pháp quan trọng: C51 cho phép thao tác trực tiếp trên các bit của cổng, ví dụ P1^0 = 1; để đặt chân P1.0 lên mức cao.
  • Cấu hình môi trường: Phần mềm Keil uVision là môi trường phát triển phổ biến cho C51, bao gồm trình biên dịch, công cụ gỡ lỗi và nạp chương trình.

5.1.2 Xử lý ngắt và ứng dụng bộ định thời

Ngắt và bộ định thời là hai thành phần không thể thiếu trong nhiều ứng dụng vi điều khiển.

  • Xử lý ngắt: C51 hỗ trợ nhiều mức ưu tiên ngắt. Hàm phục vụ ngắt cần sử dụng lệnh IRET để trả về.
  • Bộ định thời: Vi điều khiển C51 tích hợp hai bộ định thời (Timer0 và Timer1) có thể sử dụng cho tạo ngắt định thời hoặc đếm xung.

5.2 Thực hành thiết kế phần cứng hệ thống nhúng

5.2.1 Thiết kế mạch và bố trí PCB

Thiết kế phần cứng là giai đoạn quan trọng bao gồm vẽ sơ đồ nguyên lý và bố trí mạch in.

  • Thiết kế mạch: Cần bố trí hợp lý nguồn và đường mass, chọn linh kiện phù hợp với các thông số kỹ thuật mong muốn.
  • Bố trí PCB: Phân chia theo khối chức năng, bố trí các linh kiện để giảm nhiễu tín hiệu và giảm chiều dài đường truyền.

5.2.2 Gỡ lỗi và tối ưu hóa hiệu suất

Gỗ lỗi hệ thống sử dụng các thiết bị như máy hiện sóng và máy phân tích logic để quan sát tín hiệu và xác minh hoạt động của mạch.

Tối ưu hóa hiệu suất có thể thực hiện ở cả phần cứng (cải thiện mạch, sử dụng linh kiện tốc độ cao) và phần mềm (tối ưu code, quản lý bộ nhớ).

Thẻ: vi điều khiển 8051 C51 bàn phím ma trận DS1302

Đăng vào ngày 10 tháng 10 lúc 23:35