Site icon TAPIT

Hướng dẫn sử dụng chức năng UART IDLE DMA

Khi tìm hiểu UART trên STM32, các bạn thường tìm hiểu về cách hoạt động của giao tiếp này qua các phương pháp quen thuộc như polling, interrupt hay DMA.

Một phương pháp tối ưu hơn đó là sử dụng ngắt IDLE kết hợp với DMA. Ngắt IDLE hay còn được gọi là ngắt phát hiện dòng nhàn rỗi, xảy ra khi một khung IDLE được phát hiện. Ưu điểm của nó dùng để nhận được dữ liệu có kích thước bất kỳ không biết trước. Trong bài viết này, chúng ta sẽ cùng nhau thực hành về UART IDLE DMA được xây dựng sẵn trên thư viện HAL.

HƯỚNG DẪN THỰC HÀNH

Bước 1: Tạo mới một project, chọn vi điều khiển, đặt tên cho project.

Bước 2: Tại mục System Core > SYS > Serial Wire.

Bước 3: Cấu hình USART. Mình sử dụng USART2 để thực hiện giao tiếp. Các thông số cấu hình:

Bước 4: Nhấn vào biểu tượng sinh code.

Trước tiên, các bạn hãy mở và đọc qua mô tả hàm được hỗ trợ bởi thư viện HAL. Vào Divers > STM32Fxxx_HAL_Driver > Src, tìm đến file stm32fxxx_hal_uart_ex.c

Trong bài viết này, mình sẽ tập trung thực hiện bằng phương pháp DMA.

Trước tiên, khai báo một bộ đệm để lưu trữ dữ liệu:

Trong hàm main, chúng ta gọi hàm nhận dữ liệu bằng IDLE DMA. Tuy nhiên, khi sử dụng DMA sẽ sinh ra hai ngắt là HalfReception và EndReception. Chúng ta nên tắt ngắt nhận HalfReception vì nó sẽ gọi hàm RxEventCallback khi nhận được một nữa dữ liệu.

&huart2: là UART2 mà chúng ta đang sử dụng.

rxBuffer: là bộ đệm mà dữ liệu sẽ lưu dữ liệu vào đây.

RX_SIZE: số phần tử sẽ được nhận.

Khi sảy ra sự kiện ngắt, hàm Callback sẽ được gọi và chúng ta có thể biết được kích thước của dữ liệu đã nhận.

Mã chương trình

Mở debug, sử dụng Hercules để truyền dữ liệu, quan sát bộ đệm rxBuffer.

Đầu tiên, gửi chuỗi gồm 6 ký tự “abcd\r\n”, ta thấy dữ liệu được lưu từ vị trí 0 đến vị trí 6, giá trị của biến size là 6.

Tiếp theo, gửi chuỗi “123456\r\n” có kích thước lớn hơn chuỗi đầu  tiên. Dữ liệu được lưu từ vị trí 0 đến vị trí thứ 7, và giá trị size là 8.

Gửi lại chuỗi thứ nhất, ta thấy dữ liệu lưu từ vị trí 0 đến vị trí thứ 5 và vẫn còn 2 ký tự cũ “\r\n” ở vị trí thứ 6 và thứ 7.

Có thể nhận thấy rằng, dữ liệu luôn được lưu từ vị trí đầu tiên của bộ đệm. Việc này rất tiện cho việc xử lý chuỗi. Không giống như phương pháp DMA, vị trí lưu dữ liệu mới luôn nằm sau vị trí cuối cùng của dữ liệu trước đó.

Tiếp theo, chúng ta gửi một chuỗi có độ dài lớn hơn kích thước bộ đệm “abcd9876543\r\n”.

Phần dữ liệu dư sẽ ghi đè lên dữ liệu cũ từ vị trí đầu tiên của bộ đệm.

Qua bài viết này, hi vọng các bạn có thể thấy được ưu điểm của phương pháp sử dụng ngắt IDLE kết hợp DMA, các chức năng được xây dựng sẵn trong thư viện HAL. Từ đó, phát triển thêm các ứng dụng liên quan đến việc nhận truyền các dữ liệu có kích thước lớn, cải thiện được hiệu suất của thiết bị.

Chúc các bạn thành công!

Cộng tác viên mảng Nhúng tại Cộng đồng Kỹ thuật TAPIT

Hoàng Văn Bình

Tìm hiểu thêm:
Tổng hợp hướng dẫn Internet of Things với NodeMCU ESP8266 và ESP32
Tổng hợp các bài hướng dẫn Lập trình vi điều khiển STM32
[HỌC ONLINE: LẬP TRÌNH C CHO HỆ THỐNG NHÚNG VÀ CÁC THIẾT BỊ IOTS]
[HỌC ONLINE: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX–M]
Fanpage Cộng đồng Kỹ thuật TAPIT: TAPIT – Learning, Research and Sharing Community