OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6951|回复: 4

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

[复制链接]

11

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
109
金钱
109
注册时间
2019-5-15
在线时间
34 小时
发表于 2023-1-10 13:59:50 | 显示全部楼层 |阅读模式
10金钱
求助:STM32 串口IDLE接收空闲中断+DMA------波特率1200,数据接收错误.设备要求通信的波特率是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接收
        }

测试如下:

1.png
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

11

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
109
金钱
109
注册时间
2019-5-15
在线时间
34 小时
 楼主| 发表于 2023-1-10 17:34:50 | 显示全部楼层
STM32F4 USART1 1200波特率乱码问题找到了,USART1将APB2时钟的频率分频,由2分频改为4分频可解决
回复

使用道具 举报

7

主题

480

帖子

0

精华

高级会员

Rank: 4

积分
773
金钱
773
注册时间
2021-4-15
在线时间
304 小时
发表于 2023-1-11 09:36:17 | 显示全部楼层
波特率太低 要降频 之前遇到过
日常敲键--头秃一片
回复

使用道具 举报

11

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
109
金钱
109
注册时间
2019-5-15
在线时间
34 小时
 楼主| 发表于 2023-1-11 15:04:23 | 显示全部楼层
日渐秃兀 发表于 2023-1-11 09:36
波特率太低 要降频 之前遇到过

嗯,你说的是对的,把对应的时钟频率降下来就正常了。
具体如下:
STM32F4串口1挂在APB2上;我的系统HCLK=SYSCLK/1=180MHz,APB2采用的是2分频,也就是90MHZ;
正点原子寄存器版本第五章5.3usart文件夹有提到:
根据公式波特率分配系数计算,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波特率也可以得到正确的执行。
回复

使用道具 举报

7

主题

480

帖子

0

精华

高级会员

Rank: 4

积分
773
金钱
773
注册时间
2021-4-15
在线时间
304 小时
发表于 2023-1-11 15:13:17 | 显示全部楼层
chenshuibing 发表于 2023-1-11 15:04
嗯,你说的是对的,把对应的时钟频率降下来就正常了。
具体如下:
STM32F4串口1挂在APB2上;我的系统HC ...

还有误差计算公式的 之前在手册还是ST论坛看到 官方有给,不同频率下计算得到的误差 一般不是很精细的话 应该也不会影响很大
日常敲键--头秃一片
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-24 20:08

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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