硬汉嵌入式论坛

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

[技术讨论] 求助:STM32 串口IDLE接收空闲中断+DMA------波特率1200,数据接收错误

[复制链接]

10

主题

29

回帖

59

积分

初级会员

积分
59
发表于 2023-1-10 13:51:30 | 显示全部楼层 |阅读模式
    STM32F4 HAL,串口IDLE接收空闲中断+DMA------波特率1200,数据接收错误;
    PS:把MX_USART1_UART_Init函数中程序默认波特率设置改为2400、115200,串口助手调试通信正常。
程序如下:

初始化函数如下:
void MX_USART1_UART_Init(void)
{
  huart1.Instance = USART1;
huart1.Init.BaudRate = 1200;                                    //波特率
  huart1.Init.WordLength = UART_WORDLENGTH_8B;   //字长为9位数据格式
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;                    //校验位
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);

  //DMA接收函数(启动DMA接收),此句一定要加,不加接收不到第一次传进来的实数据,是空的,且此时接收到的数据长度为缓存器的数据长度
        HAL_UART_Receive_DMA(&huart1,USART1_RE.Data_BUFF2,BUFFER_SIZE);
}


中断处理如下:
void USART1_IRQHandler(void)
{
        uint32_t tmp_flag = 0;
        uint32_t temp;
        tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
        if((tmp_flag != RESET))//idle标志被置位
        {
                __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
                //temp = huart1.Instance->SR;  //清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能
                //temp = huart1.Instance->DR; //读取数据寄存器中的数据
                //这两句和上面那句等效
                HAL_UART_DMAStop(&huart1); //  停止DMA传输,防止
                temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中未传输的数据个数   
                //temp  = hdma_usart1_rx.Instance->NDTR;// 读取NDTR寄存器,获取DMA中未传输的数据个数,
                USART1_RE.Data_Num =  BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
    //一帧数据接收完成
                USART1_RE.END_FG = 1;   
         }

  /* USER CODE BEGIN USART2_IRQn 0 */

  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART2_IRQn 1 */

  /* USER CODE END USART2_IRQn 1 */

}


主函数如下:
       ......
        if((USART1_RE.END_FG))
        {
                USART1_RE.END_FG = 0;
                               
                HAL_UART_Transmit_IT(&huart1, USART1_RE.Data_BUFF2, USART1_RE.Data_Num);//自收自发
                while (huart1.gState != HAL_UART_STATE_READY)//test 20230103 发送未完成:延时1毫秒,等待发送完成
               {
                   HAL_Delay(1);//延时
               }
       
                for(uint8_t i = 0;i <= USART1_RE.Data_Num; i++)
                    USART1_RE.Data_BUFF2 = 0;

                USART1_RE.Data_Num = 0;
                HAL_UART_Receive_DMA(&huart1,USART1_RE.Data_BUFF2,BUFFER_SIZE);//重新打开DMA接收
        }




测试如下:


波特率1200测试图

波特率1200测试图
回复

使用道具 举报

12

主题

48

回帖

84

积分

初级会员

积分
84
发表于 2023-1-10 17:25:59 | 显示全部楼层
你可以去看一下手册里波特率设置,你设置的波特率有点低,有可能不能设置成功。
回复

使用道具 举报

10

主题

29

回帖

59

积分

初级会员

积分
59
 楼主| 发表于 2023-1-10 17:34:10 | 显示全部楼层
STM32F4 USART1 1200波特率乱码问题找到了,USART1将APB2的频率分频,由2分频改为4分频可解决
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111540
QQ
发表于 2023-1-11 09:07:01 | 显示全部楼层
2774799399 发表于 2023-1-10 17:34
STM32F4 USART1 1200波特率乱码问题找到了,USART1将APB2的频率分频,由2分频改为4分频可解决

谢谢告知最终原因。
回复

使用道具 举报

21

主题

287

回帖

350

积分

高级会员

积分
350
发表于 2023-1-11 10:08:04 | 显示全部楼层
F4波特率分频器的整数位只有12位,位数不够,F429 APB2默认90MHz, 当使用16倍过采样的时候,波特率最小 90'000'000/16/(2^12) = 1'373
回复

使用道具 举报

10

主题

29

回帖

59

积分

初级会员

积分
59
 楼主| 发表于 2023-1-11 15:05:21 | 显示全部楼层
music1273 发表于 2023-1-10 17:25
你可以去看一下手册里波特率设置,你设置的波特率有点低,有可能不能设置成功。

是的,没错
回复

使用道具 举报

10

主题

29

回帖

59

积分

初级会员

积分
59
 楼主| 发表于 2023-1-11 15:06:53 | 显示全部楼层
tovinz 发表于 2023-1-11 10:08
F4波特率分频器的整数位只有12位,位数不够,F429 APB2默认90MHz, 当使用16倍过采样的时候,波特率最小 90' ...

你说的对。
把对应的时钟频率降下来就正常了。
具体如下:
STM32F4串口1挂在APB2上;我的系统HCLK=SYSCLK/1=180MHz,APB2采用的是2分频,也就是90MHZ;
根据公式波特率分配系数计算,1200波特率,USARTDIV=90000000/(1200*16)=4687.5;
而串口的波特率寄存器 USART_BRR,DIV_Mantissa占位15:4,DIV_Fraction占位3:0,明显4687.5超过12位的取值范围,所以工作异常;但是其他波特率比如2400,换算出结果为2343.75,符合范围;同样的降低APB2的频率,1200波特率也可以得到正确的执行。

评分

参与人数 1金币 +1 收起 理由
伊森亨特 + 1 赞一个,替别人踩了个坑

查看全部评分

回复

使用道具 举报

10

主题

29

回帖

59

积分

初级会员

积分
59
 楼主| 发表于 2023-1-11 15:08:21 | 显示全部楼层
tovinz 发表于 2023-1-11 10:08
F4波特率分频器的整数位只有12位,位数不够,F429 APB2默认90MHz, 当使用16倍过采样的时候,波特率最小 90' ...

你说得对!
把对应的时钟频率降下来就正常了。
具体如下:
STM32F4串口1挂在APB2上;我的系统HCLK=SYSCLK/1=180MHz,APB2采用的是2分频,也就是90MHZ;
根据公式波特率分配系数计算,1200波特率,USARTDIV=90000000/(1200*16)=4687.5;
而串口的波特率寄存器 USART_BRR,DIV_Mantissa占位15:4,DIV_Fraction占位3:0,明显4687.5超过12位的取值范围,所以工作异常;但是其他波特率比如2400,换算出结果为2343.75,符合范围;同样的降低APB2的频率,1200波特率也可以得到正确的执行。
回复

使用道具 举报

6

主题

659

回帖

677

积分

金牌会员

积分
677
QQ
发表于 2023-1-12 09:09:29 | 显示全部楼层
感谢分享
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-1 07:35 , Processed in 0.281325 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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