串口不定长接收,对数据进行分析判断。最近想弄个接收黑白图片的工程,所以要把串口接收再复习一遍:
1、串口stm32cubeMax配置:
2、配置中断:
3、配置串口发送PA9为USART1的TX,输出模式为上拉,PA10为USART1的RX:
生成工程后打开工程。
# 串口接收自定义函数的编写
1、打开main.h,加入如下代码:
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
extern UART_HandleTypeDef huart1;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
#define RXBUFFSIZE 2048
typedef struct{
UART_HandleTypeDef *huart;
u8 rx_buf[RXBUFFSIZE]; //接收缓冲区
u32 tx_count; //发送完成次数计数标志位
u32 rx_flage; //接收完成标志位
void (*init)(void); //初始化函数指针
} rxtx_it_usart_t;
/* USER CODE END ET */
代码的主要功能是结构体并进行了初始化。
2、stm32u5xxit.c 声明结构体函数:
/* External variables --------------------------------------------------------*/
extern UART_HandleTypeDef huart1;
/* USER CODE BEGIN EV */
3、定义中断函数:
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
HAL_UART_IDLE_HANDLER(&huart1); //自定义空闲中断接收
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1); //中断接收
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
/* USER CODE BEGIN 1 */
__weak void HAL_UART_IDLE_HANDLER(UART_HandleTypeDef *huart)
{
UNUSED(huart);
}
4、在main.c主函数中增加初始化函数代码
/* USER CODE BEGIN PFP */
//声明一个结构体并进行初始化
void uart1_user_init(void);
rxtx_it_usart_t rxtx_it_usart = {
.huart = &huart1,
.init = uart1_user_init, //为该指针赋值,指向init函数
};
/* USER CODE END PFP */
增加中断回调处理函数:
/* USER CODE BEGIN 4 */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if(rxtx_it_usart.huart == huart)
{
rxtx_it_usart.tx_count++;
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_TxCpltCallback could be implemented in the user file
*/
if(rxtx_it_usart.huart == huart)
{
rxtx_it_usart.rx_flage = 1;
}
}
//初始化空闲中断
void uart1_user_init(void)
{
__HAL_UART_ENABLE_IT(rxtx_it_usart.huart, UART_IT_IDLE);
__HAL_UART_CLEAR_IDLEFLAG(rxtx_it_usart.huart);
HAL_UART_Receive_IT(rxtx_it_usart.huart,rxtx_it_usart.rx_buf,RXBUFFSIZE);
}
//自定义空闲中断处理函数
void HAL_UART_IDLE_HANDLER(UART_HandleTypeDef *huart)
{
uint32_t isrflags = READ_REG(huart->Instance->ISR);
if((USART_ISR_IDLE & isrflags) != RESET && ( huart->RxXferCount > 0))
{
printf("idle\r\n");
__HAL_UART_CLEAR_IDLEFLAG(huart);
/* Disable the UART Data Register not empty Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
/* Disable the UART Parity Error Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_PE);
/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
__HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
/* Rx process is completed, restore huart->RxState to Ready */
huart1.RxState = HAL_UART_STATE_READY;
HAL_UART_RxCpltCallback(huart);
}else if((USART_ISR_IDLE & isrflags) != RESET && ( huart->RxXferCount == 0 ))
{
__HAL_UART_CLEAR_IDLEFLAG(huart);
}
}
//自定中断错误处理函数
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if(rxtx_it_usart.huart == huart)
{
printf("error %d\r\n",huart->ErrorCode);
}
}
/* USER CODE END 4 */
在main中函数中增加对数据处理的功能:
if (( HAL_GetTick()-tickend )>5000)
{
tickend = HAL_GetTick();
HAL_UART_Transmit_IT(rxtx_it_usart.huart,send_data,sizeof(send_data)-1);
}
//发送成功一次,就发送send done
if(rxtx_it_usart.tx_count>0)
{
rxtx_it_usart.tx_count --;
printf("send done\r\n");
}
if(rxtx_it_usart.rx_flage == 1)
{
rxtx_it_usart.rx_flage = 0;
//回显接收到的数据
printf("\r\nrcv done:\r\n");
printf("%s\r\n", rxtx_it_usart.rx_buf);
//重新开始接收20个字节数据
memset(rxtx_it_usart.rx_buf,0,sizeof(rxtx_it_usart.rx_buf));
HAL_UART_Receive_IT(rxtx_it_usart.huart,rxtx_it_usart.rx_buf,RXBUFFSIZE);
}
下载后的效果如下: