Bộ giao tiếp USART được dùng để trao đổi dữ liệu giữa MCU với các thiết bị bên ngoài dựa trên định dạng dữ liệu nối tiếp bất đồng bộ NRZ tiêu chuẩn công nghiệp. Bộ USART có hai chế độ truyền là truyền dữ liệu đồng bộ (Synchronous) và truyền dữ liệu không đồng bộ (Asynchronous). Đối với chế độ truyền đồng bộ, bộ USART của chip STM32F411VE hỗ trợ truyền 1 chiều (one-way communication) và truyền trên 1 đường truyền bán song công (half-duplex single wire communication). Với chế độ truyền không đồng bộ, bộ USART truyền dữ liệu song công (full-duplex) như hình dưới:
Để giao tiếp 2 chiều USART, MCU cần phải kết nối với thiết bị bên ngoài ít nhất 2 chân là chân TX (chân truyền dữ liệu ra bên ngoài) và chân RX (chân nhận dữ liệu từ bên ngoài). Chân TX của MCU sẽ được nối với chân RX của thiết bị ngoài và ngược lại chân RX của MCU sẽ được nối với chân TX của thiết bị ngoài. Chân SW_RX được dùng để nhận dữ liệu ở chế độ single-wire.
[HỌC ONLINE: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX – M]
Một khung truyền dữ liệu của bộ USART gồm 1 Start bit, 1 data word (8 hoặc 9 bits tùy người dùng cấu hình), 0,5/1/1,5/2 stops bits. Độ dài của 1 data word được lập trình bằng cách ghi mức logic 1 hoặc 0 vào M bit của thanh ghi USART_CR1 (chi tiết sẽ được đề cập ở phần thanh ghi phía dưới).
Về quá trình truyền USART
Một byte dữ liệu từ đường bus sẽ được lưu trong bộ đệm TDR. Khi bit cho phép truyền (TE) được set, dữ liệu sẽ được đưa xuống thanh ghi Transmit Shift Register và bit có trọng số thấp nhất (LSB) sẽ được gửi đi đầu tiên trên chân TX MCU. Sau khi truyền đi một byte, thanh ghi TDR sẽ được làm trống và byte tiếp theo có thể được truyền đi. Ở chế độ này dữ liệu của thanh ghi USART_DR chính là dữ liệu của bộ đệm TDR.
Một số bit liên quan đến quá trình truyền USART:
– TXE (Transmit data register empty):
Đây là bit thuộc thanh ghi USART_SR và được set bởi phần cứng. Bit này cho biết dữ liệu của bộ đệm TDR đã được đưa vào Transmit Shift Register và bắt đầu truyền đi. Ngoài ra bit này còn được set lên khi TDR được làm trống và dữ liệu tiếp theo có thể được ghi vào thanh ghi USART_DR mà không làm ảnh hưởng đến dữ liệu trước. Bit TXE có thể tạo ra tín hiệu ngắt nếu bit TXEIE được set. Bit này luôn luôn được reset bằng cách ghi vào thanh ghi dữ liệu.
– TC (Transmission complete):
Bit TC được set bởi phần cứng và được set lên khi MCU đã hoàn thành xong một quá trình truyền dữ liệu và bit TXE được set. Bit này có thể tạo ra tín hiệu ngắt nếu bit TCIE của thanh ghi USART_CR1 được set. Bit này có thể được reset bằng cách ghi ‘0’ vào nó hoặc bằng hoạt động đọc tại thanh ghi USART_SR sau đó ghi giá trị vào USART_DR.
Note: Khi bộ truyền USART được kích hoạt nhưng không có hoạt động truyền diễn ra thì chân TX được duy trì mức logic cao.
Về quá trình nhận USART
Khi có dữ liệu được truyền từ thiết bị bên ngoài, bit có trọng số thấp nhất của frame data đầu tiên được truyền qua chân RX của MCU và lưu vào thanh ghi Receive Shift Register. Khi một byte đã nhận xong, bit RXNE (Read data register not empty) set lên 1, dữ liệu chứa trong thanh ghi Receive Shift Register được đưa đến bộ đệm RDR, dữ liệu lúc này đã sẵn sàng để đọc. Nếu bit RXNE và bit RXNEIE (RXNE interrupt enable) cùng set lên 1 thì một tín hiệu ngắt sẽ được sinh ra. Bit RXNE được reset khi có hoạt động đọc dữ liệu trên thanh ghi USART_DR hoặc khi ghi bit ‘0’ vào nó. Tuy nhiên nếu quá trình nhận dữ liệu xảy ra các vấn đề sau thì các error flags tương ứng sẽ được set lên 1:
– Overrun error: Lỗi này xảy ra khi một byte dữ liệu được nhận trong lúc bit RXNE (Rx not empty) chưa được reset dẫn đến dữ liệu không được chuyển từ thanh ghi Shift Register qua bộ đệm RDR. Bất cứ dữ liệu nào được nhận trong quá trình overrun sẽ bị mất.
– Frame error: Lỗi này xảy ra khi stop bit không được nhận ra tại thời điểm dự kiến vì xảy ra nhiễu hay bị mất đồng bộ. Thông thường một frame data chứa 1 Stop bit và được lấy mẫu ở các thời điểm mẫu thứ 8, 9, 10.
– Noise error: Khi một bit được nhận MCU sẽ thực hiện lấy mẫu (8 hoặc 16 mẫu tùy người dùng cấu hình ở bit OVER8, thanh ghi USART_CR1) trên bit đó. Nếu 3 mẫu nằm ở vị trí trung tâm có giá trị không bằng nhau bit NF (Noise error flag) được set lên 1, lúc này dữ liệu sẽ bị bỏ qua vì đã xảy ra trục trặc trong quá trình lấy mẫu.
Một số thanh ghi quan trọng trong UART
Status register (USART_SR):
Thanh ghi này chứa các bit TXE, RXNE và TC và các error flags
Data register (USART_DR):
Thanh ghi dữ liệu chứa các dữ liệu của bộ đệm truyền (TDR) và bộ đệm nhận (RDR) vì vậy thanh ghi này có thể thực hiện một chức năng kép là đọc và ghi. USART_DR có độ dài 32 bits nhưng dữ liệu sẽ nằm từ bit 0 đến bit 8.
Baud rate register (USART_BRR):
Thanh ghi này chứa giá trị tốc độ baudrate được cài đặt. DIV_Mantissa[11:0] là thành phần trước dấu “.” và DIV_Freaction[3:0] là thành phần sau dấu “.” của tốc độ baud được quy đổi theo ví dụ sau:
Control register 1 (USART_CR1) :
Thanh ghi chứa các bit UE (USART enable), TE (Transmitter enable), RE (Receiver enable),…
Và các thanh ghi khác như: Control register 2 (USART_CR2), Control register 3 (USART_CR3), Guard time and prescaler register (USART_GTPR).
Thực hành:
Trong project mẫu này sẽ áp dụng cả 2 chế độ truyền và nhận UART trên chip STM32F411VE bằng cách truyền 1 byte kí tự từ phần mềm Hercules đến MCU, khi đã nhận xong thì MCU sẽ phản hồi lại byte đó lên màn hình để kiểm tra nhận đúng hay không. Ngoài ra ta đảo trạng thái của Led PD12 mỗi khi MCU nhận được một byte.
Bước 1: Kích chọn dòng STM32F411VETx và sau đó chọn “Start Project”.
Bước 2: Chọn Serial Wire để nạp code
Bước 3: Click chuột phải vào chân PD12 sau đó tích vào ô GPIO_Output
Bước 4: Ở mục Connectivity chọn USART2, mode Asynchronous, tốc độ baud là 115200 bits/s
Bước 5: Setting project và sinh code
Bước 6: Click chọn Open Project và chuyển qua tab Keil C.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/* USER CODE BEGIN 2 */ char Rx_data[2]; /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if((HAL_UART_Receive(&huart2,(uint8_t *)&Rx_data,1,1000))==HAL_OK) //Kiem tra co nhan duoc 1 byte hay khong { HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_12); //Neu nhan duoc thi dao led HAL_UART_Transmit(&huart2,(uint8_t*)Rx_data,1,1000); //Gui di ki tu vua nhan } /* USER CODE END 3 */ } |
Bước 7: Build project và nhấn nút Load để nạp code vào kit.
Bước 8: Bật phần mềm Hercules, chọn cổng COM và tốc độ baud tương ứng để truyền nhận dữ liệu với MCU
Chúc các bạn thành công!
Nhóm TAPIT ARM R&D