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

占毛毛

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

暂无评论

发表评论

相关推荐

STM32C8T6+LORA(SX1278)

LoRa通信系统 从毕设开始搭建了一个简单的LORA通信系统(两块STM32C8T6最小单片机系统,两块正点原子的loRa,一块温湿度传感器)构建了一个简单的loRa通信系统作为入门。之