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

占毛毛

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

暂无评论

发表评论

相关推荐

四足机器狗——12自由度舵机狗DIY(一)

文章目录 前言 一、初步了解四足结构 1.1.2串联机构 1.2 四足关节配置 二、结构方案选择及舵机选型 2.1并联与串联机构的选型 2.2 四足关节配置的选择 2.3 电机选型(有经济基础的建议尝试) 2.4 舵

rt_thread hc32f460开发四:pwm驱动移植

RT-Thread 驱动开发简介 RT-Thread驱动开发最开始应该是要阅读官方的文档,理解驱动的运行原理和使用方法。PWM部分的文档在这里https://www.rt-thread.org/document/site/#/rt

基于STM32的LoRa无线通信(AS32—TTL-1W)

目录 无线串口简介 项目简介 发送端代码 接收端代码 项目总结 前些天接触到一个小项目,需要使用无线传输的功能,不仅如此还需要远距离的通信,搜索资料后最终选择了泽耀科技的LoRa&#xff08

w25qxx spi flash WP写保护引脚的正确使用方式

WP引脚使用方式 spi flash有一个外部写保护引脚WP, 此引脚并不是直接保护flash上的数据内容,而是保护状态寄存器不被异常改写.flash上的内容写保护是通过状态寄存器的BPxbit的不同组合来实现的. 对于环境相对恶劣的使用场景