天天看點

MWCT1013-時鐘配置

       最近偶然需要調試MWCT1013的CAN驅動,但是這顆晶片的官方資料少得可憐,官網就隻有IDE和晶片手冊,官方不直接提供開發例程,個人很難拿到更多的開發資源。另一方面,淘寶和閑魚都找不到對應的開發闆,求人不如求己,于是自己動手畫了一塊。

MWCT1013-時鐘配置

            開發闆引出了晶片主要的外設,因為需要調試CAN驅動,加了CAN收發器,此外,為了便于調試,通過TYPE-C接口和CH340E,設計了USB轉序列槽,友善調試過程中列印調試資訊。

           回到正題,MWCT1013的時鐘系統結構如下圖所示:

MWCT1013-時鐘配置

           由圖可以看出,該晶片輸入時鐘源可選内部時鐘,CLKIN以及外部晶振時鐘。但官方手冊裡并不推薦輸入CLKIN直接使用。輸入時鐘源經過鎖相環後得到最高200MHz的sys_clk_2x,但這個時鐘并不是系統時鐘,該時鐘供給SIM子產品使用,系統時鐘則是sys_clk_2x時鐘的一半。除此之外,其他外設時鐘由SIM子產品分布如下。

MWCT1013-時鐘配置

           本文重點介紹該晶片的鎖相環配置,分别使用内部8MHz時鐘以及外部8MHz晶振時鐘配配置出200MHz的MSTR_2X時鐘,最終CPU_CLK為100MHz。按照官方手冊說明,共需要用到4個寄存器:

1.OCCS_CTRL,該寄存器用于使能鎖相環及鎖相環中斷,設定輸入時鐘源和輸出時鐘源。其中LCKON需要開啟,用于檢測鎖相環輸出是否穩定,PLLPD置1時使能鎖相環,PRECS用于選擇輸入時鐘源,ZSRC用于選擇輸出時鐘源,ZSRC直接決定了MSTR_2X的頻率。

MWCT1013-時鐘配置
MWCT1013-時鐘配置

 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。

MWCT1013-時鐘配置
MWCT1013-時鐘配置

3.OCCS_STAT,該寄存器用于查詢各個時鐘的狀态。更改鎖相環參數後,切換外部晶振時鐘,以及切換系統時鐘時需要查詢該寄存器得知時鐘是否穩定,時鐘穩定才能繼續下一步驟。

MWCT1013-時鐘配置

4.OCCS_OSCTL1,該寄存器用于設定時鐘模式,主要用到COHL、CLK_MODE以及EXT_SEL三個位段,當然,如果選擇外部時鐘源,外部時鐘穩定後,可以通過ROPD置1來關閉内部時鐘源。

三個位共同決定了系統時鐘生成的不同模式。

MWCT1013-時鐘配置
MWCT1013-時鐘配置
MWCT1013-時鐘配置
MWCT1013-時鐘配置

内部時鐘配置步驟:

    下圖為手冊中給出的配置内部時鐘源和鎖相環的步驟:

MWCT1013-時鐘配置

代碼實作如下:

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*/
}
           

外部時鐘配置:

  下圖為手冊中給出的配置外部晶振時鐘源和鎖相環的步驟:

MWCT1013-時鐘配置

代碼實作如下:

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*/
}
           

 以上代碼經過測試,無論内部時鐘還是外部晶振均可正常使用,作者水準有限,如有錯誤不當之處,請指出。

本文是作者閑時業餘記錄,如由遺漏錯誤,請見諒,轉載不用注明出處。。