基本串口通信通常只能接收到定長(zhǎng)數(shù)據(jù),無(wú)法穩(wěn)定接收不定長(zhǎng)數(shù)據(jù),本章介紹利用STM32單片機(jī)的IDLE空閑中斷,接收不定長(zhǎng)數(shù)據(jù)。
使能串口1的異步串行通信模式,開(kāi)啟Usart1的全局中斷。添加DMA通道。
使用Stm32Cubemx生成源碼, 打開(kāi)生成的源碼,刪除whiel循環(huán)中的語(yǔ)句。
打開(kāi)usart.h文件,在文件開(kāi)頭的USER CODE BEGIN Includes下方引入stdio.h頭文件
打開(kāi)usart.c文件,在USER CODE BEGIN 0與 USER CODE END 0之間添加下列代碼。
#if 1 struct __FILE { int handle; };
FILE __stdout; //定義_sys_exit()以避免使用半主機(jī)模式 void _sys_exit(int x) { x = x; } //重定義fputc函數(shù)int fputc(int ch, FILE *f){ while((USART1->SR&0X40)==0);//循環(huán)發(fā)送,直到發(fā)送完畢 USART1->DR=(uint8_t)ch; return ch;}#endif
打開(kāi)uart.c文件,在文件頂部的USER CODE BEGIN 0下方添加下列變量。
volatile uint8_t rx1_len = 0; //接收一幀數(shù)據(jù)的長(zhǎng)度volatile uint8_t rec1_end_flag = 0; //一幀數(shù)據(jù)接收完成標(biāo)志uint8_trx1_buffer[BUFFER_SIZE]={0}; //接收數(shù)據(jù)緩存數(shù)組
打開(kāi)uart.c文件,在文件末尾的USER CODE BEGIN 1下方添加下列函數(shù)。
void Usart1_IDLE(void) //USART1的IDLE接收{(diào) uint32_t tmp_flag = 0; uint32_t temp; tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //獲取IDLE標(biāo)志位 if((tmp_flag != RESET))//idle標(biāo)志被置位 { __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除標(biāo)志位 HAL_UART_DMAStop(&huart1); // 停止DMA傳輸,防止 temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 獲取DMA中未傳輸?shù)臄?shù)據(jù)個(gè)數(shù) rx1_len = BUFFER_SIZE - temp; //總計(jì)數(shù)減去未傳輸?shù)臄?shù)據(jù)個(gè)數(shù),得到已經(jīng)接收的數(shù)據(jù)個(gè)數(shù) rec1_end_flag = 1; // 接受完成標(biāo)志位置1 }}
void Usart1_Handle() //USART1對(duì)接收的一幀數(shù)據(jù)進(jìn)行處理{ DMA_Usart1_Send(rx1_buffer, rx1_len); //將接收到的數(shù)據(jù)回發(fā)給發(fā)送端 rx1_len = 0;//清除計(jì)數(shù) rec1_end_flag = 0;//清除接收結(jié)束標(biāo)志位 HAL_UART_Receive_DMA(&huart1,rx1_buffer,BUFFER_SIZE);//重新打開(kāi)DMA接收}
void DMA_Usart1_Send(uint8_t *buf,uint8_t len) //串口發(fā)送封裝{ if(HAL_UART_Transmit_DMA(&huart1,buf,len)!= HAL_OK) //判斷是否發(fā)送正常,如果出現(xiàn)異常則進(jìn)入異常中斷函數(shù) { Error_Handler(); }}
打開(kāi)usart.h文件,在文件開(kāi)頭的USER CODE BEGIN Includes下方添加如下語(yǔ)句:
#include "stdio.h"#include "string.h"#define BUFFER_SIZE 100
extern volatile uint8_t rx1_len; //接收一幀數(shù)據(jù)的長(zhǎng)度extern volatile uint8_t rec1_end_flag; //一幀數(shù)據(jù)接收完成標(biāo)志extern uint8_t rx1_buffer[BUFFER_SIZE]; //接收數(shù)據(jù)緩存數(shù)組
void Usart1_Handle(void);void DMA_Usart1_Send(uint8_t *buf,uint8_t len);//串口發(fā)送封裝voidUsart1_IDLE(void);
進(jìn)入main.c文件,找到入口函數(shù)void mian(void), 在USER CODE BEGIN 2下方開(kāi)啟串口1的DILE中斷,并打開(kāi)DMA接收。
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能IDLE中斷 HAL_UART_Receive_DMA(&huart1,rx1_buffer,BUFFER_SIZE); //開(kāi)啟DMA接收
在while語(yǔ)句中添加接收查詢語(yǔ)句。
if(rec1_end_flag) //判斷是否接收到1幀數(shù)據(jù){ Usart1_Handle(); //前往數(shù)據(jù)處理函數(shù)處理接收到的數(shù)據(jù)。}
打開(kāi)stm32f4xx_it.c文件,在文件開(kāi)頭引入usart.h頭文件。
向下翻stm32f4xx_it.c文件,找到void USART1_IRQHandler(void)函數(shù),此函數(shù)為串口1的中斷入口函數(shù)。在此函數(shù)中添加之前在usart.c文件中創(chuàng)建的IDLE接收函數(shù)。
源碼修改完畢后,編譯下載,打開(kāi)串口助手,隨意發(fā)送100個(gè)字節(jié)以內(nèi)的任意長(zhǎng)度內(nèi)容進(jìn)入單片機(jī),都可得到同樣的回復(fù)。
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
6754瀏覽量
88612 -
STM32
+關(guān)注
關(guān)注
2262文章
10846瀏覽量
353677
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論