1 /******************************************************************************************************************************************
2 * 文件名称: system_SWM320.c
3 * 功能说明: SWM320单片机的时钟设置
4 * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
5 * 注意事项:
6 * 版本日期: V1.1.0      2017年10月25日
7 * 升级记录:
8 *
9 *
10 *******************************************************************************************************************************************
11 * @attention
12 *
13 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
14 * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
15 * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
16 * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
17 * -ECTION WITH THEIR PRODUCTS.
18 *
19 * COPYRIGHT 2012 Synwit Technology
20 *******************************************************************************************************************************************/
21 #include <stdint.h>
22 #include "SWM320.h"
23 
24 
25 /******************************************************************************************************************************************
26  * 系统时钟设定
27  *****************************************************************************************************************************************/
28 #define SYS_CLK_20MHz   0       //0 内部高频20MHz RC振荡器
29 #define SYS_CLK_40MHz   1       //1 内部高频40MHz RC振荡器
30 #define SYS_CLK_32KHz   2       //2 内部低频32KHz RC振荡器
31 #define SYS_CLK_XTAL    3       //3 外部晶体振荡器(2-30MHz)
32 #define SYS_CLK_PLL     4       //4 片内锁相环输出
33 
34 #define SYS_CLK   SYS_CLK_PLL
35 
36 
37 #define SYS_CLK_DIV_1   0
38 #define SYS_CLK_DIV_2   1
39 
40 #define SYS_CLK_DIV     SYS_CLK_DIV_1
41 
42 
43 #define __HSI       (20000000UL)        //高速内部时钟
44 #define __LSI       (   32000UL)        //低速内部时钟
45 #define __HSE       (20000000UL)        //高速外部时钟
46 
47 
48 /********************************** PLL 设定 **********************************************
49  * VCO输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV
50  * PLL输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV / OUTDIV = VCO输出频率 / OUTDIV
51  * 注意:VCO输出频率需要在 [600MHz, 1200MHz] 之间
52  *****************************************************************************************/
53 #define SYS_PLL_SRC     SYS_CLK_20MHz   //可取值SYS_CLK_20MHz、SYS_CLK_XTAL
54 
55 #define PLL_IN_DIV      5
56 
57 #define PLL_FB_DIV      60
58 
59 
60 #define PLL_OUT_DIV8    0
61 #define PLL_OUT_DIV4    1
62 #define PLL_OUT_DIV2    2
63 
64 #define PLL_OUT_DIV     PLL_OUT_DIV8
65 
66 
67 
68 uint32_t SystemCoreClock  = __HSI;                  //System Clock Frequency (Core Clock)
69 uint32_t CyclesPerUs      = (__HSI / 1000000);      //Cycles per micro second
70 
71 
72 /******************************************************************************************************************************************
73 * 函数名称:
74 * 功能说明: This function is used to update the variable SystemCoreClock and must be called whenever the core clock is changed
75 * 输    入:
76 * 输    出:
77 * 注意事项:
78 ******************************************************************************************************************************************/
SystemCoreClockUpdate(void)79 void SystemCoreClockUpdate(void)
80 {
81     if(SYS->CLKSEL & SYS_CLKSEL_SYS_Msk)            //SYS_CLK  <= HFCK
82     {
83         if(SYS->CLKSEL & SYS_CLKSEL_HFCK_Msk)           //HFCK <= XTAL
84         {
85             SystemCoreClock =  __HSE;
86         }
87         else                                            //HFCK <= HRC
88         {
89             if(SYS->HRCCR & SYS_HRCCR_DBL_Msk)              //HRC = 40MHz
90             {
91                 SystemCoreClock = __HSI*2;
92             }
93             else                                            //HRC = 20MHz
94             {
95                 SystemCoreClock = __HSI;
96             }
97         }
98     }
99     else                                            //SYS_CLK  <= LFCK
100     {
101         if(SYS->CLKSEL & SYS_CLKSEL_LFCK_Msk)           //LFCK <= PLL
102         {
103             if(SYS->PLLCR & SYS_PLLCR_INSEL_Msk)            //PLL_SRC <= HRC
104             {
105                 SystemCoreClock = __HSI;
106             }
107             else                                            //PLL_SRC <= XTAL
108             {
109                 SystemCoreClock = __HSE;
110             }
111 
112             SystemCoreClock = SystemCoreClock / PLL_IN_DIV * PLL_FB_DIV * 4 / (2 << (2 - PLL_OUT_DIV));
113         }
114         else                                            //LFCK <= LRC
115         {
116             SystemCoreClock = __LSI;
117         }
118     }
119 
120     if(SYS->CLKDIV & SYS_CLKDIV_SYS_Msk) SystemCoreClock /= 2;
121 
122     CyclesPerUs = SystemCoreClock / 1000000;
123 }
124 
125 /******************************************************************************************************************************************
126 * 函数名称:
127 * 功能说明: The necessary initializaiton of systerm
128 * 输    入:
129 * 输    出:
130 * 注意事项:
131 ******************************************************************************************************************************************/
SystemInit(void)132 void SystemInit(void)
133 {
134     SYS->CLKEN |= (1 << SYS_CLKEN_ANAC_Pos);
135 
136     Flash_Param_at_xMHz(120);
137 
138     switch(SYS_CLK)
139     {
140         case SYS_CLK_20MHz:         //0 内部高频20MHz RC振荡器
141             switchCLK_20MHz();
142             break;
143 
144         case SYS_CLK_40MHz:         //1 内部高频40MHz RC振荡器
145             switchCLK_40MHz();
146             break;
147 
148         case SYS_CLK_32KHz:         //2 内部低频32KHz RC振荡器
149             switchCLK_32KHz();
150             break;
151 
152         case SYS_CLK_XTAL:          //3 外部晶体振荡器(2-30MHz)
153             switchCLK_XTAL();
154             break;
155 
156         case SYS_CLK_PLL:           //4 片内锁相环输出
157             switchCLK_PLL();
158             break;
159     }
160 
161     SYS->CLKDIV &= ~SYS_CLKDIV_SYS_Msk;
162     SYS->CLKDIV |= (SYS_CLK_DIV << SYS_CLKDIV_SYS_Pos);
163 
164     SystemCoreClockUpdate();
165 
166     if(SystemCoreClock > 80000000)
167     {
168         Flash_Param_at_xMHz(120);
169     }
170     else if(SystemCoreClock > 40000000)
171     {
172         Flash_Param_at_xMHz(80);
173     }
174     else if(SystemCoreClock > 30000000)
175     {
176         Flash_Param_at_xMHz(40);
177     }
178     else
179     {
180         Flash_Param_at_xMHz(30);
181     }
182 }
183 
delay_3ms(void)184 static void delay_3ms(void)
185 {
186     uint32_t i;
187 
188     if(((SYS->CLKSEL & SYS_CLKSEL_SYS_Msk) == 0) &&
189        ((SYS->CLKSEL & SYS_CLKSEL_LFCK_Msk) == 0))  //32KHz
190     {
191         for(i = 0; i < 20; i++) __NOP();
192     }
193     else
194     {
195         for(i = 0; i < 20000; i++) __NOP();
196     }
197 }
198 
switchCLK_20MHz(void)199 void switchCLK_20MHz(void)
200 {
201     SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) |
202                  (0 << SYS_HRCCR_DBL_Pos);          //HRC = 20MHz
203 
204     delay_3ms();
205 
206     SYS->CLKSEL &= ~SYS_CLKSEL_HFCK_Msk;            //HFCK  <=  HRC
207     SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos);       //SYS_CLK  <= HFCK
208 }
209 
switchCLK_40MHz(void)210 void switchCLK_40MHz(void)
211 {
212     SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) |
213                  (1 << SYS_HRCCR_DBL_Pos);          //HRC = 40MHz
214 
215     delay_3ms();
216 
217     SYS->CLKSEL &= ~SYS_CLKSEL_HFCK_Msk;            //HFCK  <=  HRC
218     SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos);       //SYS_CLK  <= HFCK
219 }
220 
switchCLK_32KHz(void)221 void switchCLK_32KHz(void)
222 {
223     SYS->CLKEN |= (1 << SYS_CLKEN_RTCBKP_Pos);
224 
225     SYS->LRCCR &= ~(1 << SYS_LRCCR_OFF_Pos);
226 
227     delay_3ms();
228 
229     SYS->CLKSEL &= ~SYS_CLKSEL_LFCK_Msk;            //LFCK  <=  LRC
230     SYS->CLKSEL &= ~SYS_CLKSEL_SYS_Msk;             //SYS_CLK  <= LFCK
231 }
232 
switchCLK_XTAL(void)233 void switchCLK_XTAL(void)
234 {
235     SYS->XTALCR = (1 << SYS_XTALCR_EN_Pos);
236 
237     delay_3ms();
238     delay_3ms();
239 
240     SYS->CLKSEL |= (1 << SYS_CLKSEL_HFCK_Pos);      //HFCK  <=  XTAL
241     SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos);       //SYS_CLK  <= HFCK
242 }
243 
switchCLK_PLL(void)244 void switchCLK_PLL(void)
245 {
246     PLLInit();
247 
248     SYS->PLLCR |= (1 << SYS_PLLCR_OUTEN_Pos);
249 
250     SYS->CLKSEL |= (1 << SYS_CLKSEL_LFCK_Pos);      //LFCK  <=  PLL
251     SYS->CLKSEL &= ~SYS_CLKSEL_SYS_Msk;             //SYS_CLK  <= LFCK
252 }
253 
PLLInit(void)254 void PLLInit(void)
255 {
256     if(SYS_PLL_SRC == SYS_CLK_20MHz)
257     {
258         SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) |
259                      (0 << SYS_HRCCR_DBL_Pos);      //HRC = 20MHz
260 
261         delay_3ms();
262 
263         SYS->PLLCR |= (1 << SYS_PLLCR_INSEL_Pos);   //PLL_SRC <= HRC
264     }
265     else if(SYS_PLL_SRC == SYS_CLK_XTAL)
266     {
267         SYS->XTALCR = (1 << SYS_XTALCR_EN_Pos);
268 
269         delay_3ms();
270         delay_3ms();
271 
272         SYS->PLLCR &= ~(1 << SYS_PLLCR_INSEL_Pos);  //PLL_SRC <= XTAL
273     }
274 
275     SYS->PLLDIV &= ~(SYS_PLLDIV_INDIV_Msk |
276                      SYS_PLLDIV_FBDIV_Msk |
277                      SYS_PLLDIV_OUTDIV_Msk);
278     SYS->PLLDIV |= (PLL_IN_DIV << SYS_PLLDIV_INDIV_Pos) |
279                    (PLL_FB_DIV << SYS_PLLDIV_FBDIV_Pos) |
280                    (PLL_OUT_DIV<< SYS_PLLDIV_OUTDIV_Pos);
281 
282     SYS->PLLCR &= ~(1 << SYS_PLLCR_OFF_Pos);
283 
284     while(SYS->PLLLOCK == 0);       //等待PLL锁定
285 }
286