1 /******************************************************************************************************************************************
2 * 文件名称: system_SWM341.c
3 * 功能说明: SWM341单片机的时钟设置
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 "SWM341.h"
23
24
25 /******************************************************************************************************************************************
26 * 系统时钟设定
27 *****************************************************************************************************************************************/
28 #define SYS_CLK_20MHz 0 //0 内部高频20MHz RC振荡器
29 #define SYS_CLK_2M5Hz 1 //1 内部高频2.5MHz RC振荡器
30 #define SYS_CLK_40MHz 2 //2 内部高频40MHz RC振荡器
31 #define SYS_CLK_5MHz 3 //3 内部高频 5MHz RC振荡器
32 #define SYS_CLK_XTAL 4 //4 外部晶体振荡器(4-32MHz)
33 #define SYS_CLK_XTAL_DIV8 5 //5 外部晶体振荡器(4-32MHz) 8分频
34 #define SYS_CLK_PLL 6 //6 锁相环输出
35 #define SYS_CLK_PLL_DIV8 7 //7 锁相环输出 8分频
36 #define SYS_CLK_32KHz 8 //8 内部低频32KHz RC 振荡器
37 #define SYS_CLK_XTAL_32K 9 //9 外部低频32KHz 晶体振荡器
38
39 #define SYS_CLK SYS_CLK_PLL
40
41
42 #define __HSI (20000000UL) //高速内部时钟
43 #define __LSI ( 32000UL) //低速内部时钟
44 #define __HSE (12000000UL) //高速外部时钟
45 #define __LSE ( 32768UL) //低速外部时钟
46
47
48 /********************************** PLL 设定 **********************************************
49 * VCO输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV
50 * PLL输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV / OUTDIV = VCO输出频率 / OUTDIV
51 * 注意:VCO输出频率需要在 [600MHz, 1400MHz] 之间
52 *****************************************************************************************/
53 #define SYS_PLL_SRC SYS_CLK_XTAL //可取值SYS_CLK_20MHz、SYS_CLK_XTAL
54
55 #define PLL_IN_DIV 3
56
57 #define PLL_FB_DIV 75
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 <= HRC
82 {
83 if(SYS->HRCCR & SYS_HRCCR_DBL_Msk) //HRC = 40MHz
84 {
85 SystemCoreClock = __HSI*2;
86 }
87 else //HRC = 20MHz
88 {
89 SystemCoreClock = __HSI;
90 }
91 }
92 else //SYS <= CLK
93 {
94 switch((SYS->CLKSEL & SYS_CLKSEL_CLK_Msk) >> SYS_CLKSEL_CLK_Pos)
95 {
96 case 0:
97 SystemCoreClock = __LSI;
98 break;
99
100 case 1:
101 if(SYS->PLLCR & SYS_PLLCR_INSEL_Msk) //PLL_IN <= HRC
102 {
103 SystemCoreClock = __HSI;
104 }
105 else //PLL_IN <= XTAL
106 {
107 SystemCoreClock = __HSE;
108 }
109
110 SystemCoreClock = SystemCoreClock / PLL_IN_DIV * PLL_FB_DIV * 4 / (2 << (2 - PLL_OUT_DIV));
111 break;
112
113 case 2:
114 SystemCoreClock = __LSE;
115 break;
116
117 case 3:
118 SystemCoreClock = __HSE;
119 break;
120
121 case 4:
122 SystemCoreClock = __HSI;
123 if(SYS->HRCCR & SYS_HRCCR_DBL_Msk) SystemCoreClock *= 2;
124 break;
125 }
126
127 if(SYS->CLKSEL & SYS_CLKSEL_CLK_DIVx_Msk) SystemCoreClock /= 8;
128 }
129
130 CyclesPerUs = SystemCoreClock / 1000000;
131 }
132
133 /******************************************************************************************************************************************
134 * 函数名称:
135 * 功能说明: The necessary initializaiton of systerm
136 * 输 入:
137 * 输 出:
138 * 注意事项:
139 ******************************************************************************************************************************************/
SystemInit(void)140 void SystemInit(void)
141 {
142 SYS->CLKEN0 |= (1 << SYS_CLKEN0_ANAC_Pos);
143
144 Flash_Param_at_xMHz(150);
145
146 switch(SYS_CLK)
147 {
148 case SYS_CLK_20MHz:
149 switchTo20MHz();
150 break;
151
152 case SYS_CLK_2M5Hz:
153 switchTo2M5Hz();
154 break;
155
156 case SYS_CLK_40MHz:
157 switchTo40MHz();
158 break;
159
160 case SYS_CLK_5MHz:
161 switchTo5MHz();
162 break;
163
164 case SYS_CLK_XTAL:
165 switchToXTAL(0);
166 break;
167
168 case SYS_CLK_XTAL_DIV8:
169 switchToXTAL(1);
170 break;
171
172 case SYS_CLK_PLL:
173 switchToPLL(0);
174 break;
175
176 case SYS_CLK_PLL_DIV8:
177 switchToPLL(1);
178 break;
179
180 case SYS_CLK_32KHz:
181 switchTo32KHz();
182 break;
183
184 case SYS_CLK_XTAL_32K:
185 switchToXTAL_32K();
186 break;
187 }
188
189 SystemCoreClockUpdate();
190
191 if(SystemCoreClock > 120000000)
192 {
193 Flash_Param_at_xMHz(150);
194 }
195 else if(SystemCoreClock > 80000000)
196 {
197 Flash_Param_at_xMHz(120);
198 }
199 else if(SystemCoreClock > 40000000)
200 {
201 Flash_Param_at_xMHz(80);
202 }
203 else if(SystemCoreClock > 30000000)
204 {
205 Flash_Param_at_xMHz(40);
206 }
207 else
208 {
209 Flash_Param_at_xMHz(30);
210 }
211
212 PORTM->PULLD &= ~(1 << PIN1);
213 PORTM->PULLU &= ~((1 << PIN2) | (1 << PIN3));
214
215 SYS->USBPHYCR &= ~SYS_USBPHYCR_OPMODE_Msk;
216 SYS->USBPHYCR |= (1 << SYS_USBPHYCR_OPMODE_Pos); //Non-Driving, DP Pull-Up disable
217 }
218
219
FPU_Enable(void)220 void FPU_Enable(void)
221 {
222 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
223 SCB->CPACR |= (0xF << 20);
224 #endif
225 }
226
227
delay_3ms(void)228 static void delay_3ms(void)
229 {
230 uint32_t i;
231
232 if(((SYS->CLKSEL & SYS_CLKSEL_SYS_Msk) == 0) &&
233 ((((SYS->CLKSEL & SYS_CLKSEL_CLK_Msk) >> SYS_CLKSEL_CLK_Pos) == 0) || //LSI 32KHz
234 (((SYS->CLKSEL & SYS_CLKSEL_CLK_Msk) >> SYS_CLKSEL_CLK_Pos) == 2))) //LSE 32KHz
235 {
236 for(i = 0; i < 20; i++) __NOP();
237 }
238 else
239 {
240 for(i = 0; i < 20000; i++) __NOP();
241 }
242 }
243
244
switchTo20MHz(void)245 void switchTo20MHz(void)
246 {
247 SYS->HRCCR = (1 << SYS_HRCCR_ON_Pos) |
248 (0 << SYS_HRCCR_DBL_Pos); //HRC = 20Hz
249
250 delay_3ms();
251
252 SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS <= HRC
253 }
254
switchTo2M5Hz(void)255 void switchTo2M5Hz(void)
256 {
257 switchTo20MHz();
258
259 SYS->CLKDIVx_ON = 1;
260
261 SYS->CLKSEL &= ~SYS_CLKSEL_CLK_Msk;
262 SYS->CLKSEL |= (4 << SYS_CLKSEL_CLK_Pos); //CLK <= HRC
263
264 SYS->CLKSEL |= (1 << SYS_CLKSEL_CLK_DIVx_Pos);
265
266 delay_3ms();
267
268 SYS->CLKSEL &=~(1 << SYS_CLKSEL_SYS_Pos); //SYS <= HRC/8
269 }
270
switchTo40MHz(void)271 void switchTo40MHz(void)
272 {
273 SYS->HRCCR = (1 << SYS_HRCCR_ON_Pos) |
274 (1 << SYS_HRCCR_DBL_Pos); //HRC = 40MHz
275
276 delay_3ms();
277
278 SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS <= HRC
279 }
280
switchTo5MHz(void)281 void switchTo5MHz(void)
282 {
283 switchTo40MHz();
284
285 SYS->CLKDIVx_ON = 1;
286
287 SYS->CLKSEL &= ~SYS_CLKSEL_CLK_Msk;
288 SYS->CLKSEL |= (4 << SYS_CLKSEL_CLK_Pos); //CLK <= HRC
289
290 SYS->CLKSEL |= (1 << SYS_CLKSEL_CLK_DIVx_Pos);
291
292 delay_3ms();
293
294 SYS->CLKSEL &=~(1 << SYS_CLKSEL_SYS_Pos); //SYS <= HRC/8
295 }
296
switchToXTAL(uint32_t div8)297 void switchToXTAL(uint32_t div8)
298 {
299 switchTo20MHz();
300
301 PORT_Init(PORTA, PIN3, PORTA_PIN3_XTAL_IN, 0);
302 PORT_Init(PORTA, PIN4, PORTA_PIN4_XTAL_OUT, 0);
303 SYS->XTALCR |= (1 << SYS_XTALCR_ON_Pos) | (15 << SYS_XTALCR_DRV_Pos) | (1 << SYS_XTALCR_DET_Pos);
304
305 delay_3ms();
306 delay_3ms();
307
308 SYS->CLKDIVx_ON = 1;
309
310 SYS->CLKSEL &= ~SYS_CLKSEL_CLK_Msk;
311 SYS->CLKSEL |= (3 << SYS_CLKSEL_CLK_Pos); //CLK <= XTAL
312
313 if(div8) SYS->CLKSEL |= (1 << SYS_CLKSEL_CLK_DIVx_Pos);
314 else SYS->CLKSEL &=~(1 << SYS_CLKSEL_CLK_DIVx_Pos);
315
316 SYS->CLKSEL &=~(1 << SYS_CLKSEL_SYS_Pos); //SYS <= XTAL
317 }
318
switchToPLL(uint32_t div8)319 void switchToPLL(uint32_t div8)
320 {
321 switchTo20MHz();
322
323 PLLInit();
324
325 SYS->CLKDIVx_ON = 1;
326
327 SYS->CLKSEL &= ~SYS_CLKSEL_CLK_Msk;
328 SYS->CLKSEL |= (1 << SYS_CLKSEL_CLK_Pos); //CLK <= PLL
329
330 if(div8) SYS->CLKSEL |= (1 << SYS_CLKSEL_CLK_DIVx_Pos);
331 else SYS->CLKSEL &=~(1 << SYS_CLKSEL_CLK_DIVx_Pos);
332
333 SYS->CLKSEL &=~(1 << SYS_CLKSEL_SYS_Pos); //SYS <= PLL
334 }
335
switchTo32KHz(void)336 void switchTo32KHz(void)
337 {
338 switchTo20MHz();
339
340 SYS->LRCCR = (1 << SYS_LRCCR_ON_Pos);
341
342 SYS->CLKDIVx_ON = 1;
343
344 SYS->CLKSEL &= ~SYS_CLKSEL_CLK_Msk;
345 SYS->CLKSEL |= (0 << SYS_CLKSEL_CLK_Pos); //CLK <= LRC
346
347 SYS->CLKSEL &=~(1 << SYS_CLKSEL_CLK_DIVx_Pos);
348
349 delay_3ms();
350
351 SYS->CLKSEL &=~(1 << SYS_CLKSEL_SYS_Pos); //SYS <= LRC
352 }
353
switchToXTAL_32K(void)354 void switchToXTAL_32K(void)
355 {
356 uint32_t i;
357
358 switchTo20MHz();
359
360 SYS->XTALCR |= (1 << SYS_XTALCR_32KON_Pos) | (7 << SYS_XTALCR_32KDRV_Pos) | (1 << SYS_XTALCR_32KDET_Pos);
361 for(i = 0; i < 1000; i++) __NOP();
362
363 SYS->CLKDIVx_ON = 1;
364
365 SYS->CLKSEL &= ~SYS_CLKSEL_CLK_Msk;
366 SYS->CLKSEL |= (2 << SYS_CLKSEL_CLK_Pos); //CLK <= XTAL_32K
367
368 SYS->CLKSEL &=~(1 << SYS_CLKSEL_CLK_DIVx_Pos);
369
370 delay_3ms();
371
372 SYS->CLKSEL &=~(1 << SYS_CLKSEL_SYS_Pos); //SYS <= XTAL_32K
373 }
374
PLLInit(void)375 void PLLInit(void)
376 {
377 if(SYS_PLL_SRC == SYS_CLK_20MHz)
378 {
379 SYS->HRCCR = (1 << SYS_HRCCR_ON_Pos) |
380 (0 << SYS_HRCCR_DBL_Pos); //HRC = 20Hz
381
382 delay_3ms();
383
384 SYS->PLLCR |= (1 << SYS_PLLCR_INSEL_Pos); //PLL_SRC <= HRC
385 }
386 else if(SYS_PLL_SRC == SYS_CLK_XTAL)
387 {
388 PORT_Init(PORTA, PIN3, PORTA_PIN3_XTAL_IN, 0);
389 PORT_Init(PORTA, PIN4, PORTA_PIN4_XTAL_OUT, 0);
390 SYS->XTALCR |= (1 << SYS_XTALCR_ON_Pos) | (15 << SYS_XTALCR_DRV_Pos) | (1 << SYS_XTALCR_DET_Pos);
391
392 delay_3ms();
393 delay_3ms();
394
395 SYS->PLLCR &= ~(1 << SYS_PLLCR_INSEL_Pos); //PLL_SRC <= XTAL
396 }
397
398 SYS->PLLDIV &= ~(SYS_PLLDIV_INDIV_Msk |
399 SYS_PLLDIV_FBDIV_Msk |
400 SYS_PLLDIV_OUTDIV_Msk);
401 SYS->PLLDIV |= (PLL_IN_DIV << SYS_PLLDIV_INDIV_Pos) |
402 (PLL_FB_DIV << SYS_PLLDIV_FBDIV_Pos) |
403 (PLL_OUT_DIV<< SYS_PLLDIV_OUTDIV_Pos);
404
405 SYS->PLLCR &= ~(1 << SYS_PLLCR_OFF_Pos);
406
407 while(SYS->PLLLOCK == 0); //等待PLL锁定
408
409 SYS->PLLCR |= (1 << SYS_PLLCR_OUTEN_Pos);
410 }
411