一、起因
为什么要写一个串口接收不定长数据,还要把数据保存起来??
因为存起来的数据要用要判断要根据数据做不同的处理,要把数据拿到后解析。
但是,最开始想当然的使用HAL库中的HAL_UART_Receive_IT() 和 HAL_UART_Receive(),调用函数发现怎么也不对,总是有bug。网上查了一堆,博客很多,解决不了我的问题啊,按照他们的方法我还是不能接收到数据。
后来参考了野火的教程,直接用寄存器,自己再单独写了个函数解决。
二、代码
main.c 直接写while循环就OK了 其他的都一样
while (1)
{
HAL_Delay(1000);
//测试串口数据保存
Test_Usart_Recv();
}
stm32f10x_it.c
串口1的中断:数据打印到上位机后,对ch数据做保存
这里有个坑,就是不能调用printf,真的是个坑啊,调用printf("%c",ch)根本不能把所有ch数据打印出来,只能打印2个
串口接收数据是一个字节一个字节接收的,所以每接收一个字节就会进入一次中断。我是怎么知道的,测试时我在中断函数中用一个全局的变量记录进入次数,主函数中再打印出来,这样就知道进入函数的次数了。没办法,不能用printf,用printf就只打印两次,我以为只进入两次中断,其实不是的,printf函数中会调底层的寄存器,和上面的寄存器操作冲突了,这里用printf就有bug.
//串口1中断函数:stm32接收到上位机的数据
void DEBUG_USART_IRQHandler(void)
{
uint8_t ch = 1;
if (__HAL_UART_GET_FLAG( &DebugUartHandle, UART_FLAG_RXNE ) != RESET)
{
HAL_UART_IRQHandler(&DebugUartHandle);
//读寄存器
ch = ( uint16_t)READ_REG(DebugUartHandle.Instance->DR);
//printf("%c\n",ch); //这里不能使用printf 会有bug 因为printf中调用HAL_UART_Transmit中同样使用了DebugUartHandle.Instance->DR
//打印到上位机
WRITE_REG ( DebugUartHandle.Instance->DR,ch);
//保存数据到缓冲区
Usart_Save_Data(ch);
}
}
bsp_uart.c bsp_uart.h
/**************************************************/
/* .h头文件 */
//串口1接收数据结构体
#define USART1_RECV_BUFFR_SIZE 256
typedef struct Usart1_Recv_Data
{
uint8_t data_buff[USART1_RECV_BUFFR_SIZE];
uint8_t recv_flag;//1:接收完毕 0:未接收数据、未接收完数据
uint16_t recv_size;//当前接收数据的个数(数组下标 0~255)
}Usart1_Recv_Data_t;
//测试串口1 接收不定长数据
void Test_Usart_Recv(void);
extern UART_HandleTypeDef DebugUartHandle;
extern Usart1_Recv_Data_t Usart_Recv_Data_Buff;
/**************************************************/
/* .c源文件 */
//初始化 结构体
void Usart_Recv_Buff_Init(void)
{
Usart_Recv_Data_Buff.recv_flag = 0;
Usart_Recv_Data_Buff.recv_size = 0;
}
//保存数据 到 buff
void Usart_Save_Data(uint8_t ch)
{
if(ch == '\n')//表示接受完毕
{
Usart_Recv_Data_Buff.data_buff[Usart_Recv_Data_Buff.recv_size++] = ch;
Usart_Recv_Data_Buff.recv_flag = 1;
}
else
{
Usart_Recv_Data_Buff.data_buff[Usart_Recv_Data_Buff.recv_size++] = ch;
}
}
//main调用 测试使用
void Test_Usart_Recv(void)
{
if(Usart_Recv_Data_Buff.recv_flag)
{
printf("usart1 recv data = %s\n",Usart_Recv_Data_Buff.data_buff);
Usart_Recv_Buff_Init();//清零size 和 flag
memset(Usart_Recv_Data_Buff.data_buff,0,USART1_RECV_BUFFR_SIZE);//清空
}
}
源程序工程代码链接: