Bài 11: Lập trình STM32 với Giao thức UART

Giao thức UART với STM32

Lập trình STM32 với giao thức UART sẽ cung cấp cho các bạn kiến thức:

  • Giao thức UART là gì
  • Cách cấu hình giao thức UART STM32 trên CubeMX
  • Cách sử dụng giao thức UART trong lập trình

Bài 11 thuộc serie Học lập trình STM32 từ A tới Z

Giao thức UART là gì?

Khái quát về UART

UART (Universal Asynchronous Receiver/Transmitter) là một chuẩn giao tiếp nối tiếp không đồng bộ giữa MCU và các thiết bị ngoại vi.

Chuẩn UART là chuẩn giao tiếp điểm – điểm, nghĩa là trong mạng chỉ có hai thiết bị, mỗi thiết bị vừa là bên truyền (transmitter) vừa là bên nhận (receiver).

h1 3

Cách hoạt động của giao thức UART

UART là giao thức truyền thông không đồng bộ, nghĩa là không có dây xung Clock. Các thiết bị hiểu được nhau là nhờ đã cài đặt giống nhau từ trước. Giống như 2 người nói chuyện qua bộ đàm: cả hai phải dùng chung một thứ tiếng và nói cùng một tốc độ thì mới nghe hiểu nhau.

UART là truyền thông song công (Full duplex), nghĩa là tại một thời điểm có thể truyền và nhận đồng thời.

Trong đó quan trọng nhất là Baud rate (tốc độ baud), là số bit được truyền trong 1 giây. Ví dụ baud 9600 thì mỗi bit kéo dài khoảng 1/9600 ≈ 104µs. Baud rate phải được cài đặt giống nhau ở cả bên gửi và bên nhận.

Sau đó là định dạng gói tin.

Định dạng gói tin như sau:

H2 1

Start Bit

Start bit còn được gọi là bit đồng bộ, được đặt trước dữ liệu thực tế. Khi không truyền, đường dữ liệu luôn được giữ ở mức điện áp cao. Để bắt đầu truyền, bên truyền kéo đường dữ liệu từ mức cao (1) xuống mức thấp (0). Bên nhận phát hiện sự chuyển đổi từ cao xuống thấp này và bắt đầu đọc dữ liệu. Thông thường chỉ có một start bit.

Stop Bit

Stop bit được đặt ở cuối gói dữ liệu, có thể dài 1, 1.5 hoặc 2 bit, nhưng thường chỉ sử dụng 1 bit. Để kết thúc gói, UART giữ đường dữ liệu ở mức điện áp cao.

Parity Bit

Bit chẵn lẻ giúp bên nhận kiểm tra dữ liệu nhận được có đúng hay không. Đây là cơ chế kiểm tra lỗi đơn giản, có hai kiểu là kiểm tra chẵn (Even) và kiểm tra lẻ (Odd). Trên thực tế bit này không được sử dụng rộng rãi nên không bắt buộc.

Data frame

Các bit dữ liệu chứa dữ liệu thực được truyền từ bên gửi đến bên nhận. Độ dài khung dữ liệu thường từ 5 đến 8 bit, nếu không dùng bit chẵn lẻ thì có thể dài tới 9 bit. Bit thấp nhất (LSB) của dữ liệu được truyền đi trước tiên.

Cấu hình giao thức UART STM32 trong Cube MX

Ở bài này chúng ta sẽ thực hành truyền UART từ bộ UART1 lên máy tính, sử dụng Baud rate = 9600, các cài đặt khác để mặc định.
Trong chế độ sử dụng ngắt, ta sẽ kiểm tra chuỗi gửi đến, nếu thấy kí tự Enter thì gửi ngược lại.

Trong chế độ DMA, ta sẽ cho dữ liệu truyền thẳng vào Buffer để thấy sự khác nhau giữa cách hoạt động của ngắt và DMA.

Các bạn phải chuẩn bị bộ chuyển đổi UART to USB như Bài 2 mình giới thiệu, và phần mềm Hercules Terminal.

Xem hướng dẫn tại: Hướng dẫn sử dụng Hercules Terminal

Đầu tiên các bạn mở CubeMX lên, chọn chip STM32F103C8, trong SYS Debug chọn Serial Wire. Mình đã nói rõ trong Bài 3 nhé.

Trong tab Connectivity chọn USART1.

H3 8

Mode: Asynchronous (không đồng bộ)

Hardware Flow Control: Disable

NVIC Settings: tick vào bật ngắt USART1

H4 7

Đặt tên, chọn Toolchain rồi Gen code.

H5 8

Lập trình giao thức UART trên Keil C

Mở project, trong main.c khai báo như sau:

2 Buffer để truyền và nhận dữ liệu

1 biến nhận Rx data

1 biến lưu vị trí ghi tiếp theo vào Rx Buffer

1 cờ báo nhận thành công để gửi TX

H6 8

Tìm hàm HAL_UART_RxCpltCallback, sau đó viết code như sau:

H7 10

Nếu u8_RxData nhận được khác kí tự Enter (giá trị 13 trong bảng ASCII), ghi giá trị u8_RxData vào u8_RxBuf, sau đó tăng giá trị _RxIndex.

Nếu RxData là kí tự Enter, xóa biến _RxIndex về 0 và bật cờ Tx.

Gọi hàm HAL_UART_Receive_IT(&huart1, &u8_RxData, 1); để tiếp tục nhận byte tiếp theo.

Lưu ý: Hàm HAL_UART_Receive_IT() chỉ nhận đúng số byte được yêu cầu rồi tắt ngắt nhận. Nếu quên gọi lại nó ở cuối Callback thì STM32 chỉ nhận được đúng 1 kí tự đầu tiên rồi “điếc” luôn.

Trước while(1) chúng ta gửi qua UART dữ liệu ban đầu trong u8_TxBuff là “Hello anh em!!!”.

Sau đó bật nhận dữ liệu bằng ngắt.

H8 8

Trong while(1):

Kiểm tra cờ truyền UART có được bật lên không.

Nếu có thì sao chép giá trị RxBuff sang TxBuff, sau đó truyền đi và xóa cờ TX.

Nhấn F7 build và nạp chương trình vào chip.

Kết nối STM32 với mạch UART to USB như sơ đồ sau: PA9 (TX) nối RX của mạch chuyển đổi, PA10 (RX) nối TX, GND nối chung.

Sơ đồ đấu nối STM32 UART1 với cáp USB to UART: PA9 (TX) nối RX, PA10 (RX) nối TX, GND nối GND

Lưu ý: TX của bên này phải nối vào RX của bên kia và ngược lại (nối chéo). Nối TX với TX là lỗi rất hay gặp, khi đó Terminal sẽ không nhận được gì. Đừng quên nối chung GND nhé.

H9

Sau đó bật Hercules Terminal lên. Kiểm tra cổng COM của mạch UART to USB bằng cách nhấn chuột phải vào biểu tượng My Computer -> Manage.

H10 7

Mở Device Manager -> Ports, ta thấy port đang sử dụng là COM4 với driver là CH340.

H11 7

Trong Terminal, chuyển sang tab Serial, mục Name chọn cổng COM bạn đang dùng, với mình là COM4.

Baud đặt là 9600, còn lại để mặc định rồi nhấn Open.

H12 6

Nhấn Reset trên mạch để chương trình chạy lại từ đầu, ta sẽ thấy mạch gửi lên chuỗi chào đầu tiên. Nhập tin nhắn bạn cần gửi xuống mạch và kết thúc bằng <CR> (kí tự Enter trong ASCII), mạch sẽ gửi lại đúng tin nhắn đó.

H13 4

Truyền nhận dữ liệu bằng DMA

Để truyền nhận dữ liệu sử dụng DMA các bạn làm như sau.

Trong CubeMX, tab USART1 Configuration -> DMA Settings.

Các bạn nhấn Add, DMA Request chọn USART1_RX, Mode Circular (chỉ cần gọi 1 lần, DMA sẽ liên tục chuyển dữ liệu từ ngoại vi về bộ nhớ), Data Width là Byte.

H14 4

Nhấn Gen Code và Close.

Keil C sẽ báo Reload lại file, bạn nhấn OK.

H15 2

Trong hàm Callback ta comment hết các lệnh cũ, viết lại hàm Transmit.

H16 2

Trong main() ta gọi hàm HAL_UART_Receive_DMA thay cho HAL_UART_Receive_IT, và comment toàn bộ code trong while(1).

H17 2

Build, nạp chương trình và xem kết quả.

H18 1

Ta thấy rằng chỉ khi nhập đủ 20 kí tự, bằng đúng độ dài của Rx_Buffer, thì chương trình mới nhảy vào ngắt và truyền dữ liệu lại. Vì vậy khi nhận UART bằng DMA nên sử dụng các frame có độ dài cố định.

Kết luận

Giao thức UART được sử dụng rất nhiều trong các sản phẩm nhúng. Việc lập trình giao thức này cũng không quá khó khăn, chỉ cần bạn đọc kĩ phần hướng dẫn, chắc chắn sẽ làm được nhé!

5/5 - (1 bình chọn)

25 những suy nghĩ trên “Bài 11: Lập trình STM32 với Giao thức UART”

  1. Nguyễn văn công nói:

    Mình muốn nhờ chút có cách nào đọc mã giao tiếp giữa 2 con stm32 nối với nhau theo chuẩn uart không, mình đã dùng một mạch USB TTL uart nối song song với dây nối giữa 2 mạch giao đọc bằng máy tính mà mã truyền của nó không đúng.

  2. Manh Duc nói:

    Em hỏi chút ạ, có cách nào để giao tiếp uart giữa stm32 với esp8266 không. Vì e truyền từ stm32 sang esp8266 1 chuỗi mà n không nhận.

  3. Dũng nguyễn nói:

    Anh ơi cho em hỏi chút với ạ . Cái chỗ Kết nối STM32 vào UART to USB là phải có cái mạch chuyển UART USB mới dùng được cái hercules terminal hả anh.

  4. dong tran nói:

    Cho em hỏi: Em dùng DMA để nhận dữ liệu, nhưng khi mảng dữ liệu nhận, tràn. Thì nó không ghi đè lên, hay xóa đi các kí tự cũ đi, là sao vậy anh?

  5. nguyễn tú nói:

    cho em hỏi. Truyền một gói tin từ máy tính xuống STM32 có định dạng như sau:
    *|X|Data|#( bao gồm 3 byte, trong đó “*” là kí tự bắt đầu,”#” là ký tự kết thúc,”X”( X=1->16) là byte khai báo kích thước của data;” data” là các ký tự, có kích thước từ 1 đến 16byte.
    khi nhận đúng định dạng gói tin: hiển thị nội dung gói tin lên LCD 16×2 đồng thời truyền trở về máy tính chữ”OK” thông qua UART. KHi nhận sai gói định dạng: không thay đổi nội dung LCD, đồng thời truyền trở về máy tính chữ” ERROR” thông qua UART

  6. Trường kelvin nói:

    anh ơi cho em hỏi làm thế nào để sau khoảng 1-3s thì data truyền sau sẽ ghi đè lên data truyền trc ạ???

  7. huy nói:

    lập trình gửi dữ liệu từ Herculus qua protues và
    hiển thị dữ liệu lên LCD 16×2 .. thì làm thêm code gì nửa anh ạ

  8. Ngọc nói:

    Anh ơi, nếu em dùng UART từ vi điều khiển qua RS 485 rồi mới vào máy tihs thì cũng làm tương tự đúng không hả anh?
    Em cảm ơn ạ!

  9. huynh khanh nói:

    anh ơi cho em hỏi là em giao tiếp giữa stm32f411 với máy tình qua con ft232 thì khi nhận dữ liệu nó bị lỗi, em xem baudrate rồi mà vẫn bị

  10. Thắng nói:

    em có làm như a hướng dẫn, nhưng nó chỉ nhận được dữ liệu từ STM32 truyền sang máy tính, nhưng em gửi từ máy tính về STM32 thì nó k hiện lên kí tự

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *