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 Cube MX
- 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 tiếng anh là Universal Asynchronous Reciver/Transmister một chuẩn giao tiếp không đồng bộ cho MCU và các thiết bị ngoại vi.
Chuẩn UART là chuẩn giao tiếp điểm và điểm, nghĩa là trong mạng chỉ có hai thiết bị đóng vai trò là transmister hoặc reciver.
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ó xung Clock, các thiết bị có thể hiểu được nhau nếu các Setting giống 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à Baund rate (tốc độ Baund) là khoảng thời gian dành cho 1 bit được truyền. Phải được cài đặt giống nhau ở gửi và nhận.
Sau đó là định dạng gói tin.
Định dạng gói tin như sau:
Start – Bit
Start-bit còn được gọi là bit đồng bộ hóa được đặt trước dữ liệu thực tế. Nói chung, một đường truyền dữ liệu không hoạt động được điều khiển ở mức điện áp cao. Để bắt đầu truyền dữ liệu, truyền UART kéo đường dữ liệu từ mức điện áp cao (1) xuống mức điện áp thấp (0). UART thu được thông báo sự chuyển đổi này từ mức cao sang mức thấp qua đường dữ liệu cũng như bắt đầu hiểu dữ liệu thực. Nói chung, chỉ có một start-bit.
Stop – Bit
Bit dừng được đặt ở phần cuối của gói dữ liệu. Thông thường, bit này dài 2 bit nhưng thường chỉ sử dụng 1 bit. Để dừng sóng, UART giữ đường dữ liệu ở mức điện áp cao.
Partity Bit
Bit chẵn lẻ cho phép người nhận đảm bảo liệu dữ liệu được thu thập có đúng hay không. Đây là một hệ thống kiểm tra lỗi cấp thấp & bit chẵn lẻ có sẵn trong hai phạm vi như Chẵn lẻ – chẵn lẻ cũng như Chẵn lẻ – lẻ. 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 bao gồm dữ liệu thực được truyền từ người gửi đến người nhận. Độ dài khung dữ liệu có thể nằm trong khoảng 5 & 8. Nếu bit chẵn lẻ không được sử dụng thì chiều dài khung dữ liệu có thể dài 9 bit. Nói chung, LSB của dữ liệu được truyền trước tiên sau đó nó rất hữu ích cho việc truyề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 Baundrate = 9600, các setup 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ẽ sử dụng truyền thẳng vào Buffer để biết 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 1 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 UART chọn UART1
Mode: Asynchronous (không đồng bộ)
Hard ware: Disable
NVIC Setting Tick vào bật ngắt UART
Đặt tên chọn tool chain rồi Gen code
Lập trình giao thức UART trên Keil C
Mở project trong main.c cấu hình như sau.
Khởi tạo 2 Buffer để truyền nhận dữ liệu
1 biến nhận Rx data
1 biến lưu giá trị con trỏ ghi vào Rx Buffer
1 Cờ báo nhận thành công để gửi TX
Tìm hàm RxCpltCallback sau đó cấu hình như sau
Nếu u8_RxData nhận được là 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 dữ liệu nếu có dữ liệu truyền qua.
Trước main chúng ta gửi 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
Trong while(1)
Kiểm tra cờ truyền UART nếu được bật lên.
Sao chép giá trị RxBuff cho 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ào UART to USB
Sau đó bật Hercules terminal lên, kiểm tra cổng kết nối với UART to USB bằng cách nhấn chuột phải vào biểu tượng My computer -> manager
Mở tab Device -> Ports ta thấy rằng port đang sử dụng là COM4 với driver là CH340
Trong Terminal, chuyển Tab Serial – Name chọn cổng com bạn đang dùng với mình là COM4
Baud set là 9600, còn lại để mặc định rồi ấn vào Open
Nhấn Reset trên mạch để mạch chạy từ đầu. Ta sẽ thấy mạch gửi kí tự đầu tiên. Nhập tin nhắn bạn cần gửi lên mạch và kết thúc là <CR> (kí tự Enter trong ASCII), mạch sẽ gửi lại đúng tin nhắn đó.
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 UART1 Config-> 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 sẽ truyền liên tục từ ngoại vi về bộ nhớ), Data Width là Byte
Nhấn Gen Code và Close
Trong KeilC sẽ báo Reload lại file, bạn nhấn ok
Trong hàm callback ta comment hết các hàm trước, viết lại hàm Transmit
Trong main() ta gọi hàm Recive_DMA thay cho Recive_IT, và comment toàn bộ While (1)
Build và nạp chương trình và xem kết quả.
Ta thấy rằng, chỉ khi nhấn đủ 20 giá trị = Độ 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 truyền UART 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.
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.
Bạn truyền giữa Stm32 và máy tính hay stm32 với stm32 nhỉ?
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.
Truyền bình thường mà e, ko nhận thì do e code bên esp rồi
Thế e muốn STM đọc ADC rồi UART qua ESP thì làm sao ạ?
E tách ra thành 2 phần. Phần 1 đọc ADC, phần 2 Gửi UART, data gửi chính là giá trị ADC đọc được
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.
đúng rồi em, e mua và cài driver cho nó thường là ch340 và pl2303
vậy để truyền dữ liệu thay đổi( ví dụ nhiệt độ, tốc độ) qua uart thì phải làm ntn ạ
truyền bình thường thôi em
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?
em phải tự xóa mà
anh ơi cho em hỏi uart giữa stm32 với module R305 có giống với cách anh hướng dẫn không anh
Giống nhau e nhé, vậy nên mới gọi là giao thức
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
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 ạ???
bài này anh làm ví dụ hay hơn những người khác lắm luôn.
cám ơn em
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 ạ
Trc tiên là điều khiển đc LCD16x2 sau đó là truyền dữ liệu qua lcd thay vì UART thôi e
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 ạ!
đúng rồi, về cơ bản là giống nhau
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ị
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ự