硬汉嵌入式论坛

 找回密码
 立即注册
查看: 6000|回复: 11
收起左侧

[有问必答] HAL库使用空闲中断接收不定长数据第一帧数据丢失

[复制链接]

14

主题

31

回帖

73

积分

初级会员

积分
73
发表于 2020-12-4 10:33:38 | 显示全部楼层 |阅读模式
各位大牛,我在使用HAL库 空闲中断接收不定长数据,然后将接收到的数据再发送到电脑,第一帧数据一定会丢失,后面就正常了。有谁遇到过这样的问题的吗?

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration   
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
       

    /* USART1 DMA Init */
    /* USART1_RX Init */
    hdma_usart1_rx.Instance = DMA1_Channel5;
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode = DMA_NORMAL;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_HIGH;
    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);

    /* USART1_TX Init */
    hdma_usart1_tx.Instance = DMA1_Channel4;
    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_tx.Init.Mode = DMA_NORMAL;
    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_HIGH;
    if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);

    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);

         HAL_UART_Receive_DMA(uartHandle,recieve,64); //½óêÕ3õê¼»ˉ
         HAL_UART_Transmit_DMA(uartHandle,send,64); //·¢Ëí3õê¼»ˉ
       
         __HAL_UART_ENABLE_IT(uartHandle,UART_IT_IDLE);
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);
       
  /* USER CODE END USART1_MspInit 1 */
  }
}



if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)==SET)
{
                __HAL_UART_CLEAR_IDLEFLAG(&huart1);
               
                //__HAL_UART_CLEAR_PEFLAG(&huart1);
                temp = huart1.Instance->DR;
                temp = huart1.Instance->SR;
                temp = temp;
                len = 0;
                HAL_UART_DMAStop(&huart1);
                temp=__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
                len = 64 - temp;
                HAL_UART_Receive_DMA(&huart1,recieve,64); //½óêÕ3õê¼»ˉ
                memcpy(send,recieve,len);
                rx_flag =1 ;
               
}


while (1)
  {
         if(rx_flag == 1)
         {
                 HAL_UART_Transmit_DMA(&huart1,send,len);
                 rx_flag=0;
         }
}


回复

使用道具 举报

14

主题

31

回帖

73

积分

初级会员

积分
73
 楼主| 发表于 2020-12-4 10:44:37 | 显示全部楼层
电脑串口发送第一帧数据,程序进到了空闲中断,从现象看就是DMA接收到的数据为64,(但是接收buff的数据为空),len=64,在while中发送了64个0
回复

使用道具 举报

5

主题

192

回帖

212

积分

高级会员

积分
212
发表于 2020-12-4 11:06:16 | 显示全部楼层
STM32V6之串口HAL库串口空闲中断接收不定长字节代码实现 http://www.armbbs.cn/forum.php?m ... 77&fromuid=8820 (出处: 硬汉嵌入式论坛)
回复

使用道具 举报

334

主题

2036

回帖

3043

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3043
发表于 2020-12-4 11:10:27 | 显示全部楼层
可能是硬件上的问题。 mcu的RX接收端一定是上拉,最好是外部上拉。 千万不要默认成下拉到地之类的。
回复

使用道具 举报

5

主题

192

回帖

212

积分

高级会员

积分
212
发表于 2020-12-4 12:54:33 | 显示全部楼层
石头123 发表于 2020-12-4 10:44
电脑串口发送第一帧数据,程序进到了空闲中断,从现象看就是DMA接收到的数据为64,(但是接收buff的数据为空) ...

HAL_UART_Receive_DMA(uartHandle,recieve,64); //½óêÕ3õê¼»ˉ
         HAL_UART_Transmit_DMA(uartHandle,send,64); //·¢Ëí3õê¼»ˉ
      
         __HAL_UART_ENABLE_IT(uartHandle,UART_IT_IDLE);
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);

你开机的时候打印了64字节数据,你说的丢失不会是你自己开机打印的全0数据吧
回复

使用道具 举报

10

主题

140

回帖

170

积分

初级会员

积分
170
发表于 2020-12-4 13:05:39 | 显示全部楼层
在运行HAL_UART_MspInit之后,你没有调用 HAL_UART_Receive_DMA(&huart1,recieve,64),所以第1次进中断你的数据就丢失了。
解决方法就是在HAL_UART_MspInit的末尾
__HAL_UART_ENABLE_IT(uartHandle,UART_IT_IDLE);
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
之后调用HAL_UART_Receive_DMA(&huart1,recieve,64);
回复

使用道具 举报

14

主题

31

回帖

73

积分

初级会员

积分
73
 楼主| 发表于 2020-12-4 15:33:55 | 显示全部楼层
旮旯旭 发表于 2020-12-4 12:54
HAL_UART_Receive_DMA(uartHandle,recieve,64); //½óêÕ3õê¼»ˉ
         H ...

系统上电后,我从电脑端第一次发出任意数据,mcu返回来的都是64个0,然后后面就正常了,我发什么,就返回来什么。感觉是hal库的问题,我换成用标准库就没有mcu第一次接收数据丢失的问题。
回复

使用道具 举报

14

主题

31

回帖

73

积分

初级会员

积分
73
 楼主| 发表于 2020-12-4 15:51:23 | 显示全部楼层
lvehe 发表于 2020-12-4 13:05
在运行HAL_UART_MspInit之后,你没有调用 HAL_UART_Receive_DMA(&huart1,recieve,64),所以第1次进中断你的 ...

函数里有调用呀,我按照你说的把dma接受函数放在中断配置后还是一样有问题
回复

使用道具 举报

5

主题

192

回帖

212

积分

高级会员

积分
212
发表于 2020-12-4 20:32:34 | 显示全部楼层
石头123 发表于 2020-12-4 15:51
函数里有调用呀,我按照你说的把dma接受函数放在中断配置后还是一样有问题

我在F429上的程序没问题,可惜我没有F103的板子,不知道你具体那里搞出问题了
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
发表于 2020-12-5 14:59:25 | 显示全部楼层
标准库用mda,第一次上电第一帧丢失
回复

使用道具 举报

334

主题

2036

回帖

3043

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3043
发表于 2020-12-11 14:35:29 | 显示全部楼层
928399306 发表于 2020-12-5 14:59
标准库用mda,第一次上电第一帧丢失

stm32的中断响应有个特点,第一次开启中断后,立马跟上一个清空中断标志的代码。 不然会立马进入中断。

我在定时器中断里面经常碰到这个情况。 后来百度各种论坛发现,这是个普遍现象。
回复

使用道具 举报

12

主题

66

回帖

102

积分

初级会员

程序员小小弟

积分
102
发表于 2021-6-26 23:49:47 | 显示全部楼层
caicaptain2 发表于 2020-12-11 14:35
stm32的中断响应有个特点,第一次开启中断后,立马跟上一个清空中断标志的代码。 不然会立马进入中断。
...

你好,请问第一帧丢失这种情况有办法处理吗?谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-8 17:35 , Processed in 0.187440 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表