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

占毛毛

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

暂无评论

发表评论

相关推荐

ESP32-GY_30光照强度传感器

GY_30光照强度传感器介绍 GY-30光强传感器特点及使用介绍 一、连接引脚 GY_30光照强度传感器使用I2C传输数据 。 5根引脚,名称与功能如下; vcc 为外接供电电源输入端 GND 地线 SCL I2C通信模式时钟

初学STM32之串口通信

一、背景知识 1. 处理器与外部通信的两种方式 并行通信:数据各个位同时传输 优点速度快;缺点占用引脚资源多串行通信:数据按位顺序传输 优点占用引脚资源少;缺点速度慢 2.串行通信的

GPIO口详解、HAL库操作按键

本次博客知识来自于韦东山老师的7天物联网课程。 一、GPIO详解 1、STM32F103C8T6一共有48个引脚。 2、按A、B、C分组,每组16个引脚,编号为0~15,STM32F103C8T6