STM2G031-使用STM32CubeIDE進行串口通信實驗
一、基礎配置
模式選擇 : 配置為異步模式Asynchronous
- Asynchronous : 異步, 整個程序,不會阻礙發送者的作業,
- Synchronous : 同步, 同步資訊一旦發送,發送者必須等到應答,才能繼續后續的行為,
- Single Wire : 單總線, 半雙工,
- Multiprocessor Communication:多機通信

基本引數配置: 引數配置里面主要關注一下基本引數配置,其他的一些配置默認即可, - 波特率:可以根據實際情況進行選擇
- 字長:一般選擇8位即可
- 奇偶校驗:一般選擇無
- 停止位:1位

二、printf 重定向
在 Private includes 中引入頭檔案:
#include <stdio.h>
在 USER CODE BEGIN PD 添加下面代碼:
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *F)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
使用printf輸出浮點數:
Project–>Properties–>C/C++ Build–>Settings–>MCU settings,如下圖所示,勾選上即可,

實驗一:通過串口發送資料
- 基本配置

- 添加代碼:
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */
/* USER CODE BEGIN PD */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *F)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END PD */
/* USER CODE BEGIN 3 */
HAL_Delay(500);
printf("Hello World!\r\n");
}
/* USER CODE END 3 */
- 實驗現象:
打開串口除錯助手,即可看將以500ms為周期輸出Hello World!

實驗二:接收資料
- 基本配置:注意需要開啟串口中斷


- 添加代碼:
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */
/* USER CODE BEGIN PD */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *F)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END PD */
/* USER CODE BEGIN PV */
uint8_t RxBuff[1]; // 用來接收串口2發送的資料
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart2, RxBuff, 1);
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2) // 判斷是由哪個串口觸發的中斷
{
HAL_UART_Transmit(&huart2,RxBuff,1,100); // 接收到資料馬上使用串口2發送出去
HAL_UART_Receive_IT(&huart2,RxBuff,1); // 重新使能串口2接收中斷
}
}
/* USER CODE END 4 */
實驗現象: 將串口接收到的資料,又通過該串口發送回去

實驗三:串口接收不定長資料(定時器方式實作)
- 基本配置:
關于定時器的配置,在這里使用通用定時器3,如下圖所示,配置一下時鐘,內部時鐘我們配置為64Mhz,定時器1ms產生一次中斷(可以根據實際情況增大時間),
定時器的配置主要有兩個:定時時間與是否重裝定時器,
定時頻率 = 定時器時鐘 / (預分頻 +1) /(計數值 + 1 ) Hz,
定時時間 = 1 / 定時頻率 s,




添加代碼:
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */
/* USER CODE BEGIN PD */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *F)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END PD */
/* USER CODE BEGIN PV */
uint8_t RxBuff[1]; //進入中斷接收資料的陣列
uint8_t DataBuff[100]; //保存接收到的資料的陣列
int RxLine=0; //接收到的資料長度
int Rx_flag=0; //接受到資料標志
/* USER CODE END PV */
/* USER CODE BEGIN 0 */
void printf_usart(void)
{
printf("length=%d\r\n",RxLine);
DataBuff[RxLine] = '\0';
printf("Rxdata:%s\r\n",DataBuff);
memset(DataBuff,0,sizeof(DataBuff)); //清空快取陣列
//memset()作用:可以方便的清空一個結構型別的變數或陣列,
//例句:memset(aTxbuffer,0,sizeof(aTxbuffer)) 用memset清空aTxbuffer,
RxLine=0; //清空接收長度
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart2, (uint8_t *)RxBuff, 1);
HAL_TIM_Base_Start_IT(&htim3);//開啟定時器
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2) // 判斷是由哪個串口觸發的中�?
{
RxLine++; //每接收到一個資料,進入回呼資料長度加1
DataBuff[RxLine-1]=RxBuff[0]; //把每次接收到的資料保存到快取陣列
Rx_flag=1;
if(RxBuff[0]==0xff) //接收結束標志位,這個資料可以自定義,根據實際需求,這里只做示例使用,不一定是0xff
{
printf_usart();
}
RxBuff[0]=0;
HAL_UART_Receive_IT(&huart2, (uint8_t *)RxBuff, 1); //每接收一個資料,就打開一次串口中斷接收,否則只會接收一個資料就停止接收
__HAL_TIM_SET_COUNTER(&htim3, 1); // 計數清零,從頭開始計
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
if (htim->Instance == TIM3){ // 判斷是由哪個定時器觸發的中斷
if(Rx_flag==1)
{
printf_usart();
Rx_flag=0;
}
}
}
/* USER CODE END 4 */
實驗四:串口接收不定長資料(DMA方式實作)
- 基本原理:
DMA方式接收不定長資料要用到IDLE空閑中斷,
空閑中斷是接受資料后出現一個 byte 的高電平 (空閑) 狀態, 就會觸發空閑中斷. 并不是空閑就會一直中斷,準確的說應該是上升沿(停止位)后一個 byte,如果一直是低電平是不會觸發空閑中斷的(會觸發 break中斷),所以為了減少誤進入串口空閑中斷,串口 RX 的 IO 管腳一定設定成 Pull-up<上拉模式>,串口空閑中斷只是接收的資料時觸發,發送時不觸發,
說明白一點,就是我們在發送資料的時候,是一直在發送,不會有一幀這么長的空閑,當發送資料結束后,就會產生空閑中斷,所以,可以通過空間中斷來判斷資料是否接收完成,
- 優勢:
相較于上面用定時器實作的方式,這種方法不需要一直產生中斷,而占用cpu的資源,也省去了一個定時器,
目前使用DMA和空閑中斷的方式,不知道遇到了什么問題,就是看不到現象…參考了很多資料,暫時還沒實作,具體錯誤不知道出在哪里了,找了一天的錯誤了,快吐了,以后再說吧…
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/258083.html
標籤:其他
下一篇:常見電子元器件的常用品牌匯總
