NXP串口高波特率踩坑记录

最近使用NXP9080MCU的串口,使用921600波特率通信,发现几个大坑,记录之~。

坑1:波特率不准

调试过程中发现,115200可正常通信,修改波特率为921600后出现各种问题。抓取波形后确定为MCU问题。遂查看datesheet:
908x的串口时钟来源:外部或内部晶振->systemcore时钟->AHB->Flexcomm接口->USART 。
这里较于其他MCU比较特殊的是有一个Flex接口,多通信方式接口(SPI I2C)。可通过配置FRG寄存器来获取更精确的波特率。计算方式:Flexcomm interface clock: (FRG input clock) / (1+ (MULT / DIV)),DIV为0XFF,MULT可配置,这样分频系数变成了一个1~2之间的小数,再通过USART的波特率分频寄存器便可获得更精确的波特率: baud rate: [FCLK / (OSRVAL+ 1)] / (BRGVAL + 1)。
配置FRG:

        CLOCK_SetFRGClock(kCLOCK_DivFrg0,
                          FLEXCOMM_CLK((CLOCK_GetFreq(kCLOCK_BusClk)), 
                          gUARTBaudRate921600_c));

坑2:丢数据

调试BLE的SDK时发现,串口在921600时,一次接收100个字节以上会丢包。查看SDK串口底层实现方式:有一个专门的串口任务,套了两层回调接收函数,触发事件的方式来接收(原厂的代码确实美观)。最底层还是通过接收中断来触发的,即一个字节触发一次中断(什么?原厂居然用这么LOW的方法)。应该就是速率变高,一次接收数据较大时,中断过于频繁导致。只能说Fuck中断,开始调DMA接收。

坑3 DMA的DEMO的错误

波特率分频不准:
调DMA的DEMO时发现,速率高时有无法通信,可是已经配置了小数分频了啊。最终发现波特率寄存器配置不准,查看波特率配置函数,对比计算准确的代码。
计算错误:

brgval = (((srcClock_Hz * 10) / ((osrval + 1) * baudrate_Bps)) - 5) / 10;

计算正确:

brgval = (srcClock_Hz / ((osrval + 1) * baudrate_Bps)) - 1;

DMA获取当前接收数据错误:

uint32_t DMA_GetRemainingBytes(DMA_Type *base, uint32_t channel)
{
    assert(channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS);

    /* NOTE: when descriptors are chained, ACTIVE bit is set for whole chain. It makes 
     * impossible to distinguish between:
     * - transfer finishes (represented by value '0x3FF')
     * - and remaining 1024 bytes to transfer (value 0x3FF)
     * for all descriptor in chain, except the last one.
     * If you decide to use this function, please use 1023 transfers as maximal value */

    /* Channel not active (transfer finished) and value is 0x3FF - nothing to transfer */
    if (
        (!(base->COMMON[DMA_CHANNEL_GROUP(channel)].ACTIVE & (1U << (DMA_CHANNEL_INDEX(channel))))) && 
        (0x3FF == ((base->CHANNEL[channel].XFERCFG & DMA_CHANNEL_XFERCFG_XFERCOUNT_MASK) >> DMA_CHANNEL_XFERCFG_XFERCOUNT_SHIFT))
    )
    {
        return 0;
    }

    return base->CHANNEL[channel].XFERCFG + 1;
}

要改为

    uint32_t k = base->CHANNEL[channel].XFERCFG>>16;
    k = k+1;
    return k;

总结

一个串口出现这么多问题,基本都是波特率调到最高发生的,一般115200就好。

版权声明:本文为CSDN博主「占毛毛」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_40570010/article/details/122250153

最近使用NXP9080MCU的串口,使用921600波特率通信,发现几个大坑,记录之~。

坑1:波特率不准

调试过程中发现,115200可正常通信,修改波特率为921600后出现各种问题。抓取波形后确定为MCU问题。遂查看datesheet:
908x的串口时钟来源:外部或内部晶振->systemcore时钟->AHB->Flexcomm接口->USART 。
这里较于其他MCU比较特殊的是有一个Flex接口,多通信方式接口(SPI I2C)。可通过配置FRG寄存器来获取更精确的波特率。计算方式:Flexcomm interface clock: (FRG input clock) / (1+ (MULT / DIV)),DIV为0XFF,MULT可配置,这样分频系数变成了一个1~2之间的小数,再通过USART的波特率分频寄存器便可获得更精确的波特率: baud rate: [FCLK / (OSRVAL+ 1)] / (BRGVAL + 1)。
配置FRG:

        CLOCK_SetFRGClock(kCLOCK_DivFrg0,
                          FLEXCOMM_CLK((CLOCK_GetFreq(kCLOCK_BusClk)), 
                          gUARTBaudRate921600_c));

坑2:丢数据

调试BLE的SDK时发现,串口在921600时,一次接收100个字节以上会丢包。查看SDK串口底层实现方式:有一个专门的串口任务,套了两层回调接收函数,触发事件的方式来接收(原厂的代码确实美观)。最底层还是通过接收中断来触发的,即一个字节触发一次中断(什么?原厂居然用这么LOW的方法)。应该就是速率变高,一次接收数据较大时,中断过于频繁导致。只能说Fuck中断,开始调DMA接收。

坑3 DMA的DEMO的错误

波特率分频不准:
调DMA的DEMO时发现,速率高时有无法通信,可是已经配置了小数分频了啊。最终发现波特率寄存器配置不准,查看波特率配置函数,对比计算准确的代码。
计算错误:

brgval = (((srcClock_Hz * 10) / ((osrval + 1) * baudrate_Bps)) - 5) / 10;

计算正确:

brgval = (srcClock_Hz / ((osrval + 1) * baudrate_Bps)) - 1;

DMA获取当前接收数据错误:

uint32_t DMA_GetRemainingBytes(DMA_Type *base, uint32_t channel)
{
    assert(channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS);

    /* NOTE: when descriptors are chained, ACTIVE bit is set for whole chain. It makes 
     * impossible to distinguish between:
     * - transfer finishes (represented by value '0x3FF')
     * - and remaining 1024 bytes to transfer (value 0x3FF)
     * for all descriptor in chain, except the last one.
     * If you decide to use this function, please use 1023 transfers as maximal value */

    /* Channel not active (transfer finished) and value is 0x3FF - nothing to transfer */
    if (
        (!(base->COMMON[DMA_CHANNEL_GROUP(channel)].ACTIVE & (1U << (DMA_CHANNEL_INDEX(channel))))) && 
        (0x3FF == ((base->CHANNEL[channel].XFERCFG & DMA_CHANNEL_XFERCFG_XFERCOUNT_MASK) >> DMA_CHANNEL_XFERCFG_XFERCOUNT_SHIFT))
    )
    {
        return 0;
    }

    return base->CHANNEL[channel].XFERCFG + 1;
}

要改为

    uint32_t k = base->CHANNEL[channel].XFERCFG>>16;
    k = k+1;
    return k;

总结

一个串口出现这么多问题,基本都是波特率调到最高发生的,一般115200就好。

版权声明:本文为CSDN博主「占毛毛」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_40570010/article/details/122250153

生成海报
点赞 0

占毛毛

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32 QSPI双闪存操作

STM32 QSPI双闪存操作 使用CubeMX或者CubeIDE生成框架 使用野火的开发板,MCU型号为stm32h750/743,他们家核心板上使用了QSPI挂了2片FLASH,型号为W25Q2

STM32串口发送接收数据

1.串口通信 我用的32是stm32f10x最小系统没有UART4和UART5 USART : 通用同步异步收发器 UART : 通用异步收发器 nRTS : 请求发送 nCTS : 请求接收 区别:USART指单片机的一个IO端

韦东山物联网学习第一课

今天我重温习了一下STM32的物联网编程。主要重新温故了一下STM32的时钟设置,并放上了注释: void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_