博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
GD32F450 200M时USB不稳定
阅读量:7042 次
发布时间:2019-06-28

本文共 2888 字,大约阅读时间需要 9 分钟。

使用GD32F450的demo修改usb驱动,发现120M和168M时正常,200M时很不稳定。怀疑USB时钟分频有问题,一查果然是,记录如下:

200M是库函数主时钟分频代码如下

static void system_clock_200m_25m_hxtal(void){    uint32_t timeout = 0U;    uint32_t stab_flag = 0U;        /* enable HXTAL */    RCU_CTL |= RCU_CTL_HXTALEN;    /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */    do{        timeout++;        stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);    }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));    /* if fail */    if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){        while(1){        }    }             RCU_APB1EN |= RCU_APB1EN_PMUEN;    PMU_CTL |= PMU_CTL_LDOVS;    /* HXTAL is stable */    /* AHB = SYSCLK */    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;    /* APB2 = AHB/2 */    RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;    /* APB1 = AHB/4 */    RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;    /* Configure the main PLL, PLL_M = 25, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */     RCU_PLL = (25U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) |                   (RCU_PLLSRC_HXTAL) | (9U << 24U));    /* enable PLL */    RCU_CTL |= RCU_CTL_PLLEN;    /* wait until PLL is stable */    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){    }        /* Enable the high-drive to extend the clock frequency to 200 Mhz */    PMU_CTL |= PMU_CTL_HDEN;    while(0U == (PMU_CS & PMU_CS_HDRF)){    }        /* select the high-drive mode */    PMU_CTL |= PMU_CTL_HDS;    while(0U == (PMU_CS & PMU_CS_HDSRF)){    }         /* select PLL as system clock */    RCU_CFG0 &= ~RCU_CFG0_SCS;    RCU_CFG0 |= RCU_CKSYSSRC_PLLP;    /* wait until PLL is selected as system clock */    while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){    }}

这里注意几个重要信息,PLL_M=25,PLL_N=400,PLL_Q=9 

 

再查看demo里的usb时钟配置代码,从代码里我们可以了解,USB时钟来源是PLLM_48M,而PLLM_48M是HXTAL倍频后经由PLLQ分频得到

rcu_pll48m_clock_config(RCU_PLL48MSRC_PLLQ);    rcu_ck48m_clock_config(RCU_CK48MSRC_PLL48M);    rcu_periph_clock_enable(RCU_USBFS);

 

对比数据手册里USB这块的时钟树我们计算下USB时钟

输入时钟25Mhz,USB时钟=25/PLL_M*PLL_N/PLL_Q=25/25*400/9=44.44444MHz,而我们知道USB需要48MHz的时钟才能稳定工作,所以这导致了USB工作的不稳定。

为什么120MHz和168MHz时不会有这个稳定呢?那是因为不同时钟主时钟分频函数不一样,在120MHz和168MHz时能分出48M的时钟给USB。

 

知道问题哪后,就好解决了,方法如下:

1、直接修改库函数里PLL的分频系数,这个方法新人不推荐

2、使用内部RCK_48M作为USB的时钟源,

rcu_ck48m_clock_config(RCU_CK48MSRC_IRC48M)rcu_osci_on(RCU_IRC48M)/* wait till RCU_IRC48M is ready */while(SUCCESS != rcu_osci_stab_wait(RCU_IRC48M)){}

3、修改PLLM_48M由PLLAI分频来

//使用PLLAI_Q作为PLL_SEL的输入    rcu_pll48m_clock_config(RCU_PLL48MSRC_PLLSAIP);    //使用PLL_SEL作为usb主频    rcu_ck48m_clock_config(RCU_CK48MSRC_PLL48M);    /* configure PLLSAI                PLLAI_N=192;PLL_P=192/4=48MHZ,PLL_Q=192/2=96MHZ,PLL_R=192/3=64MHZ       注意,此处的PLL_P用于后面的USB主时钟,要确保为48MHZ    */    if(ERROR == rcu_pllsai_config(192, 4, 2, 3))                {        while(1);    }        rcu_osci_on(RCU_PLLSAI_CK);        if(ERROR == rcu_osci_stab_wait(RCU_PLLSAI_CK))    {        while(1);    }

 

转载于:https://www.cnblogs.com/zwj412/p/10026393.html

你可能感兴趣的文章
Python Selenium Chrome Headless 爬取企查查数据
查看>>
Sublime Text 2 常用快捷键
查看>>
hadoop day 1
查看>>
剑指offer——面试题26:判断二叉树B是否为二叉树A的子结构
查看>>
HDU2024 C语言合法标识符
查看>>
STS中applicationContext.xml配置文件
查看>>
代码编写规范
查看>>
清除浮动总结
查看>>
【android-cocos2d-X iconv.h】在android下使用iconv
查看>>
转:Java中的StringTokenizer类的使用方法
查看>>
httpd实现基于用户的访问控制
查看>>
Verilog门级建模
查看>>
Java豆瓣电影爬虫——减少与数据库交互实现批量插入
查看>>
信息传递 计蒜客16863 NOIP模拟赛 概率DP
查看>>
C++Primer第5版学习笔记(二)
查看>>
java内存溢出分析
查看>>
c++学习笔记(新手学习笔记,如有错误请与作者联系)
查看>>
Bindservice调用服务流程
查看>>
python 数据类型
查看>>
spring mvc 的各种参数的绑定方式
查看>>