完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
最近在调试stm32l0系列单片机串口程序,发现STM官方提供的HAL库中的串口函数只能接收定长数据。 这种情况明显在不改变串口协议的情况下,是无法与外设进行通信的,所以粗略的修改了一下程序,使之实现不定长接收。 如有错误,请随时指出啊哈哈哈哈哈! 恩,首先先介绍一下HAL库的串口函数的用法吧。 HAL库的串口发送比较简单: //把TxData的内容通过uart2发送出去,0xffff是超时时间 HAL_UART_Transmit(&huart2,TxData,sizeof(TxData),0xffff); HAL库提供的串口函数一共有三种用法: 1.接收定长数据 //通过uart2接收10个数据,知道串口接收到10个数据后再返回 HAL_UART_Receive_IT(&huart2,(uint8_t *)&value,10) 2.接收定长数据并设置超时时间 //通过uart2接收10个数据,1000是超时时间,表示1000MS内没有接收到10个数据也返回,timeout的时间是最大值0xffff HAL_UART_Receive(&huart2,(uint8_t *)&value,10,1000); 3.DMA接收 HAL_UART_Receive_DMA(&huart2, (uint8_t *)rxData, sizeof(rxData)-1) 数据接收后,就可以在回调函数里处理数据了。 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle); 可以从以上函数可以看到,每种接收方式都要输入接收数据的长度。但是对于不知道对方发来数据长度的情况几乎就没有很好的解决办法。 于是想到可以不可以绕过数据长度判断,不管多少数据全部接收,再通过FIFO传出数据进行处理。 其中串口的通信协议就自己定了,但是最好有数据长度。 在主要函数的while(1)前使能串口 struct kfifo recvfifo; uint8_t USART_Receive_Buf[64]; //长度需2的n次方,以便后续与操作等效取余操作 void Uart_start(void) { uint8_t bRxBuffer[20]; if(HAL_UART_DeInit(&huart2) != HAL_OK) { Error_Handler(); } if(HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } //这个20随便写,因为已经没用了 if(HAL_UART_Receive_IT(&huart2, (uint8_t *)bRxBuffer, 20) != HAL_OK) { Error_Handler(); } } void Uart_Handle(void) { uint8_t len = 0; unsigned char check = 0; uint8_t revcmdstr[CMD_LEN] = {0}; uint8_t rec_len = __kfifo_len(&recvfifo); //读取接收到FIFO里的数据长度 if (rec_len >= 16) //长度大于16(通信协议自己定) { if ( recvfifo.buffer[(recvfifo.out + UF_START) & (recvfifo.size - 1)] = 0x55) //校验协议头 { len = recvfifo.buffer[(recvfifo.out + UF_LEN) & (recvfifo.size - 1)]; //获取数据长度 if (rec_len >= len) { __kfifo_get(&recvfifo, revcmdstr, len); //获取数据 Request_Cmd(revcmdstr); } } else { __kfifo_get(&recvfifo, revcmdstr, 1);//如果当前位置不是命令起始标志,则丢弃数据 } } } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART2_UART_Init(); uint8_t aRxBuffer[20]; strcpy((char *)aRxBuffer, "SYSTEM START"); if(HAL_UART_Transmit(&huart2, (uint8_t*)aRxBuffer, 13, 5000)!= HAL_OK) memset( (char *)aRxBuffer, ' |