本章概述思維導圖:
USART串口初始化配置
串口初始化配置在(STM32-USART串口初始化章節有詳細教程配置),本章不做講解直接代碼示例,本章重點在于串口實現接收數據三種方法;
配置USART1串口接收初始化函數步驟:
1. 開時鐘
2. 對串口1模塊開啟復位時鐘,在取消復位;
3. 配置GPIO模式
4. 通過在USART_CR1寄存器上置位UE位來激活USART
5. 編程USART_CR1的M位來定義字長。
6. 在USART_CR2中編程停止位的位數。
7. 利用USART_BRR寄存器選擇要求的波特率。
8. 設置USART_CR1中的TE位,發送一個空閑幀作為第一次數據發送。
9. 設置USART_CR1的RE位。激活接收器,使它開始尋找起始位。
10. 設置USART_CR1的IDLEIE位。當USART_SR中的IDLE為’1’時,產生USART中斷
11.設置USART_CR1的RXNEIE位。當USART_SR中的ORE或者RXNE為’1’產生USART中斷。
12. 調用中斷設置優先級函數;
代碼示例:
/*USART1串口初始化函數形參bps——>保持通信的波特率PA10設置為輸入模式,PA9設置為復用輸出模式;
*/
void USART1_Init(u32 bps)
{
// 1. 開時鐘RCC->APB2ENR|=1<<2;//開啟PA時鐘;RCC->APB2ENR|=1<<14;//開啟USART1時鐘
// 2. 對串口1模塊開啟復位時鐘,在取消復位;RCC->APB2RSTR|=1<<14;//開啟USART1復位時鐘,復位這一步可以省略配置USART1步驟RCC->APB2RSTR&=~(1<<14);//取消復位時鐘,關閉復位
// 3. 配置GPIO模式GPIOA->CRH&=0xfffff00f;//清空PA10、PA9引腳模式GPIOA->CRH|=0x000008b0;//PA10輸入PA9輸出
// 4.通過在USART_CR1寄存器上置位UE位來激活USARTUSART1->CR1|=1<<13;
// 5.編程USART_CR1的M位來定義字長。USART1->CR1&=~(1<<12);
// 6.在USART_CR2中編程停止位的位數。USART1->CR2&=~(0x3<<12);
// 7.利用USART_BRR寄存器選擇要求的波特率。USART1->BRR=72000000/bps;
// 8.設置USART_CR1中的TE位,發送一個空閑幀作為第一次數據發送。USART1->CR1|=1<<3;
// 9.設置USART_CR1的RE位。激活接收器,使它開始尋找起始位。USART1->CR1|=1<<2;
// 10.設置USART_CR1的IDLEIE位。當USART_SR中的IDLE為’1’時,產生USART中斷USART1->CR1|=1<<4;
// 11.設置USART_CR1的RXNEIE位。當USART_SR中的ORE或者RXNE為’1’產生USART中斷。USART1->CR1|=1<<5;
// 12.調用中斷優先級函數STM32_SetNVICPriority(USART1_IRQn ,1,1);
}
USART串口中斷服務函數
/*串口1中斷服務函數
*/
void USART1_IRQHandler()
{u8 c;if(USART1->SR&1<<5)//判斷是否為:接收中斷;每接收一個字符就會觸發一次中斷{c=USART1->DR;//將數據賦值給cUSART1->DR=c;//將數據發生給上位機軟件,使得顯示界面上顯示。}
}
USART1串口1接收實現三種方法
判斷串口數據發送完一次數據有三種方法:
1. 是發送數據時以(\r\n)標志為結尾,檢測到(\n)時就知道數據完成一次發送
2. 串口初始化函數中開啟空閑幀中斷
3,定時器輔助串口接收,判斷串口1發送一字節和下一字節的間隔時間。超過定時器 初始設定的時間說明字符串數據發送完成
方法1:這里判斷一次數據發送完成時根據(\r\n結束標志符)
代碼示例:
u8 USART1_buffer[1024];//緩沖區數組,用來接收數據
u16 USART1_cnt=0;//緩沖區數組下標
u8 USART1_flag=0;//聯合主函數標志位
/*USART1串口1中斷服務函數
*/
void USART1_IRQHandler(void)
{u8 dat;if(USART1->SR&1<<7)//沒接收到一個字符觸發標志位{dat=USART1->DR;//讀取數據if(USART1_cnt<1024){USART1_buffer[USART1_cnt]=dat;//將讀取的數據放入到緩沖區數組里if(USART1_buffer[USART1_cnt] == '\n')//判斷是否到結束標注位"\r\n"{USART1_buffer[USART1_cnt-1]='\0';//將'\r'寫入'\0'結束USART1_flag=1;//數據接收完成}else{USART1_cnt++;}}else{USART1_buffer[USART1_cnt-1]='\0';USART1_cnt=0;}}
}
代碼講解:
創建緩沖區數組用來接收字符,只要字符不為:' \n ';就一直接收;當字符為:' \n '時;將' \r'位置寫入' \0 '表示接收完成,同時將標志位置1,聯合主函數使用;
主函數代碼示例:
#include "USART1.h"
#include "stdio.h"
int main()
{USART1_Init(115200);//USART1串口1初始化函數while(1){if(USART1_flag){printf("buffer=%s\tcnt=%d\n",USART1_buffer,USART1_cnt);USART1_cnt=0;//下標清零USART1_flag=0;//標志位置0;}}
}
代碼運行結果圖:
數據發送圖:
數據成功接收圖:
方法2:開啟空閑幀中斷
在串口初始化函數中配置USART1_CR1的IDLEIE:IDLE中斷使能位
中斷服務函數配置示例代碼:
/*USART1串口1中斷服務函數
*/
void USART1_IRQHandler(void)
{u8 dat;if(USART1->SR&1<<5)//每接收到一個字符觸發標志位{dat=USART1->DR;//讀取數據if(USART1_cnt<1024){USART1_buffer[USART1_cnt]=dat;//將讀取的數據放入到緩沖區數組里USART1_cnt++;}else{USART1_cnt=0;} }if(USART1->SR&1<<4)//空閑幀標志,這是全部發送完觸發一次{dat=USART1->DR;USART1_flag=1;//數據接收完成}USART1->SR=0;
}
主函數示例代碼:
#include "USART1.h"
#include "stdio.h"
int main()
{USART1_Init(115200);//USART1串口1初始化函數while(1){if(USART1_flag){USART1_buffer[USART1_cnt]='\0';//寫入結束標志符printf("buffer=%s\tcnt=%d\n",USART1_buffer,USART1_cnt);USART1_cnt=0;//下標清零USART1_flag=0;//標志位置0;}}
}
代碼運行結果圖:
數據發送圖:
數據成功接收圖:
方法3:定時器輔助串口接收
定時器輔助串口接收,判斷串口1發送一字節和下一字節的間隔時間。超過定時器 初始設定的時間說明字符串數據發送完成
配置步驟:
第一步:算出發送一個字節數據要多少時間:
1m=1000ms=1000000us;
1000000/(115200/10)=86.80555555us;發送一字節數據需要86.8055微秒;
判斷第一個字節數據和第二字節數據的間隔時間有沒有超過10ms
第二步:在串口1初始化函數中關閉空閑幀中斷并且串口中斷服務函數里關閉空閑幀中斷; 在定時器2初始化函數里關閉使能計數器,并且關閉定時器。設定定時時間10毫 秒
第三步:在串口第一次接收一字節數數時,在串口1中斷服務函數里清空計數器并且開啟定 時器。
第四步:如果數據全部返送完成,在定時器2中斷服務函數里將標志位置一并且關閉定時器 等待下一次數據發送玩出觸發定時器2中斷
第三步示例代碼:
/*USART1串口1中斷服務函數
*/
void USART1_IRQHandler(void)
{u8 dat;if(USART1->SR&1<<5)//每接收到一個字符觸發標志位{dat=USART1->DR;//讀取數據if(USART1_cnt<1024){TIM2->CNT=0;//清空計數器TIM2->CR1|=1<<0;//開啟定時器USART1_buffer[USART1_cnt]=dat;//將讀取的數據放入到緩沖區數組里USART1_cnt++;}else{USART1_flag=1;} }USART1->SR=0;
}
第四步示例代碼:
/*定時器2中斷服務函數
*/
void TIM2_IRQHandler(void)
{if(TIM2->SR&1<<0){USART1_flag=1;//定時時間到標志位置1TIM2->SR&=~(1<<0);TIM2->CR1&=~(1<<0);//關閉定時器}
}
主函數示例代碼:
#include "USART1.h"
#include "stdio.h"
#include "TIM.h"
int main()
{USART1_Init(115200);//USART1串口1初始化函數TIM2_Init(7200,10000);//定時器2設置定時時間為10毫秒while(1){if(USART1_flag){USART1_buffer[USART1_cnt]='\0';//給緩沖區數組寫入結束標識符;printf("buffer=%s cnt=%d\n",USART1_buffer,USART1_cnt);USART1_cnt=0;//下標清零USART1_flag=0;//標志位置0;}}
}
代碼運行結果圖:
數據發送圖:
數據成功接收圖:
制作不易!喜歡的小伙伴給個小贊贊!喜歡我的小伙伴點個關注!有不懂的地方和需要的資源隨時問我喲!