MWCT1013-时钟配置

       最近偶然需要调试MWCT1013的CAN驱动,但是这颗芯片的官方资料少得可怜,官网就只有IDE和芯片手册,官方不直接提供开发例程,个人很难拿到更多的开发资源。另一方面,淘宝和闲鱼都找不到对应的开发板,求人不如求己,于是自己动手画了一块。

            开发板引出了芯片主要的外设,因为需要调试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*/
}

 以上代码经过测试,无论内部时钟还是外部晶振均可正常使用,作者水平有限,如有错误不当之处,请指出。

本文是作者闲时业余记录,如由遗漏错误,请见谅,转载不用注明出处。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值