您的位置:首页 > 其它

基于stm32cube的stm32系列不定长度串口接收(IDLE接收)

2017-05-15 13:03 537 查看
串口接收的数据如果是符合一定的协议帧就比较好处理,比如说遍历帧头,寻找帧长,遍历帧尾,最后取出一帧数据,但是如果是不定长度的一帧数据,需要完整的接收处理一般使用的方法是这样的:在串口有中断接收的时候重置一个在定时器中累加的值,主循环等到这个数值到达一定高度后(一段时间没新数据接收),就处理这帧数据。程序流程大楷如下:

1串口中断:

void USART1_IRQHandler(void){
unsigned char temp=0;
if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET){
temp=USART_ReceiveData(USART1);//读完即自动清除RXNE
if(data_wifi_ble_frame.Receivelength[WIFI_position]<rxBufferSize){
data_wifi_ble_frame.ReceiveFlag[WIFI_position]=1;
data_wifi_ble_frame.ReceiveData[WIFI_position][data_wifi_ble_frame.Receivelength[WIFI_position]]=temp;
data_wifi_ble_frame.Receivelength[WIFI_position]++;
}


2 TIMER中断

void TIM3_IRQHandler(void)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

if(data_wifi_ble_frame.ReceiveFlag[WIFI_position]>0){
data_wifi_ble_frame.ReceiveFlag[WIFI_position]++;
}

}
3 主循环:

while(1){
if(data_wifi_ble_frame.ReceiveFlag[WIFI_position]>3){
data_wifi_ble_frame.ReceiveFlag[WIFI_position]=0;
//处理数据帧
}

第一种方法虽然可以处理一帧完整的数据,但是如果接收的数据速度太快,中间间隔太短,会不好处理数据帧。

下面介绍另一种方法:使用空闲帧接收不定长数据帧。

1 选择stm32cube的串口,开启中断:



2 生成的代码中开启中断接收,使能空闲中断

if(HAL_UART_Receive_IT(&huart1,frame.ReceiveUsart1Data,128)!=HAL_OK)Error_Handler();
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
3 在中断函数中加入判断语句,是否完成一帧数据接收;

HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
frame.ReceiveUsart2length++;
if( __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)){
__HAL_UART_FLUSH_DRREGISTER(&huart2);
frame.ReceiveUsart2Flag=1;

}
4 在主函数中处理数据:

if(LORASemHandle!=NULL){
err=xSemaphoreTake(LORASemHandle,portMAX_DELAY);
if(err==pdTRUE){
printf(" FatFs is working well!!!\r\n");

}
}
5 经过测试,数据能够完整接收 ;



注意事项 :

1,开启串口中断中有一个参数是设置接收多少数据后停止接收的,你可以在 HAL_UART_IRQHandler 中的 UART_Receive_IT 里面 把这段代码屏蔽掉;

if(--huart->RxXferCount == 0U)
{
/* Disable the UART Parity Error Interrupt and RXNE interrupt*/
CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));

/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);

/* Rx process is completed, restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;

HAL_UART_RxCpltCallback(huart);

return HAL_OK;
}


下面补充个小技巧 使用printf 输出数据。在代码前面加上这段代码,现在使用的是串口1,可以修改映射到初始化的串口;

#ifdef __GNUC__

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{

// HAL_UART_Transmit_DMA(&huart1, (uint8_t *)&ch,1);
HAL_UART_Transmit(&huart1, (uint8_t *)(&(ch)), 1, 10);

return ch;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  stm32cube 串口 IDLE