查看: 3944|回复: 18

[求助] KL16串口的问题

[复制链接]

该用户从未签到

3

主题

13

帖子

0

注册会员

Rank: 2

积分
61
最后登录
2015-6-19
发表于 2015-6-3 21:48:12 | 显示全部楼层 |阅读模式
本帖最后由 gaow11 于 2015-6-3 21:50 编辑

各位大侠:
       我用KL16的UART0串口每隔1ms给电脑发送一帧数据,格式是61 XX XX XX XX 共五个字节这样的,115200波特率,但是在串口猎人上接收到的数据会有丢数据或者数据不对的,看了一下寄存器,实际波特率算下来是117647,我用的是网上的例程,串口初始化函数是uart0_init(UART0_BASE_PTR,2000,115200);

void uart0_init (UART0_MemMapPtr uartch, int sysclk, int baud)
{
    uint8 i;
    uint32 calculated_baud = 0;
    uint32 baud_diff = 0;
    uint32 osr_val = 0;
    uint32 sbr_val, uart0clk;
    uint32 baud_rate;
    uint32 reg_temp = 0;
    uint32 temp = 0;
   
    SIM_SCGC4 |= SIM_SCGC4_UART0_MASK;
   
    // Disable UART0 before changing registers
    UART0_C2 &= ~(UART0_C2_TE_MASK | UART0_C2_RE_MASK);
  
    // Verify that a valid clock value has been passed to the function
    if ((sysclk > 50000) || (sysclk < 32))
    {
        sysclk = 0;
        reg_temp = SIM_SOPT2;
        reg_temp &= ~SIM_SOPT2_UART0SRC_MASK;
        reg_temp |= SIM_SOPT2_UART0SRC(0);
        SIM_SOPT2 = reg_temp;
    }
   
    // Verify that a valid value has been passed to TERM_PORT_NUM and update
    // uart0_clk_hz accordingly.  Write 0 to TERM_PORT_NUM if an invalid
    // value has been passed.  
    if (TERM_PORT_NUM != 0)
    {
        reg_temp = SIM_SOPT2;
        reg_temp &= ~SIM_SOPT2_UART0SRC_MASK;
        reg_temp |= SIM_SOPT2_UART0SRC(0);
        SIM_SOPT2 = reg_temp;
   
     // Enter inifinite loop because the
     // the desired terminal port number
     // invalid!!
     while(1)
    {}
    }
   
   
   
    // Initialize baud rate
    baud_rate = baud;
   
    // Change units to Hz
    uart0clk = sysclk * 1000;
    // Calculate the first baud rate using the lowest OSR value possible.  
    i = 4;
    sbr_val = (uint32)(uart0clk/(baud_rate * i));
    calculated_baud = (uart0clk / (i * sbr_val));
        
    if (calculated_baud > baud_rate)
        baud_diff = calculated_baud - baud_rate;
    else
        baud_diff = baud_rate - calculated_baud;
   
    osr_val = i;
        
    // Select the best OSR value
    for (i = 5; i <= 32; i++)
    {
        sbr_val = (uint32)(uart0clk/(baud_rate * i));
        calculated_baud = (uart0clk / (i * sbr_val));
        
        if (calculated_baud > baud_rate)
            temp = calculated_baud - baud_rate;
        else
            temp = baud_rate - calculated_baud;
        
        if (temp <= baud_diff)
        {
            baud_diff = temp;
            osr_val = i;
        }
    }
   
    if (baud_diff < ((baud_rate / 100) * 3))
    {
        // If the OSR is between 4x and 8x then both
        // edge sampling MUST be turned on.  
        if ((osr_val >3) && (osr_val < 9))
            UART0_C5|= UART0_C5_BOTHEDGE_MASK;
        
        // Setup OSR value
        reg_temp = UART0_C4;
        reg_temp &= ~UART0_C4_OSR_MASK;
        reg_temp |= UART0_C4_OSR(osr_val-1);
   
        // Write reg_temp to C4 register
        UART0_C4 = reg_temp;
        
        reg_temp = (reg_temp & UART0_C4_OSR_MASK) + 1;
        sbr_val = (uint32)((uart0clk)/(baud_rate * (reg_temp)));
        
         /* Save off the current value of the uartx_BDH except for the SBR field */
        reg_temp = UART0_BDH & ~(UART0_BDH_SBR(0x1F));
   
        UART0_BDH = reg_temp |  UART0_BDH_SBR(((sbr_val & 0x1F00) >> 8));
        UART0_BDL = (uint8)(sbr_val & UART0_BDL_SBR_MASK);
        
        /* Enable receiver and transmitter */
        UART0_C2 |= (UART0_C2_TE_MASK
                    | UART0_C2_RE_MASK );
    }
    else
    {
   
{}
    }     
   
}


请各位大侠指正,谢谢!
我知道答案 目前已有18人回答
回复

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2015-6-4 09:32:10 | 显示全部楼层
楼主的波特率误差以及超出1.5%了,所以会出问题。
你可以参考KL26的UART代码:
uart.rar (2.65 KB, 下载次数: 20)
回复 支持 反对

使用道具 举报

该用户从未签到

11

主题

354

帖子

0

高级会员

Rank: 4

积分
763
最后登录
2018-6-7
发表于 2015-6-4 10:31:27 | 显示全部楼层
顺便来偷师一下
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

13

帖子

0

注册会员

Rank: 2

积分
61
最后登录
2015-6-19
 楼主| 发表于 2015-6-4 11:16:07 | 显示全部楼层
本帖最后由 gaow11 于 2015-6-4 12:38 编辑
FSL_TICS_ZJJ 发表于 2015-6-4 09:32
楼主的波特率误差以及超出1.5%了,所以会出问题。
你可以参考KL26的UART代码:


你好,我又设置UART时钟为48000000,FLL做时钟源,算下来波特率为115384,低于千分之二了,可是还是会出现数据传错问题。。
MCG_C1 |= MCG_C1_IRCLKEN_MASK;
MCG_C4 |= 0xa0;
uart0_init(UART0_BASE_PTR,48000,115200);
还有上面这样配置有问题吗,FLL这样配置有误差吗?

回复 支持 反对

使用道具 举报

  • TA的每日心情
    开心
    2018-7-23 21:04
  • 签到天数: 103 天

    连续签到: 1 天

    [LV.6]常住居民II

    228

    主题

    5379

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    16714
    最后登录
    1970-1-1
    发表于 2015-6-4 12:43:09 | 显示全部楼层
    学习了!
    回复

    使用道具 举报

    该用户从未签到

    145

    主题

    4926

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    9267
    最后登录
    1970-1-1
    发表于 2015-6-4 13:37:32 | 显示全部楼层
    gaow11 发表于 2015-6-4 11:16
    你好,我又设置UART时钟为48000000,FLL做时钟源,算下来波特率为115384,低于千分之二了,可是还是会出 ...

    你FLLCLK是48Mhz吗?
    你用的是内部时钟还是外部晶振多大?
    另外,如果用的是外部晶振,那么FRDIV是多大?
    首先你要保证你给uart初始化的时钟源频率是对的。
    另外,你的串口线是否有干扰?
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    3

    主题

    13

    帖子

    0

    注册会员

    Rank: 2

    积分
    61
    最后登录
    2015-6-19
     楼主| 发表于 2015-6-5 10:46:18 | 显示全部楼层
    本帖最后由 gaow11 于 2015-6-5 10:47 编辑
    FSL_TICS_ZJJ 发表于 2015-6-4 13:37
    你FLLCLK是48Mhz吗?
    你用的是内部时钟还是外部晶振多大?
    另外,如果用的是外部晶振,那么FRDIV是多大?


    用的内部晶振,慢速时钟32.768K的,MCG_C4 |= 0xa0;
    设置FLL48MHz
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    145

    主题

    4926

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    9267
    最后登录
    1970-1-1
    发表于 2015-6-5 10:49:21 | 显示全部楼层
    gaow11 发表于 2015-6-5 10:46
    用的内部晶振,慢速时钟32.768K的,MCG_C4 |= 0xa0;
    设置FLL48MHz

    你把代码工程给我,我这边测试看看是否正常。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    145

    主题

    4926

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    9267
    最后登录
    1970-1-1
    发表于 2015-6-5 10:57:52 | 显示全部楼层
    另外,楼主把你UART发出来的数据,给我贴一部分出来。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    3

    主题

    13

    帖子

    0

    注册会员

    Rank: 2

    积分
    61
    最后登录
    2015-6-19
     楼主| 发表于 2015-6-7 11:15:35 | 显示全部楼层
    FSL_TICS_ZJJ 发表于 2015-6-5 10:57
    另外,楼主把你UART发出来的数据,给我贴一部分出来。

    我用的是GPIOD中断,每1ms中断一次,接收六个SPI数据以后再通过串口发送其中四个,以0x61作为间隔符,测试串口的时候没有用SPI数据,只是发固定的测试数据,附上代码和接收到的串口数据

    klxx-sc-baremetal.zip

    4.96 MB, 下载次数: 23, 下载积分: 威望 1

    串口数据.zip

    2.49 KB, 下载次数: 5, 下载积分: 威望 1

    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-27 12:26 , Processed in 0.107887 second(s), 31 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表