Bài viết 17 thuộc series STM32F103C8T6 tập trung theo hướng “học để làm được việc”. Với chủ đề Lập trình LCD1602 với STM32F103C8T6, bạn sẽ đi từ lý thuyết cốt lõi đến quy trình triển khai thực tế trong phòng lab. Nội dung được thiết kế để sinh viên, kỹ thuật viên bảo trì và người mới chuyển từ PLC sang Embedded đều có thể áp dụng ngay vào project mẫu.

LCD1602 là thiết bị hiển thị phổ biến trong đào tạo embedded vì dễ học, trực quan và chi phí thấp. Dù đơn giản, LCD vẫn là nơi thể hiện rõ kỹ năng tổ chức driver và tối ưu cập nhật giao diện.

LCD1602 với STM32
Minh họa cho bài 17: Lập trình LCD1602 với STM32F103C8T6.

1. Mục tiêu bài học

Bài đi theo hai hướng triển khai: giao tiếp song song 4-bit và giao tiếp qua module I2C, giúp bạn so sánh ưu nhược điểm để chọn theo mục tiêu dự án.

  • Hiểu nguyên lý điều khiển LCD1602 ở mode 4-bit.
  • Triển khai LCD qua I2C (PCF8574) để tiết kiệm chân MCU.
  • Hiển thị dữ liệu ADC/sensor theo định dạng dễ đọc.
  • Xử lý lỗi ký tự và lỗi hiển thị phổ biến.

Sau khi hoàn thành, bạn nên tự trả lời được ba câu hỏi: hệ thống cần đo/điều khiển đại lượng gì, vòng đời xử lý dữ liệu chạy theo chu kỳ nào, và cơ chế bảo vệ lỗi nào cần có để hệ thống ổn định khi chạy liên tục ngoài hiện trường.

2. Kiến thức nền tảng

STM32F103C8T6 dùng lõi ARM Cortex-M3, phù hợp để học đồng thời kiến trúc MCU và phương pháp lập trình thời gian thực. Khi học theo lộ trình chuẩn, bạn nên nắm đồng thời phần cứng (clock, GPIO, bus, nguồn), firmware (HAL/LL, ngắt, timer), và phương pháp test (scope, logic analyzer, UART log). Việc kết hợp đủ ba lớp kiến thức giúp quá trình debug nhanh hơn nhiều so với chỉ học code thuần.

  • Timing và lệnh cơ bản của controller HD44780.
  • Sự khác nhau giữa write command và write data.
  • Định dạng chuỗi trong C cho hiển thị số.
  • Kỹ thuật refresh từng phần màn hình.

Trong quá trình thực hành, bạn nên duy trì checklist kiểm thử ở từng vòng: xác nhận wiring, xác nhận xung clock, xác nhận trạng thái ngoại vi, sau đó mới kiểm tra thuật toán. Cách làm này giảm đáng kể lỗi dây chuyền và giúp nhóm dự án phối hợp hiệu quả giữa phần cứng và phần mềm.

3. Phân tích kỹ thuật

LCD 4-bit: kiểm soát trực tiếp tín hiệu

Mode 4-bit cần nhiều chân hơn nhưng dễ hiểu bản chất giao tiếp LCD. Bạn tự điều khiển EN, RS và 4 data line, từ đó nắm rõ timing và thứ tự gửi nibble cao/thấp.

  • Bắt buộc khởi tạo đúng chuỗi lệnh theo datasheet.
  • Delay ngắn sai có thể gây hiển thị ký tự rác.
  • Phù hợp bài học nền tảng về giao tiếp song song.

LCD I2C qua PCF8574

Module I2C giảm số chân đáng kể, phù hợp project nhiều ngoại vi. Tuy nhiên cần chú ý địa chỉ I2C và mapping bit tới chân LCD do mỗi module có thể khác nhau.

  • Scan địa chỉ I2C trước khi khởi tạo LCD.
  • Kiểm tra backlight control theo module thực tế.
  • Đóng gói driver dạng lcd_write_cmd/data thống nhất.

Hiển thị dữ liệu đo một cách ổn định

Không nên clear toàn màn hình liên tục vì gây nhấp nháy. Cập nhật theo vùng thay đổi hoặc theo chu kỳ 200-500 ms sẽ cho trải nghiệm hiển thị mượt hơn.

  • Dùng sprintf có kiểm soát độ dài chuỗi.
  • Canh lề cố định để số đo không nhảy cột.
  • Tách task đọc cảm biến và task update LCD.

Từ góc nhìn hệ thống, chủ đề này không chỉ là “chạy được chức năng”, mà còn là bài toán tối ưu độ tin cậy, độ trễ xử lý, khả năng mở rộng khi thêm cảm biến hoặc thêm kênh truyền thông. Nếu ngay từ đầu bạn chuẩn hóa cấu trúc code theo module driver/app/service thì giai đoạn mở rộng về sau sẽ nhẹ hơn rất nhiều.

4. Các bước thực hiện

Ưu tiên viết driver theo API trừu tượng để có thể đổi backend 4-bit/I2C mà không phải sửa logic ứng dụng.

  1. Chọn phương án 4-bit hoặc I2C theo số chân còn trống.
  2. Kết nối wiring, kiểm tra nguồn và biến trở chỉnh tương phản.
  3. Khởi tạo LCD theo đúng chuỗi lệnh yêu cầu.
  4. Viết API lcd_set_cursor, lcd_print.
  5. Đọc ADC và hiển thị điện áp/giá trị cảm biến lên LCD.
  6. Tối ưu chu kỳ refresh để tránh nhấp nháy.

Ở mỗi bước, bạn nên lưu log kỹ thuật (ảnh wiring, ảnh cấu hình CubeMX, thông số timer/UART/ADC, snapshot kết quả đo). Bộ log này giúp giảng viên hoặc trưởng nhóm đánh giá tiến độ nhanh và giảm thời gian trao đổi khi cần hỗ trợ từ xa.

5. Ví dụ cập nhật LCD với dữ liệu ADC

Code dưới đây là mẫu rút gọn theo HAL Library, tập trung phần cốt lõi để bạn nhìn rõ luồng xử lý. Khi đưa vào dự án thực, hãy tách code thành các module rõ ràng, thêm kiểm tra lỗi trả về và timeout cho mọi giao tiếp ngoại vi.

char line[17];
float voltage = (adc_raw * 3.3f) / 4095.0f;

lcd_set_cursor(0, 0);
lcd_print("ADC Monitor");

snprintf(line, sizeof(line), "V=%.2fV Raw=%4u", voltage, adc_raw);
lcd_set_cursor(0, 1);
lcd_print(line);

Nguyên tắc quan trọng: giữ hàm ngắt ngắn gọn, xử lý nặng chuyển về vòng lặp chính hoặc task nền; dùng biến trạng thái rõ ràng để tránh race condition; thêm timeout cho mọi thao tác có thể block. Đây là nền tảng để firmware ổn định khi chạy lâu dài.

6. Lỗi thường gặp

Phần lớn lỗi trong STM32F103C8T6 đến từ cấu hình chưa đồng bộ giữa clock, ngoại vi và wiring thực tế. Nếu bạn xử lý theo thứ tự “đọc triệu chứng -> khoanh vùng lớp lỗi -> test độc lập từng khối”, thời gian debug sẽ giảm rất rõ.

  • Sai wiring RS/EN/D4-D7 ở mode 4-bit.
  • Không chỉnh tương phản nên tưởng LCD không hoạt động.
  • Địa chỉ I2C module LCD không đúng.
  • Clear màn hình quá thường xuyên gây nhấp nháy.
  • Chuỗi in quá dài làm tràn bố cục 16 ký tự.

Giảm tần suất cập nhật LCD để tiết kiệm tài nguyên và tránh nhấp nháy giao diện.

7. Bài tập thực hành

Để chuyển từ mức “hiểu lý thuyết” sang “làm chủ kỹ năng”, bạn nên làm các bài tập sau theo đúng thứ tự từ dễ đến khó, sau mỗi bài đều ghi lại tiêu chí đạt/chưa đạt và thông số đo thực tế.

  1. Hiển thị đồng thời nhiệt độ và điện áp trên 2 dòng LCD.
  2. Tạo menu đơn giản điều khiển bằng 2 nút nhấn.
  3. So sánh tốc độ cập nhật giữa LCD 4-bit và LCD I2C.
  4. Viết driver thống nhất để chuyển đổi 4-bit/I2C bằng macro.

Khuyến nghị chấm bài theo rubric: đúng chức năng (40%), độ ổn định 30 phút chạy liên tục (30%), chất lượng cấu trúc code (20%), tài liệu kỹ thuật và báo cáo đo kiểm (10%).

Tài liệu tham khảo

  • STMicroelectronics, STM32F103x8/B Datasheet.
  • STMicroelectronics, RM0008 Reference Manual: STM32F10xxx advanced ARM-based 32-bit MCUs.
  • STMicroelectronics, UM1850 STM32CubeMX user manual và tài liệu STM32Cube liên quan.
  • ARM, Cortex-M3 Technical Reference Manual.
  • STMicroelectronics Application Notes về GPIO, ADC, Timer, UART, I2C, SPI, DMA và Watchdog.