iT邦幫忙

0

STM32-6 NVIC USART

  • 分享至 

  • xImage
  •  

USART介紹

USART全名為通用同步/非同步收發傳輸器(universal synchronous asynchronous receiver transmitter),可以透過串列通訊的方式進行傳輸。
STM32具有全雙工的USART,同時支援同步/非同步與半雙工/全雙工等等模式,STM32已將預設的USART2連接到燒錄器同時連結到電腦上,可以直接使用。
https://ithelp.ithome.com.tw/upload/images/20220312/20146325GeoVTAW3HH.png

半雙工 / 全雙工區別

  • 半雙工 : 允許兩台設備之間雙向資料傳輸,但無法同時進行。也就是說同一時間內只能允許一個設備傳送資料,另一個設備要重送資料只能等待。
  • 全雙工 : 同時允許兩台設備進行雙向的資料傳輸(傳送與接收)

同步/非同步

  • 同步 : 需額外提供SCLK,讓兩設備可以同步收發資料。不需要Start/stop bit,一次可以傳比較多的資料。
  • 非同步: 傳送資料的時候透過起始位與結束位來確定資料的收發狀態
    https://ithelp.ithome.com.tw/upload/images/20220312/201463255Sa11y3Szj.png
    USART每一次傳輸資料時,會以上圖一個訊框作(frame)為一個單元,其中包含開頭與結尾的起始/結束位元與中間的8 bit/9bit資料。圖中可以看到在TX發送資料於起始位時處於低電位,結束則處於高電位。
    其中有分為8bit資料與9bit資料兩種訊框,可以透過IDE當中.ioc去做詳細的設置。
    https://ithelp.ithome.com.tw/upload/images/20220312/201463251ex6KzvuzQ.png
    https://ithelp.ithome.com.tw/upload/images/20220312/20146325yX0p0x37RV.png
    詳細暫存器與特性可以參考STM32中文參考手冊

函數介紹-發送

1.HAL_UART_Transmit :輪詢方式,阻塞式發送函數(必須等資料傳送完成後MCU才去做其他事情)

//*huart : 看選擇哪個USART填入對應編號
//*pData : 要傳送的資料Buf指針
//Size : 資料長度
//Timeout : 逾時時間
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)

2.HAL_UART_Transmit_IT : 中斷方式,非阻塞發送函數

//*huart : 看選擇哪個USART填入對應編號
//*pData : 要傳送的資料Buf指針
//Size : 資料長度
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
  1. HAL_UART_TxCpltCallback :串列埠發送中斷回調函數
void HAL_UART_TxCpltCallback(UART_HandleTypeDef  *huart);
  1. HAL_UART_TxHalfCpltCallback : 串列埠發送一半中斷回調函數
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef  *huart)

應用方式

//使用中斷方式
//將buf當中的前10筆數據發送到usart2,接著等發送完成後進到回調函數
HAL_UART_Transmit_IT(&huart2,buf,10);

void HAL_UART_TxCpltCallback(UART_HandleTypeDef  *huart) 
{         
    if(huart->Instance == USART2);         
    {             
        HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5); 
    }
}

//使用輪詢方式
HAL_UART_Transmit(&huart2,buf, 10, 100);
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5); 

函數介紹-接收

  1. HAL_UART_Receive : 輪詢方式,阻塞式接收函數(必須等資料傳送完成後MCU才去做其他事情)
//*huart : 看選擇哪個USART填入對應編號
//*pData : 要接收的資料Buf指針
//Size : 等待接收的資料長度
//Timeout : 逾時時間
HAL_StatusTypeDef  HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData,  uint16_t Size, uint32_t Timeout);
  1. HAL_UART_Receive_IT : 中斷方式,非阻塞發送函數
//*huart : 看選擇哪個USART填入對應編號
//*pData : 要接收的資料Buf指針
//Size : 等待接收的資料長度
HAL_StatusTypeDef  HAL_UART_Receive_IT(UART_HandleTypeDef *huart,uint8_t *pData,uint16_t Size);
  1. HAL_UART_RxCpltCallback :串列埠接收中斷回調函數
void HAL_UART_RxCpltCallback(UART_HandleTypeDef  *huart);
  1. HAL_UART_TxHalfCpltCallback : 串列埠接收一半中斷回調函數
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef  *huart);

應用方式

//使用中斷,非阻塞方式
//接收USART2的一個byte,假設是0xFF將板載LED燈反轉
HAL_UART_Receive_IT(&huart2,  &buf, 1);
  
void HAL_UART_RxCpltCallback(UART_HandleTypeDef  *huart)  
{        
    if(huart->Instance == USART2)    
    {       
        if(buf == 0xFF)      
         HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
    }
}

//使用輪詢方式
HAL_UART_Receive(&huart2,buf, 1, 100);

函數介紹-查詢

  1. HAL_UART_GetState : 查詢發送是否正處於忙碌狀態或是接收是否結束了
HAL_UART_GetState();
//EX
while(HAL_UART_GetState(&huart2) == HAL_UART_STATE_BUSY_TX)   //查詢UART是否發送結束

範例-透過輪詢方式傳送與接收

  1. 先在最上方宣告buf
char buf[] = "USART2 初始化中.....\r\n";
char buf1[] = "初始化完成\r\n";
char Receivebuf[7];
  1. 在mian當中寫進傳送與接收函數
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* 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();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
	if(HAL_OK == HAL_UART_Transmit(&huart2, (uint8_t*)buf, sizeof(buf), 1000)) //顯示初始化是否成功
	{
		HAL_Delay(1000);
		HAL_UART_Transmit(&huart2, (uint8_t*)buf1, sizeof(buf1), 1000); //顯示初始化成功字串
	}
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
		if (HAL_OK == HAL_UART_Receive(&huart2, (uint8_t*)Receivebuf, 7, 10000)) //如果成功接收到了資料,則將資料傳送出去
		{
			HAL_UART_Transmit(&huart2, (uint8_t*)Receivebuf, 7, 10000);
	  }
		HAL_Delay(500);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

這邊介紹一下我覺得挺好用的調適工具-串口調適助手,可以到Microsoft Store當中去下載~
https://ithelp.ithome.com.tw/upload/images/20220312/20146325KOXuCfcJww.png


範例-透過中斷方式傳送與接收

  1. 同樣先宣告buf
char Txbuf[] = {"USART 中斷測試\r\n"};
char AckBuf[] = {"收到訊息\r\n"};
char Rxbuf[7];
  1. 到.ioc當中將USART中斷開啟
    https://ithelp.ithome.com.tw/upload/images/20220312/201463255FVr0BdXJ6.png

  2. 先在main當中寫上Receive_IT與Transmit_IT函數,會先傳送上方Txbuf當中的字串做測試,接著要先啟用Receive_IT否則不會進入接收中斷。

/* USER CODE BEGIN 2 */
  HAL_UART_Transmit_IT(&huart2, (uint8_t*)&Txbuf, sizeof(Txbuf));
  HAL_UART_Receive_IT(&huart2, (uint8_t*)&Rxbuf, 7);
  /* USER CODE END 2 */
  1. 編寫接收中斷回調函數(如果傳送中斷要連續使用的話,要記得先檢查是否已傳送完成)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == huart2.Instance)
	{
        //這邊也可以將AckBuf改為Rxbuf,就可以看到接收到的訊息~
		HAL_UART_Transmit_IT(huart, (uint8_t*)&AckBuf, sizeof(AckBuf));
		HAL_UART_Receive_IT(huart, (uint8_t*)&Rxbuf, 7);
	}
}

https://ithelp.ithome.com.tw/upload/images/20220312/20146325ABPTZyMXGU.png
以上內容如果有誤的話,麻煩各位通知我。感謝~


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言