完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
开发板引出了芯片主要的外设,因为需要调试CAN驱动,加了CAN收发器,此外,为了便于调试,通过TYPE-C接口和CH340E,设计了USB转串口,方便调试过程中打印调试信息。
回到正题,MWCT1013的时钟系统结构如下图所示: 由图可以看出,该芯片输入时钟源可选内部时钟,CLKIN以及外部晶振时钟。但官方手册里并不推荐输入CLKIN直接使用。输入时钟源经过锁相环后得到最高200MHz的sys_clk_2x,但这个时钟并不是系统时钟,该时钟供给SIM模块使用,系统时钟则是sys_clk_2x时钟的一半。除此之外,其他外设时钟由SIM模块分布如下。 本文重点介绍该芯片的锁相环配置,分别使用内部8MHz时钟以及外部8MHz晶振时钟配配置出200MHz的MSTR_2X时钟,最终CPU_CLK为100MHz。按照官方手册说明,共需要用到4个寄存器: 1.OCCS_CTRL,该寄存器用于使能锁相环及锁相环中断,设置输入时钟源和输出时钟源。其中LCKON需要开启,用于检测锁相环输出是否稳定,PLLPD置1时使能锁相环,PRECS用于选择输入时钟源,ZSRC用于选择输出时钟源,ZSRC直接决定了MSTR_2X的频率。 2.OCCS_DIVBY,该寄存器用于配置锁相环参数,主要配置PLLDB以及COD位段,其输出时钟的计算公式如下:sys_clk_2x = Fclk*(PLLDB+1)/2/COD,若Fclk为8M,PLLDB设为49,COD分频设置为1,则PLL输出时钟为200MHz。需要特别注意的是,在改变PLLDB前,ZSRC位必须为0,也即:输出时钟必须为MSTR_OSC。 3.OCCS_STAT,该寄存器用于查询各个时钟的状态。更改锁相环参数后,切换外部晶振时钟,以及切换系统时钟时需要查询该寄存器得知时钟是否稳定,时钟稳定才能继续下一步骤。 4.OCCS_OSCTL1,该寄存器用于设置时钟模式,主要用到COHL、CLK_MODE以及EXT_SEL三个位段,当然,如果选择外部时钟源,外部时钟稳定后,可以通过ROPD置1来关闭内部时钟源。 三个位共同决定了系统时钟生成的不同模式。 内部时钟配置步骤: 下图为手册中给出的配置内部时钟源和锁相环的步骤: 代码实现如下: void Clock_100M_Inner_CLK(void) { uint16_t temp; /*打开内部时钟*/ OCCS_OSCTL1 &= (~OCCS_OSCTL1_ROPD); /*禁用PLL中断,使能PLL,选择8M内部时钟作为时钟源*/ /*配置PLL前,时钟源必须先配置为MSTR_OSC*/ OCCS_CTRL = 0x0080; /*参考时钟丢失中断检测时间参数:推荐大于0b0010*/ /*2倍系统时钟=时钟源*(PLLDB+1)/2/COD,8M*50/2/1=200M*/ /*COD = 1,0b0000*/ /*PLLDB = 49,0x31*/ OCCS_DIVBY = 0x02031; /*等待PLL,LCK0稳定*/ do { temp = OCCS_STAT; }while((temp&OCCS_STAT_LCK0)!=0); /*等待PLL,LCK1稳定*/ do { temp = OCCS_STAT; }while((temp&OCCS_STAT_LCK1)!=0); /*锁相环稳定后,将2倍系统时钟切换到PLL*/ OCCS_CTRL = 0x0081; /*等待时钟切换完成*/ do { temp = OCCS_STAT; }while((temp&OCCS_STAT_ZSRCS)!=0x01); /* 配置完成,相关时钟状态如下: MSTR_2X:200M CPU_CLK:100M BUS_CLK:100M*/ } 外部时钟配置: 下图为手册中给出的配置外部晶振时钟源和锁相环的步骤: 代码实现如下: void Clock_100M_EX_CLK(void) { uint16_t temp; /*配置时钟输入引脚*/ GPIOC_PER |= GPIOC_PER_PE; SIM_GPSCL &= (~SIM_GPSCL_C0); /*配置晶体振荡电路模式*/ // OCCS_OSCTL1 &= (~OCCS_OSCTL1_COHL); OCCS_OSCTL1 |= OCCS_OSCTL1_COHL; OCCS_OSCTL1 &= (~OCCS_OSCTL1_CLK_MODE); OCCS_OSCTL1 &= (~OCCS_OSCTL1_EXT_SEL); /*打开晶振时钟*/ OCCS_OSCTL2 &= (~OCCS_OSCTL2_COPD); do { temp = OCCS_STAT; }while((temp&OCCS_STAT_OSC_OK)!=0); /*等待外部时钟稳定*/ /*切换时钟源*/ OCCS_CTRL |= 0x01<<2; for(temp = 0;temp<100;) { temp++; } /*等待时钟切换完成,见手册345页*/ /*关闭内部时钟*/ OCCS_OSCTL1 |= OCCS_OSCTL1_ROPD; OCCS_CTRL &= (~OCCS_CTRL_PLLPD); /*参考时钟丢失中断检测时间参数:推荐大于0b0010*/ /*2倍系统时钟=时钟源*(PLLDB+1)/2/COD*,8M*50/2/1=200M*/ /*COD = 1,0b0001*/ /*PLLDB = 49,0x31*/ OCCS_DIVBY = 0x02031; /*等待PLL,LCK0稳定*/ do { temp = OCCS_STAT; }while((temp&OCCS_STAT_LCK0)!=0); /*等待PLL,LCK1稳定*/ do { temp = OCCS_STAT; }while((temp&OCCS_STAT_LCK1)!=0); /*锁相环稳定后,将2倍系统时钟切换到PLL*/ OCCS_CTRL = 0x0085; /*等待时钟切换完成*/ do { temp = OCCS_STAT; }while((temp&OCCS_STAT_ZSRCS)!=0x01); /* 配置完成,相关时钟状态如下: MSTR_2X:200M CPU_CLK:100M BUS_CLK:100M*/ } 以上代码经过测试,无论内部时钟还是外部晶振均可正常使用,作者水平有限,如有错误不当之处,请指出。 |
|
|
|
只有小组成员才能发言,加入小组>>
3309 浏览 9 评论
2990 浏览 16 评论
3490 浏览 1 评论
9052 浏览 16 评论
4085 浏览 18 评论
1171浏览 3评论
602浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
594浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2332浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1894浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 04:10 , Processed in 1.673150 second(s), Total 78, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号