Professional Documents
Culture Documents
Uart 2
Uart 2
Uart 2
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.
– 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.
– 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
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
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:
PC12———————– USART5_RX
UART4:
PA0———————- UART4_TX
PA1———————- UART4_RX
(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.
3
Word Length: 8 bit
Parity: None
Stop Bits:1
3. Lập trình
/**
******************************************************************************
* @file : main.c
******************************************************************************
* @attention
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
* opensource.org/licenses/BSD-3-Clause
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
5
/* USER CODE BEGIN PM */
UART_HandleTypeDef huart5;
void SystemClock_Config(void);
/**
6
* @retval int
*/
int main(void)
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
7
MX_UART5_Init();
/* Infinite loop */
while (1)
switch(cmd){
HAL_GPIO_WritePin(GPIOD,LED_RED_Pin |
LED_BLUE_Pin | LED_GREEN_Pin | LED_ORANGE_Pin, GPIO_PIN_RESET);//tat het led
break;
HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin,
GPIO_PIN_SET);//bat led do
break;
HAL_GPIO_WritePin(LED_BLUE_GPIO_Port,
LED_BLUE_Pin, GPIO_PIN_SET);//bat led xanh
break;
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;
/**
* @retval None
*/
void SystemClock_Config(void)
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
*/
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();
*/
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;
Error_Handler();
10
/**
* @param None
* @retval None
*/
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();
/**
* @param None
* @retval None
*/
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
HAL_GPIO_WritePin(GPIOD, LED_GREEN_Pin|LED_ORANGE_Pin|LED_RED_Pin|
LED_BLUE_Pin, GPIO_PIN_RESET);
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);
/**
* @retval None
*/
void Error_Handler(void)
/* User can add his own implementation to report the HAL error return state */
#ifdef USE_FULL_ASSERT
/**
13
* @brief Reports the name of the source file and the source line number
* @retval None
*/
/* User can add his own implementation to report the file name and line number,
#endif /* USE_FULL_ASSERT */
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.
USART_CR1
USART_BRR
15
Thanh ghi cấu hình tốc độ baudrate UART.
USART_RDR
USART_TDR
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.
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.
22
Sơ đồ nối dây như sau:
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.
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