Uart 2

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 27

UART (Universal synchronous asynchronous receiver transmitter ) là một ngoại vi cơ bản của

STM32 sử dụng 2 chân Rx và Tx để nhận và truyền dữ liệu.

UART truyền dữ liệu không đồng bộ, có nghĩa là không có tín hiệu để đồng bộ hóa đầu ra của
các bit từ UART truyền đến việc lấy mẫu các bit bởi UART nhận. Thay vì tín hiệu đồng bộ,
UART truyền thêm các bit start và stop vào gói dữ liệu được chuyển. Các bit này xác định điểm
bắt đầu và điểm kết thúc của gói dữ liệu để UART nhận biết khi nào bắt đầu đọc các bit.

Các thông số cơ bản trong truyền nhận UART :

– Baund rate (tốc độ baund): 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. Một số Baud Rate thông dụng: 9600, 38400, 115200, 230400,…

– Frame (khung truyền): Khung truyền quy định về số bit trong mỗi lần truyền.

– Start bit: là bit đầu tiên được truyền trong 1 Frame. Báo hiệu cho thiết bị nhận có một gói dữ
liệu sắp đc truyền đến. Bit bắt buộc.

– Data: dữ liệu cần truyền. Bit có trọng số nhỏ nhất LSB được truyền trước sau đó đến bit MSB.

– Parity bit: kiểm tra dữ liệu truyền có đúng không.

– Stop bit: là 1 hoặc các bit báo cho thiết bị rằng các bit đã được gửi xong. Thiết bị nhận sẽ tiến
hành kiểm tra khung truyền nhằm đảm bảo tính đúng đắn của dữ liệu. Bit bắt buộc.

1
Cách kết nối STM32 với máy tính thông qua chip cổng com

2. Cấu hình UART trong STM32 CubeIDE

Phần tạo project các bạn tham khảo lại bài 2 phần GPIO (cách tạo project, cấu hình mạch nạp,
xung clock) tại đây

Trong STM32F4 có 3 kênhUSART:

USART1:

PA9———————- USART1_TX

PA10——————— USART1_RX

USART2:

PA2———————- USART2_TX

PA3———————– USART2_RX
2
USART3:

PB10———————- USART3_TX

PB11———————- USART3_RX

có 3 kênh U2ART:

UART5:

PD2 ———————- USART5_TX

PC12———————– USART5_RX

UART4:

PA0———————- UART4_TX

PA1———————- UART4_RX

Bây giờ mình tiến hành cấu hình UART5

(1) Click vào UART5

(2) Mode: Chọn chế độ Asynchronous

(3) Tích vào USART1 global interrupt. Mình sẽ chọn dùng ngắt nhận USART

(4) Khi đó thì 2 chân PD2 và PC12 sẽ lần lượt là UART5_TX và UART5_RX

Ở phần parameters settings: Chương trình sẽ để sẵn mặc định như bên dưới.

Baud Rate:115200 bits/s

3
Word Length: 8 bit

Parity: None

Stop Bits:1

3. Lập trình

/* USER CODE BEGIN Header */

/**

******************************************************************************

* @file : main.c

* @brief : Main program body

******************************************************************************

* @attention

* <h2><center>&copy; Copyright (c) 2023 STMicroelectronics.

* All rights reserved.</center></h2>

4
* This software component is licensed by ST under BSD 3-Clause license,

* the "License"; You may not use this file except in compliance with the

* License. You may obtain a copy of the License at:

* opensource.org/licenses/BSD-3-Clause

******************************************************************************

*/

/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/

#include "main.h"

/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/

/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/

/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/

5
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

UART_HandleTypeDef huart5;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_UART5_Init(void);

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**

* @brief The application entry point.

6
* @retval int

*/

int main(void)

/* USER CODE BEGIN 1 */

uint8_t cmd = 0; //khai báo bien

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */

SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */

MX_GPIO_Init();

7
MX_UART5_Init();

/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

/* USER CODE END WHILE */

if(HAL_UART_Receive(&huart5, &cmd, 1, 100) == HAL_OK){

switch(cmd){

case '0'://nhan 0 tu ban phim

HAL_GPIO_WritePin(GPIOD,LED_RED_Pin |
LED_BLUE_Pin | LED_GREEN_Pin | LED_ORANGE_Pin, GPIO_PIN_RESET);//tat het led

break;

case 'r'://nhan r tu ban phim

HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin,
GPIO_PIN_SET);//bat led do

break;

case 'b'://nhan b tu ban phim

HAL_GPIO_WritePin(LED_BLUE_GPIO_Port,
LED_BLUE_Pin, GPIO_PIN_SET);//bat led xanh

break;

case 'g'://nhan g tu ban phim

HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,
LED_GREEN_Pin, GPIO_PIN_SET);//bat led xanh las

break;

8
case 'o'://nhan o tu ban phim

HAL_GPIO_WritePin(LED_ORANGE_GPIO_Port,
LED_ORANGE_Pin, GPIO_PIN_SET);//bat den cam

break;

/* USER CODE BEGIN 3 */

/* USER CODE END 3 */

/**

* @brief System Clock Configuration

* @retval None

*/

void SystemClock_Config(void)

RCC_OscInitTypeDef RCC_OscInitStruct = {0};

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure the main internal regulator output voltage

*/

__HAL_RCC_PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

/** Initializes the RCC Oscillators according to the specified parameters

* in the RCC_OscInitTypeDef structure.

*/

9
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

RCC_OscInitStruct.HSEState = RCC_HSE_ON;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

RCC_OscInitStruct.PLL.PLLM = 4;

RCC_OscInitStruct.PLL.PLLN = 168;

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;

RCC_OscInitStruct.PLL.PLLQ = 4;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

Error_Handler();

/** Initializes the CPU, AHB and APB buses clocks

*/

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)

Error_Handler();

10
/**

* @brief UART5 Initialization Function

* @param None

* @retval None

*/

static void MX_UART5_Init(void)

/* USER CODE BEGIN UART5_Init 0 */

/* USER CODE END UART5_Init 0 */

/* USER CODE BEGIN UART5_Init 1 */

/* USER CODE END UART5_Init 1 */

huart5.Instance = UART5;

huart5.Init.BaudRate = 9600;

huart5.Init.WordLength = UART_WORDLENGTH_8B;

huart5.Init.StopBits = UART_STOPBITS_1;

huart5.Init.Parity = UART_PARITY_NONE;

huart5.Init.Mode = UART_MODE_TX_RX;

huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE;

huart5.Init.OverSampling = UART_OVERSAMPLING_16;

if (HAL_UART_Init(&huart5) != HAL_OK)

11
Error_Handler();

/* USER CODE BEGIN UART5_Init 2 */

/* USER CODE END UART5_Init 2 */

/**

* @brief GPIO Initialization Function

* @param None

* @retval None

*/

static void MX_GPIO_Init(void)

GPIO_InitTypeDef GPIO_InitStruct = {0};

/* GPIO Ports Clock Enable */

__HAL_RCC_GPIOH_CLK_ENABLE();

__HAL_RCC_GPIOD_CLK_ENABLE();

__HAL_RCC_GPIOC_CLK_ENABLE();

/*Configure GPIO pin Output Level */

HAL_GPIO_WritePin(GPIOD, LED_GREEN_Pin|LED_ORANGE_Pin|LED_RED_Pin|
LED_BLUE_Pin, GPIO_PIN_RESET);

/*Configure GPIO pins : LED_GREEN_Pin LED_ORANGE_Pin LED_RED_Pin LED_BLUE_Pin */

12
GPIO_InitStruct.Pin = LED_GREEN_Pin|LED_ORANGE_Pin|LED_RED_Pin|LED_BLUE_Pin;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**

* @brief This function is executed in case of error occurrence.

* @retval None

*/

void Error_Handler(void)

/* USER CODE BEGIN Error_Handler_Debug */

/* User can add his own implementation to report the HAL error return state */

/* USER CODE END Error_Handler_Debug */

#ifdef USE_FULL_ASSERT

/**

13
* @brief Reports the name of the source file and the source line number

* where the assert_param error has occurred.

* @param file: pointer to the source file name

* @param line: assert_param error line source number

* @retval None

*/

void assert_failed(uint8_t *file, uint32_t line)

/* USER CODE BEGIN 6 */

/* User can add his own implementation to report the file name and line number,

tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

/* USER CODE END 6 */

#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

14
UART là một trong những chuẩn giao tiếp được sử dụng nhiều nhất trong lập trình nhúng. Ưu
điểm của nó là sự đơn giản trong cách sử dụng, tuy nhiên chuẩn giao tiếp này có tốc độ khá thấp
(115200bit/s) so với các chuẩn truyền khác (SPI, I2C, USB) và khoảng cách cho phép truyền
cũng tương đối gần.

Tại sao tốc độ thấp và khoảng cách truyền gần như vậy, UART không bị loại bỏ so với các
chuẩn giao tiếp có nhiều ưu điểm hơn ?

1. Lý thuyết
Để hiểu rõ hơn về chuẩn giao tiếp UART, các bạn có thể tham khảo bài viết tại đây (link).

Đối với dòng chip STM32F4 sẽ có một số thanh ghi quan trọng để dễ dàng cho việc Debug
chương trình.

Một số thanh ghi quan trọng

USART_CR1

PEIE: cho phép ngắt PE hay không ngắt.


TXEIE: cho phép ngắt truyền hay không.
RXNEIE: cho phép ngắt nhận hay không.
TE: cho phép truyền hay không.
RE: cho phép nhận hay không.

USART_BRR

15
Thanh ghi cấu hình tốc độ baudrate UART.

USART_RDR

Thanh ghi chứa data nhận được.

USART_TDR

Thanh ghi chứa giá trị data muốn truyền đi.

USART_ISR

16
TXE : bit báo có data đã truyền hay không, =0 tức là data rỗng, có thể truyền, =1 data đã được
truyền đi.
RXNE: bit báo data đã nhận hay chưa =1: đã nhận, =0 chưa nhận hoặc nhận chưa xong.
TC : cờ báo đã nhận data hoặc data vừa mới truyền xong.

Khi lập trình UART không thấy nhận được dữ liệu data, chúng ta cần debug những thanh
ghi nào ?

Các bạn theo dõi ảnh bên dưới để hiểu cách ngắt USART được tạo ra nhé !

17
2. Lập trình
Mở phần mềm STM CubeMX, chọn dòng chip bạn sử dụng. Ở đây mình chọn chip
STM32L476RG.
Đối với các dòng chip STM32 đời 4, tất cả mọi câu lệnh khi sử dụng thư viện HAL đều giống
nhau. Chỉ khác nhau phần cấu hình Clock phụ thuộc riêng vào mỗi chip hỗ trợ.

18
Cấu hình Chip sử dụng thạch anh ngoài.

Cấu hình Chip Debug bằng mode SWD.

19
Ở đây mình cấu hình module UART2 để sử dụng. Cấu hình chế độ bất đồng bộ UART (khác với
chế độ đồng bộ USART). Enable ngắt UART và cấu hình tốc độ Baudrate là 115200b/s.

20
Tiếp theo, chuyển sang cấu hình tần số Clock cho Chip.

Ở đây mình chọn sử dụng nguồn Clock nội (HSI) được chip hỗ trợ sẵn, như vậy mình sẽ không
cần hàn thêm thạch anh ngoại mà chương trình vẫn chạy được. Clock nội đi qua bộ nhân tần
PLLCLK để đạt được tần số hoạt động tối đa mà chip hỗ trợ HCLK = 80MHz. Việc còn lại Cube
MX sẽ tự cấu hình cho các bạn.
Tại sao bản thân chip đã có Clock nội nhưng chúng ta vẫn sử dụng thêm thạch anh ngoài ?
Cuối cùng chúng ta cấu hình vị trí lưu Code và sinh source Code.

21
Bạn nhớ tick vào đây để CubeMX chỉ copy những file thư viện cần thiết cho Project đã cấu hình.
Như vậy sẽ giảm thiểu được đáng kể dung lượng Project đấy.

Bây giờ chúng ta cùng nhau sửa code nhé.


Ý tưởng của mình sẽ là khởi tạo module UART2, kết nối KIT STM32L4 với phần mềm
Hercules trên mấy tính thông qua USBtoUART. Sau đó sẽ gửi dữ liệu từ Hercules xuống
KIT STM32L4, rồi từ KIT STM32L4 sẽ gửi ngược lại dữ liệu nhận được lên máy tính, hiển
thị trên phần mềm Hercules.

22
Sơ đồ nối dây như sau:

Hàm khởi tạo UART2 được sinh ra bởi Hercules

23
Trong file main.c chúng ta init các Module cần thiết

Khai báo hàm Callback xử lý dữ liệu nhận được trong file main.c

24
Ở đây chúng ta có 2 hàm khá đặc biệt. Mình sẽ giải thích kỹ một chút.
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size,
uint32_t Timeout)
// *pData là con trỏ trỏ tới địa chỉ đầu tiên của mảng data cần truyền đi
// Size là số lượng byte cần truyền đi
// Timeout là khoảng thời gian tối đa chấp nhận cho quá trình truyền. Nếu quá trình vượt quá
khoảng thời gian này thì hàm sẽ trả về mã lỗi.

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t


Size)
// *pData là con trỏ trỏ tới mảng data nhận được
// Size là số lượng data nhận được
// Hàm này còn enable 2 bit PEIE và RXNEIE trong thanh ghi USART_CR1 để có thể tiếp tục nhận
dữ liệu trong lần tiếp theo
Tiến hành Build Code và Nạp chương trình xuống KIT

Kết quả build không có lỗi

Kết quả khi chạy thực tế.

25
Một số cấu hình trong KeilC có thể có ích cho bạn

26
Optimization: Mức độ tối ưu code. Để tiện trong quá trình Debug, chọn Level 0 (mức tối ưu
code thấp nhất). Khi xuất Firmware cho sản phẩm thực tế, nên chọn Level 3 (mức tối ưu code
cao nhất) sẽ cho ra file Firmware có dung lượng thấp nhất.
Cảm ơn các bạn đã đón đọc. Hẹn gặp lại các bạn trong số tiếp theo nhé !!!

27

You might also like