硬汉嵌入式论坛

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

[UART] 串口RXNE不置位的问题

[复制链接]

4

主题

19

回帖

31

积分

新手上路

积分
31
发表于 2021-9-9 14:53:09 | 显示全部楼层 |阅读模式
最近在调试双向传输,帧间隔5-10ms级同时收发,发现收发一段时间后,RDR寄存器就会停止读值,RXNE也不会自动置位,导致IDLE也不会置位。就会造成收不到数据,头疼的一匹。还望哪位大佬遇到过这种情况指导一下
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106978
QQ
发表于 2021-9-9 15:22:02 | 显示全部楼层
上代码看下,仅串口的配置的应用部分。
回复

使用道具 举报

4

主题

19

回帖

31

积分

新手上路

积分
31
 楼主| 发表于 2021-9-9 15:29:03 | 显示全部楼层
/*
*********************************************************************************************************
*        函 数 名: 串口1初始化函数
*        功能说明: 串口1初始化
*        形    参:u32 bound        波特率
*        返 回 值: 无
*********************************************************************************************************
*/
void uart_init(u32 bound)
{       
        //UART 初始化设置
        UART1_Handler.Instance=USART1;                                            //USART1
        UART1_Handler.Init.BaudRate=bound;                                    //波特率
        UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
        UART1_Handler.Init.StopBits=UART_STOPBITS_1;            //一个停止位
        UART1_Handler.Init.Parity=UART_PARITY_NONE;                    //无奇偶校验位
        UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
        UART1_Handler.Init.Mode=UART_MODE_TX_RX;                    //收发模式
        UART1_Handler.Init.OverSampling = UART_OVERSAMPLING_16;                //16倍过采样
        HAL_UART_Init(&UART1_Handler);                                            //HAL_UART_Init()会使能UART1
          
        __HAL_UART_ENABLE_IT(&UART1_Handler, UART_IT_IDLE);          //开启空闲接收中断
        HAL_UART_Receive_DMA(&UART1_Handler,Res,100);
  __HAL_UART_DISABLE_IT(&UART1_Handler, UART_IT_ERR);
  __HAL_UART_DISABLE_IT(&UART1_Handler, UART_IT_PE);

}

/*
*********************************************************************************************************
*        函 数 名: UART底层初始化
*        功能说明: 时钟使能,引脚配置,中断配置
*        形    参:UART_HandleTypeDef *huart串口句柄
*        返 回 值: 无
*********************************************************************************************************
*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    //GPIO端口设置
        GPIO_InitTypeDef GPIO_Initure;
       
        if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
        {
                __HAL_RCC_GPIOA_CLK_ENABLE();                        //使能GPIOA时钟
                __HAL_RCC_USART1_CLK_ENABLE();                        //使能USART1时钟
       
                GPIO_Initure.Pin=GPIO_PIN_9;                        //PA9
                GPIO_Initure.Mode=GPIO_MODE_AF_PP;                //复用推挽输出
                GPIO_Initure.Pull=GPIO_PULLUP;                        //上拉
                GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
                GPIO_Initure.Alternate=GPIO_AF7_USART1;        //复用为USART1
                HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //初始化PA9

                GPIO_Initure.Pin=GPIO_PIN_10;                        //PA10
                HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //初始化PA10

                HAL_NVIC_SetPriority(USART1_IRQn,3,3);                        //抢占优先级3,子优先级3
                HAL_NVIC_EnableIRQ(USART1_IRQn);                                //使能USART1中断通道       
        }

}


       
u8 OER_Count = 0;

/*
*********************************************************************************************************
*        函 数 名: 串口1中断服务函数
*        功能说明: DMA接收模式
*        形    参:无
*        返 回 值: 无
*********************************************************************************************************
*/
void USART1_IRQHandler(void)                       
{
        static u8 uart_i = 0;
        u32 len;
        u16 temp;
        u8 tmp_flag = 0;

  uint32_t isrflags   = READ_REG(UART1_Handler.Instance->ISR);        //读取ISR寄存器值
  uint32_t cr1its     = READ_REG(UART1_Handler.Instance->CR1);        //读取CR1寄存器值

        HAL_UART_IRQHandler(&UART1_Handler);

  if(((isrflags & USART_ISR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET))        //空闲线检测标志 &&        空闲中断使能
        {
                        __HAL_UART_CLEAR_IDLEFLAG(&UART1_Handler);                                                                                                                //清除空闲中断
                        Rx_EndFlag = 1;                                                                                                                                                                                                                                //接收完当前数据
        }
        if((__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_ORE)!=RESET))
        {
                __HAL_UART_CLEAR_FLAG(&UART1_Handler, UART_FLAG_ORE);                                                                                //清除溢出标志位
                uart_ORE_Flag = 1;
                OER_Count++;
        }

}
触发中断后就会执行下面的写入缓存区函数
回复

使用道具 举报

4

主题

19

回帖

31

积分

新手上路

积分
31
 楼主| 发表于 2021-9-9 15:30:53 | 显示全部楼层
        if(Rx_Len)
        {
                HAL_UART_DMAStopRx(&UART1_Handler);                                                                                                                                        //停止接收函数
                HAL_UART_Receive_DMA(&UART1_Handler,Res,100);                                                                                                //DMA模式读取数据
                __HAL_UART_DISABLE_IT(&UART1_Handler, UART_IT_ERR);       
                __HAL_UART_DISABLE_IT(&UART1_Handler, UART_IT_PE);

                SCB_CleanInvalidateDCache();                                                                                                                                                                //更新RAM数据
                wirteRingbuffer(&Uart_Buff,Res,Rx_Len);                                                                                                                        //写入缓存区
        }
回复

使用道具 举报

4

主题

19

回帖

31

积分

新手上路

积分
31
 楼主| 发表于 2021-9-9 15:31:14 | 显示全部楼层
eric2013 发表于 2021-9-9 15:22
上代码看下,仅串口的配置的应用部分。

代码部分放在楼下了
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106978
QQ
发表于 2021-9-9 16:48:32 | 显示全部楼层
497356044 发表于 2021-9-9 15:31
代码部分放在楼下了

你这个是DMA配合空闲方式?
回复

使用道具 举报

4

主题

19

回帖

31

积分

新手上路

积分
31
 楼主| 发表于 2021-9-9 17:04:54 | 显示全部楼层
eric2013 发表于 2021-9-9 16:48
你这个是DMA配合空闲方式?

/*
*********************************************************************************************************
*        函 数 名: MYDMA_Config
*        功能说明: DMA初始化配置函数
*        形    参:DMA_Streamx_txMA发送数据流,DMA_Streamx_rxMA接收数据流
*        返 回 值: 无
*********************************************************************************************************
*/
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx_tx,DMA_Stream_TypeDef *DMA_Streamx_rx)
{
    __HAL_RCC_DMA2_CLK_ENABLE();//DMA2时钟使能       


          /* USART1 DMA Init */
   
    //Tx DMA配置
    UART1TxDMA_Handler.Instance=DMA_Streamx_tx;                            //数据流选择
                UART1TxDMA_Handler.Init.Request=DMA_REQUEST_USART1_TX;                                //USART1发送DMA
    UART1TxDMA_Handler.Init.Direction=DMA_MEMORY_TO_PERIPH;             //存储器到外设
    UART1TxDMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE;                 //外设非增量模式
    UART1TxDMA_Handler.Init.MemInc=DMA_MINC_ENABLE;                     //存储器增量模式
    UART1TxDMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;    //外设数据长度:8位
    UART1TxDMA_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE;       //存储器数据长度:8位
    UART1TxDMA_Handler.Init.Mode=DMA_NORMAL;                            //外设流控模式
    UART1TxDMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM;               //中等优先级
    UART1TxDMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE;              
    UART1TxDMA_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;      
    UART1TxDMA_Handler.Init.MemBurst=DMA_MBURST_SINGLE;                 //存储器突发单次传输
    UART1TxDMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE;              //外设突发单次传输
       
    __HAL_LINKDMA(&UART1_Handler,hdmatx,UART1TxDMA_Handler);    //将发送DMA与USART1联系起来(发送DMA)


    /* USART1_RX Init */               
                UART1RxDMA_Handler.Instance = DMA_Streamx_rx;
                UART1RxDMA_Handler.Init.Request=DMA_REQUEST_USART1_RX;                                                        //USART1接收DMA
                UART1RxDMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY;                                                        //外设到存储器
    UART1RxDMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE;                 //外设非增量模式
    UART1RxDMA_Handler.Init.MemInc=DMA_MINC_ENABLE;                     //存储器增量模式
    UART1RxDMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;    //外设数据长度:8位
    UART1RxDMA_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE;       //存储器数据长度:8位
    UART1RxDMA_Handler.Init.Mode=DMA_NORMAL;                            //外设流控模式
    UART1RxDMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM;               //中等优先级
    UART1RxDMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE;              //禁止FIFO
    UART1RxDMA_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;      //禁止FIFO此位不起作用,用于设置阀值
    UART1RxDMA_Handler.Init.MemBurst=DMA_MBURST_SINGLE;                 //禁止FIFO此位不起作用,存储器突发单次传输
    UART1RxDMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE;              //禁用FIFO此位不起作用,外设突发单次传输               

                __HAL_LINKDMA(&UART1_Handler,hdmarx,UART1RxDMA_Handler);    //将接收DMA与USART1联系起来(接收DMA)
                        /* 设置DMA接收中断 */
                HAL_DMA_RegisterCallback(&UART1TxDMA_Handler, HAL_DMA_XFER_CPLT_CB_ID, HAL_UARTDMA_TxCpltCallback);
   
    HAL_DMA_DeInit(&UART1TxDMA_Handler);
                HAL_DMA_DeInit(&UART1RxDMA_Handler);
    HAL_DMA_Init(&UART1TxDMA_Handler);
                HAL_DMA_Init(&UART1RxDMA_Handler);
               
                /* DMA interrupt init */
                /* DMA2_Stream6_IRQn interrupt configuration */
                HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 0, 0);
                HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
                /* DMA2_Stream7_IRQn interrupt configuration */
                HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 0, 1);
                HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
}

/*
*********************************************************************************************************
*        函 数 名: HAL_UARTDMA_TxCpltCallback
*        功能说明: DMA模式串口中断的发送完成回调函数。
*        形    参:UartHandle,UART_HandleTypeDef结构体变量
*        返 回 值: 无
*********************************************************************************************************
*/

void HAL_UARTDMA_TxCpltCallback(DMA_HandleTypeDef *_hdma)
{
        /*无效*/

}


void DMA2_Stream6_IRQHandler(void)                //DMA接收
{
  HAL_DMA_IRQHandler(&UART1RxDMA_Handler);
}

/**
  * @brief This function handles DMA1 stream1 global interrupt.
  */
void DMA2_Stream7_IRQHandler(void)        //DMA发送
{
       
  HAL_DMA_IRQHandler(&UART1TxDMA_Handler);
        if(__HAL_DMA_GET_FLAG(&UART1TxDMA_Handler,DMA_FLAG_TCIF3_7) != RESET)
        {
                __HAL_DMA_CLEAR_FLAG(&UART1TxDMA_Handler,DMA_FLAG_TCIF3_7);                                                //清除DMA2_Steam7传输完成标志
                HAL_UART_DMAStop(&UART1_Handler);      //传输完成以后关闭串口DMA
        }
        if(__HAL_DMA_GET_FLAG(&UART1TxDMA_Handler,DMA_FLAG_TEIF3_7) != RESET)
        {
                __HAL_DMA_CLEAR_FLAG(&UART1TxDMA_Handler,DMA_FLAG_TEIF3_7);                                                //清除错误标志位       
        }
}这个是DMA部分的配置   串口DMA模式配合空闲中断
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106978
QQ
发表于 2021-9-9 17:12:54 | 显示全部楼层
497356044 发表于 2021-9-9 17:04
/*
********************************************************************************************** ...

对比下坛友这个。

STM32H7基于STM32CubeMX的串口DMA+空闲中断接收不定长数据实现(HAL库1.9.0自带函数实现)
http://www.armbbs.cn/forum.php?m ... 8553&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-13 00:30 , Processed in 0.169560 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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