南落北晴 2024-04-17 14:29 采纳率: 0%
浏览 116
已结题

STM32 串口DMA同时收发丢字节

问题现象:STM32F4的2Mbps串口DMA接收丢字节
问题描述:
1.使用STM32H743串口以2Mbps间隔1ms发送数据,每帧数据大小18字节。发送使用HAL库串口DMA发送函数。该步骤使用CH343串口(最高6Mbps)验证发送没问题。
2.使用STM32F405串口和H743同样配置接收H743发送数据。接收采用IDLE+DMA方式接受数据,测试代码空闲中断中只累加获取到的数据,没有处理数据。
2.1当STM32F4不向H7发送数据,只接收数据时。STM32F4接收正常,数据总量符合H7在1s发送的数据量。
2.2但是当STM32F405以10ms间隔,每帧18字节数据向H7发送时,F4串口接收会出现丢字节现象。逻辑分析仪接Tx和Rx发现数据重合时另一方丢失,例先开始发送,发送中接收则收数据丢失。

img


因F4发送和接收外部强上拉,所以空闲是高电平。
CH343接F4的Rx,收到数据和F4内部收到数据量一样,但都有字节丢失。
问题备注:
1.H7和F4程序都是我写的,一样写法。这套写法(串口DMA发送,接受采用IDLE+DMA)和FPGA联调过,0.5ms数据间隔,每帧数据34字节,应答式收发没有问题
2.外部接线查过了,接线没问题,不用考虑接线问题
3.测试环境没有强EMI干扰,测试线也很短,不用考虑线长问题
4.F4换过板子,换过开发板都测过了,问题依旧
5.使用的HAL库,换标准库也试过了,一样的问题
6.F4的HAL库是1.27的不是最新,但是不算很老
7.波特率升到3Mbps试过了,也是一样的问题,包括更改过采样,串口加奇偶校验
8.网上有说是HAL库的问题,导致处理时候回关闭DMA,这个也优化过了采用不暂定DMA的方法HAL_UARTEx_ReceiveToIdle_DMA()也是一样的效果。
9.疑问,STM32不是全双工的吗?为什么同时收发回出现丢字节问题,什么原因,该如何解决

  • 写回答

26条回答 默认 最新

  • 阿里嘎多学长 2024-04-17 14:32
    关注
    获得0.15元问题酬金

    以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:


    根据您提供的链接内容,这是一个关于STM32串口DMA同时收发丢字节的问题。问题描述了在STM32F405和STM32H743之间进行串口通信时,当STM32F405同时发送和接收数据时,会出现丢字节的现象。这个问题涉及到串口通信的全双工模式以及DMA(直接内存访问)的使用。

    在解决这个问题之前,我们需要考虑以下几个可能的原因:

    1. DMA配置问题:确保DMA的接收和发送通道都正确配置,并且没有冲突。
    2. 中断冲突:如果DMA的接收和发送共享同一个中断,可能会有中断优先级或处理冲突的问题。
    3. 硬件设计问题:尽管问题备注中提到外部接线没有问题,但仍然需要确认硬件设计是否支持全双工通信,包括上拉电阻的使用等。
    4. 软件逻辑问题:检查软件逻辑是否在接收和发送数据时有冲突,比如缓冲区溢出或处理不当。

    为了解决这个问题,我们可以尝试以下步骤:

    步骤1:检查DMA配置

    确保DMA的接收和发送通道都正确配置,没有地址、大小或优先级冲突。

    步骤2:优化中断处理

    如果DMA的接收和发送共享同一个中断,优化中断服务程序,确保优先级设置正确,并且中断处理逻辑没有错误。

    步骤3:硬件检查

    再次检查硬件设计,确保支持全双工通信。

    步骤4:软件逻辑优化

    检查软件逻辑,确保接收和发送缓冲区大小合适,并且没有数据溢出。

    示例代码

    由于问题描述中没有提供具体的代码,我将提供一个基本的STM32串口DMA配置示例,以供参考:

    // 假设使用USART1
    USART_HandleTypeDef huart1;
    DMA_HandleTypeDef hdma_usart1_rx;
    DMA_HandleTypeDef hdma_usart1_tx;
    
    // 初始化USART1的句柄
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 2000000; // 2Mbps
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    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;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    HAL_UART_Init(&huart1);
    
    // 初始化DMA接收通道
    hdma_usart1_rx.Instance = DMA1_Stream0;
    hdma_usart1_rx.Init.Channel = DMA_CHANNEL_0;
    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_CIRCULAR;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_usart1_rx);
    
    // 初始化DMA发送通道
    hdma_usart1_tx.Instance = DMA1_Stream1;
    hdma_usart1_tx.Init.Channel = DMA_CHANNEL_1;
    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;
    HAL_DMA_Init(&hdma_usart1_tx);
    
    // 将DMA接收通道关联到USART1的RX
    __HAL_LINKDMA(&huart1, hdmarx, hdma_usart1_rx);
    
    // 将DMA发送通道关联到USART1的TX
    __HAL_LINKDMA(&huart1, hdmatx, hdma_usart1_tx);
    
    // 启动DMA接收和发送
    HAL_UART_Receive_DMA(&huart1, (uint8_t *)rxBuffer, 18);
    HAL_UART_Transmit_DMA(&huart1, (uint8_t *)txBuffer, 18);
    

    请注意,这只是一个基础示例,实际应用中可能需要根据具体的硬件配置和需求进行调整。如果问题依然存在,可能需要进一步的调试和分析。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 4月25日
  • 创建了问题 4月17日

悬赏问题

  • ¥20 python忆阻器数字识别
  • ¥15 无法输出helloworld
  • ¥15 高通uboot 打印ubi init err 22
  • ¥20 PDF元数据中的XMP媒体管理属性
  • ¥15 R语言中lasso回归报错
  • ¥15 网站突然不能访问了,上午还好好的
  • ¥15 有没有dl可以帮弄”我去图书馆”秒选道具和积分
  • ¥15 semrush,SEO,内嵌网站,api
  • ¥15 Stata:为什么reghdfe后的因变量没有被发现识别啊
  • ¥15 振荡电路,ADS仿真