1 /*************************************************************!
2  *     技术讨论:QQ群  123763203
3  *     官网    :www.navota.com
4  *
5  * @file       ics.c
6  * @brief      时钟模块(ICS)函数库
7  * @author     Navota
8  * @date       2017-1-1
9  ****************************************************************/
10 #include "common.h"
11 #include "ics.h"
12 
13 /* 复位后ICS和OSC模块寄存器的默认值 */
14 #define ICS_C1_DEFAULT  0x04
15 #define ICS_C2_DEFAULT  0x20
16 #define ICS_C3_DEFAULT  0x54
17 #define ICS_C4_DEFAULT  0x00
18 #define ICS_S_DEFAULT   0x50
19 #define OSC_CR_DEFAULT  0
20 
21 
22 /*****************************************************************************//*!
23    *
24    * @ 概要  ICS的工作模式由当前的FEI模式切换为FEE模式,对选中的时钟源做1分频
25    *         OSC模块的输出时钟选择振荡器时钟源
26    *
27    * @ 参数【输入】 pConfig  指向ICS配置结构体
28    *
29    * @ 无返回
30    *
31    * @ 成功/失败的标准 :无
32    *****************************************************************************/
FEI_to_FEE(ICS_ConfigType * pConfig)33 void FEI_to_FEE(ICS_ConfigType *pConfig)
34 {
35     /*
36      * 使能OSC模块
37      */
38     OSC_Init(&pConfig->oscConfig); /*OSC模块初始化 */
39 
40     /*
41      * 对外部参考时钟进行分频,可将外部时钟分频到31.25k~39.0625k之间
42      */
43 
44     ICS_SetClkDivider(pConfig->u32ClkFreq);
45 
46         /*将FLL的参考时钟选择为外部时钟*/
47     ICS->C1 =  ICS->C1 & ~ICS_C1_IREFS_MASK;
48 
49         /*等待FLL参考时钟变为外部时钟*/
50 
51 #if defined(IAR)
52     asm(
53         "nop \n"
54         "nop \n"
55     );
56 #elif defined(__MWERKS__)
57     asm{
58         nop
59         nop
60 };
61 #endif
62     while(ICS->S & ICS_S_IREFST_MASK);
63 
64         /* 等待FLL时钟成为ICS输出时钟源*/
65     while(!(ICS->S & ICS_S_LOCK_MASK));
66 
67     /*
68      *现在FLL输出时钟变时钟频率等于FLL参考时钟分频结果乘以FLL的倍频系数
69      * FLL的倍频系数请参考参考手册
70      */
71 #if defined(CPU_NV32)
72   /*对选中的ICS输出时钟源做1分频*/
73     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) == 1)
74     {
75         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
76     }
77 #else
78     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
79 #endif
80 
81     /*
82      * 完成对选中的时钟源做1分频,系统/总线时钟时频率为设置的目标频率
83      */
84     /*LOLS清0*/
85     ICS->S |= ICS_S_LOLS_MASK;
86 }
87 
88 /*****************************************************************************//*!
89    *
90    * @ 概要  ICS的工作模式由当前的FEI模式转变成FBI模式,对选中的ICS输出时钟源
91    *         进行2分频
92    *
93    * @ 参数  pConfig    指向ICS配置结构体.
94    *
95    * @ 无返回
96    *
97    * @ 成功/失败的标准 :无
98    * @ 参看  ICS_ConfigType
99    *****************************************************************************/
FEI_to_FBI(ICS_ConfigType * pConfig)100 void FEI_to_FBI(ICS_ConfigType *pConfig)
101 {
102 
103         /*ICS输出时钟源选择内部参考时钟*/
104     ICS->C1 = (ICS->C1 & ~(ICS_C1_CLKS_MASK)) | ICS_C1_CLKS(1);
105     ICS->C2 = ICS->C2 & ~(ICS_C2_LP_MASK);
106         /*等待内部时钟成为ICS输出时钟源*/
107 #if defined(IAR)
108     asm(
109         "nop \n"
110         "nop \n"
111     );
112 #elif defined(__MWERKS__)
113     asm{
114         nop
115         nop
116         };
117 #endif
118     while(((ICS->S & ICS_S_CLKST_MASK) >> ICS_S_CLKST_SHIFT) !=1);
119 
120     /*
121      * 现在内部参考时钟为ICS输出时钟源
122      */
123 #if defined(BUS_CLK_EQU_CORE_DIVIDE_BY_2)||defined(CPU_NV32)
124          /*对选中的ICS输出时钟源做2分频*/
125     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
126     {
127         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
128     }
129 
130 #else
131     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK));
132 #endif
133 
134      /*LOLS清零*/
135     ICS->S |= ICS_S_LOLS_MASK;
136 }
137 
138 /*****************************************************************************//*!
139    *
140    * @ 概要  ICS的工作模式由当前的FEI模式转换成FBE模式,对选中的ICS输出时钟源做2分频
141    *         OSC模块的输出时钟选择振荡器时钟源
142    *
143    * @ 参数  pConfig   指向ICS的配置结构体 .
144    *
145    * @ 无返回
146    *
147    * @ 成功/失败的标准 :无
148    * @ 参看  ICS_ConfigType
149    *****************************************************************************/
150 
FEI_to_FBE(ICS_ConfigType * pConfig)151 void FEI_to_FBE(ICS_ConfigType *pConfig)
152 {
153     OSC_Init(&pConfig->oscConfig); /*初始化OSC 模块 */
154 
155          /*设置FLL的参考时钟为外部时钟*/
156 
157     ICS->C1 =  ICS->C1 & ~(ICS_C1_IREFS_MASK);
158     ICS->C1 = (ICS->C1 & ~(ICS_C1_CLKS_MASK)) | ICS_C1_CLKS(2);
159     ICS->C2 = ICS->C2 & ~(ICS_C2_LP_MASK);
160 
161         /*等在参考时钟发生改变*/
162 #if defined(IAR)
163     asm(
164         "nop \n"
165         "nop \n"
166     );
167 #elif defined(__MWERKS__)
168     asm{
169         nop
170         nop
171         };
172 #endif
173 
174     while(((ICS->S & ICS_S_CLKST_MASK) >> ICS_S_CLKST_SHIFT) !=2);  /*外部时钟成为ICS时钟输出源*/
175         while(ICS->S & ICS_S_IREFST_MASK);  /*FLL参考时钟成为外部时钟*/
176 
177     /*
178      * 现在外部时钟成为ICS输出时钟源
179      */
180 #if defined(CPU_NV32)
181         /*对选中的ICS输出时钟源做2分频*/
182     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
183     {
184         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
185     }
186 #else
187     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
188 #endif
189     /*
190      * 现在ICS输出时钟频率为选中的输出时钟源的2分频
191      */
192         /* LOLS清零 */
193     ICS->S |= ICS_S_LOLS_MASK;
194 }
195 
196 
197 /*****************************************************************************//*!
198    *
199    * @ 概要  ICS的工作模式由当前的FEI模式转换成FBE模式,对选中的输出时钟源做2分频
200    *         OSC输出时钟选择EXTAL引脚的外部时钟源
201    *
202    * @ 参数 pConfig  指向配置结构体.
203    *
204    * @ 无返回
205    *
206    * @ 成功/失败的标准 :无
207    * @ 参看  ICS_ConfigType
208    *****************************************************************************/
FEI_to_FBE_OSC(ICS_ConfigType * pConfig)209 void FEI_to_FBE_OSC(ICS_ConfigType *pConfig)
210 {
211 
212     OSC_Init(&pConfig->oscConfig); /* 初始化OSC */
213 
214     /*
215      * 设置外部参考时钟的分频系数,将参考时钟的分频结果设定在FLL可以锁定的31.25k~39.0625k范围内,
216      */
217     ICS_SetClkDivider(pConfig->u32ClkFreq);
218 
219         /*改变参考时钟源,将FLL的参考时钟设置为而外部时钟*/
220         ICS->C1 =  ICS->C1 & ~(ICS_C1_IREFS_MASK);/*将FLL的参考时钟设置为而外部时钟*/
221     ICS->C1 = (ICS->C1 & ~(ICS_C1_CLKS_MASK)) | ICS_C1_CLKS(2);  /*输出时钟源选择外部时钟*/
222     ICS->C2 = ICS->C2 & ~(ICS_C2_LP_MASK);
223 
224         /* 等待参考时钟发生改变*/
225 
226 #if defined(IAR)
227     asm(
228         "nop \n"
229         "nop \n"
230     );
231 #elif defined(__MWERKS__)
232     asm{
233         nop
234         nop
235         };
236 #endif
237     while(((ICS->S & ICS_S_CLKST_MASK) >> ICS_S_CLKST_SHIFT) !=2);/*外部时钟成为ICS时钟输出时钟源*/
238         while(ICS->S & ICS_S_IREFST_MASK);   /*外部时钟成为FLL参考时钟*/
239 
240     /*
241      * 现在外部时钟成为FLL参考时钟和ICS输出时钟源
242      */
243 #if defined(CPU_NV32)
244              /*对选中的ICS输出时钟源做2分频*/
245     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
246     {
247         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
248     }
249 #else
250     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
251 #endif
252     /*
253      * 现在ICS的输出时钟频率,为外部参考时钟的2分频
254      */
255         /*LOLS 清零*/
256     ICS->S |= ICS_S_LOLS_MASK;
257 }
258 
259 /*****************************************************************************//*!
260    *
261    * @ 概要  ICS的工作模式由当前的FEI模式转换FEE模式,对选中的ICS输出时钟源做2分频
262    *         OSC输出时钟选择EXTAL引脚的外部时钟源
263    *
264    * @ 参数  pConfig    指向配置结构体
265    *
266    * @ 无返回
267    *
268    * @ 成功/失败的标准 :无
269    * @ 参看  ICS_ConfigType
270    *****************************************************************************/
271 
FEI_to_FEE_OSC(ICS_ConfigType * pConfig)272 void FEI_to_FEE_OSC(ICS_ConfigType *pConfig)
273 {
274 
275     OSC_Init(&pConfig->oscConfig); /* 初始化OSC */
276 
277     /*
278      * 设置外部参考时钟的分频系数,将参考时钟的分频结果设定在FLL可以锁定的31.25k~39.0625k范围内
279      */
280     ICS_SetClkDivider(pConfig->u32ClkFreq);
281 
282         /* 将FLL的参考时钟设置为外部时钟 */
283 
284     ICS->C1 =  ICS->C1 & ~(ICS_C1_IREFS_MASK);
285 
286         /*等待参考时钟变化*/
287 #if defined(IAR)
288     asm(
289         "nop \n"
290         "nop \n"
291     );
292 #elif defined(__MWERKS__)
293     asm{
294         nop
295         nop
296         };
297 #endif
298     while(ICS->S & ICS_S_IREFST_MASK); /*FLL参考时钟变为外部时钟*/
299 
300         /*等待FLL成为ICS输出时钟源 */
301     while(!(ICS->S & ICS_S_LOCK_MASK));
302 #if defined(CPU_NV32)
303        /*对选中的时钟源做2分频*/
304     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
305     {
306         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
307     }
308 #else
309     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
310 #endif
311     /*
312      * 现在ICS输出时钟频率,成为要设置的目标频率
313      */
314 
315      /* LOLS清零 */
316     ICS->S |= ICS_S_LOLS_MASK;
317 }
318 
319 /*****************************************************************************//*!
320    *
321    * @ 概要 将ICS的工作模式由当前的FEE模式转换成FEI模式.
322    *
323    * @ 参数  pConfig  指向配置结构体
324    *
325    * @ 无返回
326    *
327    * @ 成功/失败的标准 :无
328    * @ 参看  ICS_ConfigType
329    *****************************************************************************/
FEE_to_FEI(ICS_ConfigType * pConfig)330 void FEE_to_FEI(ICS_ConfigType *pConfig)
331 {
332        /*选择内部时钟作为FLL的参考时钟*/
333     ICS->C1 =  ICS->C1 | (ICS_C1_IREFS_MASK);
334 
335         /*等待参考时钟发生改变*/
336 #if defined(IAR)
337     asm(
338         "nop \n"
339         "nop \n"
340     );
341 #elif defined(__MWERKS__)
342     asm{
343         nop
344         nop
345         };
346 #endif
347     while(!(ICS->S & ICS_S_IREFST_MASK)); /*FLL参考时钟成为内部时钟*/
348 
349         /*FLL时钟成为ICS输出时钟源 */
350     while(!(ICS->S & ICS_S_LOCK_MASK));
351          /*LOLS清零*/
352     ICS->S |= ICS_S_LOLS_MASK;
353 
354     /*
355      * 现在FLL输出成为ICS输出时钟源
356      */
357 #if defined(CPU_NV32)
358         /*对选中的ICS输出时钟源做2分频*/
359     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
360     {
361         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
362     }
363 #else
364     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
365 #endif
366     /*
367      * 现在系统/总线时钟大约为 16MHz
368      */
369         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
370       OSC_Disable();            /* 禁用 OSC模块 */
371 }
372 
373 /*****************************************************************************//*!
374    *
375    * @ 概要 将ICS的工作模式由当前的FEE模式转换成FBI模式.
376    *
377    * @ 参数 pConfig    指向配置结构体
378    *
379    * @ 无返回
380    *
381    * @ 成功/失败的标准 :无
382    * @ 参看  ICS_ConfigType
383    *****************************************************************************/
FEE_to_FBI(ICS_ConfigType * pConfig)384 void FEE_to_FBI(ICS_ConfigType *pConfig)
385 {
386         /*LOLS清零*/
387     ICS->S |= ICS_S_LOLS_MASK;
388 
389   /* 选择内部时钟作为ICS输出时钟源 */
390     /* 选择内部时钟作为FLL参考时钟 */
391     /* LP = 0 在bypass模式FLL不会被禁止*/
392 
393     ICS->C1 =  ICS->C1 | (ICS_C1_IREFS_MASK);
394     ICS->C1 = (ICS->C1 & ~(ICS_C1_CLKS_MASK)) | ICS_C1_CLKS(1);
395     ICS->C2 = ICS->C2 & ~(ICS_C2_LP_MASK);
396 
397         /* 等待参考时钟发生改变 */
398 #if defined(IAR)
399     asm(
400         "nop \n"
401         "nop \n"
402     );
403 #elif defined(__MWERKS__)
404     asm{
405         nop
406         nop
407         };
408 #endif
409     while(!(ICS->S & ICS_S_IREFST_MASK));  /*FLL参考时钟成为内部时钟*/
410     while(((ICS->S & ICS_S_CLKST_MASK) >> ICS_S_CLKST_SHIFT) !=1);  /*内部时成为ICS输出时钟源*/
411 
412 #if defined(BUS_CLK_EQU_CORE_DIVIDE_BY_2)||defined(CPU_NV32)
413          /*对所选中的ICS输出时钟源做2分频*/
414     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
415     {
416         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
417     }
418 
419 #else
420     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK));
421 
422 #endif
423         OSC_Disable();
424 }
425 
426 /*****************************************************************************//*!
427    *
428    * @ 概要  将ICS的工作模式由当前的FEE模式转变成FBE模式
429    *
430    * @ 参数  pConfig  指向配置结构体
431    *
432    * @ 无返回
433    *
434    * @ 成功/失败的标准 :无
435    * @ 参看  ICS_ConfigType
436    *****************************************************************************/
437 
FEE_to_FBE(ICS_ConfigType * pConfig)438 void FEE_to_FBE(ICS_ConfigType *pConfig)
439 {
440         /*LOLS清零*/
441     ICS->S |= ICS_S_LOLS_MASK;
442 
443 
444         /* LP = 0 */
445         /*选择外部时钟作为ICS输出时钟源*/
446         /* LP = 0 在bypass模式FLL不会被禁止*/
447 
448     ICS->C1 = (ICS->C1 & ~(ICS_C1_CLKS_MASK)) | ICS_C1_CLKS(2);
449     ICS->C2 = ICS->C2 & ~(ICS_C2_LP_MASK);
450 
451         /*等待输出时钟源发生改变*/
452 #if defined(IAR)
453     asm(
454         "nop \n"
455         "nop \n"
456     );
457 #elif defined(__MWERKS__)
458     asm{
459         nop
460         nop
461         };
462 #endif
463     while(((ICS->S & ICS_S_CLKST_MASK) >> ICS_S_CLKST_SHIFT) !=2);
464 
465    /* 现在ICS输出时钟源选择外部时钟源
466      * 注释: 确保外部时钟频率在20MHz以内
467      */
468 #if defined(CPU_NV32)
469         /*对选择的ICS输出时钟源做2分频*/
470     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
471     {
472         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
473     }
474 #else
475     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
476 #endif
477 }
478 
479 /*****************************************************************************//*!
480    *
481    * @ 概要 将ICS的工作模式由当前的FBI模式转换成FBE模式
482    *
483    * @ 参数  pConfig   指向配置结构体.
484    *
485    * @ 无返回
486    *
487    * @ 成功/失败的标准 :无
488    * @ 参看  ICS_ConfigType
489    *****************************************************************************/
FBI_to_FBE(ICS_ConfigType * pConfig)490 void FBI_to_FBE(ICS_ConfigType *pConfig)
491 {
492     OSC_Init(&pConfig->oscConfig); /*初始化OSC*/
493 
494     /* 选择外部时钟做为FLL的参考时钟 */
495     /*选择外部时钟作为输出时钟源*/
496 
497        ICS->C1 =  ICS->C1 & ~(ICS_C1_IREFS_MASK);
498     ICS->C1 = (ICS->C1 & ~(ICS_C1_CLKS_MASK)) | ICS_C1_CLKS(2);
499 
500 
501     /* 等待输出时钟源发生改变 */
502 
503 #if defined(IAR)
504     asm(
505         "nop \n"
506         "nop \n"
507     );
508 #elif defined(__MWERKS__)
509     asm{
510         nop
511         nop
512         };
513 #endif
514     while(((ICS->S & ICS_S_CLKST_MASK) >> ICS_S_CLKST_SHIFT) !=2); /*外部时钟成为ICS输出时钟源*/
515     while((ICS->S & ICS_S_IREFST_MASK));/*外部时钟成为FLL的参考时钟*/
516 
517         /* 现在系统时钟源是外部参考时钟
518      * 注释:确保外部时钟源的频率在20MHz内
519      */
520 #if defined(CPU_NV32)
521          /*对选中的时钟源做2分频*/
522     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
523     {
524         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
525     }
526 #else
527     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
528 #endif
529 }
530 
531 /*****************************************************************************//**
532    *
533    * @ 概要 将ICS的工作模式由当前的FBI模式转换成FEE模式
534    *
535    * @ 参数  pConfig    指向配置结构体
536    *
537    * @ 无返回
538    *
539    * @ 成功/失败的标准 :无
540    * @ 参看  ICS_ConfigType
541    *****************************************************************************/
FBI_to_FEE(ICS_ConfigType * pConfig)542 void FBI_to_FEE(ICS_ConfigType *pConfig)
543 {
544     OSC_Init(&pConfig->oscConfig); /*初始化OSC*/
545 
546     /* 选择外部时钟作为FLL的参考时钟 */
547     /* 选择FLL输出作为做为ICS输出时钟源*/
548 
549     ICS->C1 =  ICS->C1 & ~(ICS_C1_IREFS_MASK);
550     ICS->C1 = (ICS->C1 & ~(ICS_C1_CLKS_MASK));
551 
552         /*等待时钟源改变*/
553 #if defined(IAR)
554     asm(
555         "nop \n"
556         "nop \n"
557     );
558 #elif defined(__MWERKS__)
559     asm{
560         nop
561         nop
562         };
563 #endif
564 
565     while((ICS->S & ICS_S_CLKST_MASK));   /*FLL时钟成为ICS输出时钟源*/
566     while((ICS->S & ICS_S_IREFST_MASK));  /*外部时钟成为FLL参考时钟*/
567 
568      /* 现在系统时钟源为外部时钟
569      * 注释: 确保外部时钟源的频率在20MHz内
570      */
571 #if defined(CPU_NV32)
572         /*对选中的时钟源做2分频*/
573     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
574     {
575         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
576     }
577 #else
578     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
579 #endif
580        /*LOLS清零*/
581     ICS->S |= ICS_S_LOLS_MASK;
582 }
583 
584 /*****************************************************************************//*!
585    *
586    * @ 概要 将ICS的工作模式由当前的FBI模式转换成FBIP模式
587    *
588    * @ 参数  pConfig   输出指向配置结构体
589    *
590    * @ 无返回
591    *
592    * @ 成功/失败的标准 :无
593    * @ 警告 必须运行在调试接口没有没有接线的状态下
594    * @ 参看  ICS_ConfigType
595    *****************************************************************************/
FBI_to_FBILP(ICS_ConfigType * pConfig)596 void FBI_to_FBILP(ICS_ConfigType *pConfig)
597 {
598     /*
599      * 假设外部晶振时8MHz或者4MHz
600      */
601     ICS->C2 |= ICS_C2_LP_MASK;  /*进入低功耗模式 */
602 }
603 
604 
605 
606 /*****************************************************************************//*!
607    *
608    * @ 概要 将ICS的工作模式由当前的FBI模式转变为FEI模式
609    *
610    * @ 参数 pConfig  指向配置结构体.
611    *
612    * @ 无返回
613    *
614    * @ 成功/失败的标准 :无
615    * @ 参看  ICS_ConfigType
616    *****************************************************************************/
FBI_to_FEI(ICS_ConfigType * pConfig)617 void FBI_to_FEI(ICS_ConfigType *pConfig)
618 {
619      /* 选择内部时钟为FLL的参考时钟 */
620     /*选择FLL输出作为ICS输出时钟源*/
621     ICS->C1 =  ICS->C1 | (ICS_C1_IREFS_MASK);
622     ICS->C1 = (ICS->C1 & ~(ICS_C1_CLKS_MASK));
623 
624         /*等待时钟源发生改变*/
625 
626 #if defined(IAR)
627     asm(
628         "nop \n"
629         "nop \n"
630     );
631 #elif defined(__MWERKS__)
632     asm{
633         nop
634         nop
635         };
636 #endif
637     while((ICS->S & ICS_S_CLKST_MASK));    /*FLL输出成为ICS输出时钟源*/
638     while(!(ICS->S & ICS_S_IREFST_MASK));  /*FLL的参考时钟选择为外部时钟*/
639 
640 
641     /*
642      * 现在ICS输出时钟源为FLL输出
643      */
644 #if defined(CPU_NV32)
645          /*对选中的时钟源做2分频*/
646     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
647     {
648         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
649     }
650 #else
651     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
652 #endif
653 
654         /*LOLS清零 */
655     ICS->S |= ICS_S_LOLS_MASK;
656 }
657 
658 /*****************************************************************************//*!
659    *
660    * @ 概要  将ICS的工作模式由当前的FBE模式转换成FBI模式
661    *
662    * @ 参数  pConfig   指向配置结构体
663    *
664    * @ 无返回
665    *
666    * @ 成功/失败的标准 :无
667    * @ 参看  ICS_ConfigType
668    *****************************************************************************/
FBE_to_FBI(ICS_ConfigType * pConfig)669 void FBE_to_FBI(ICS_ConfigType *pConfig)
670 {
671         /*选择内部时钟作为FLL的参考时钟*/
672     /*选择内部时钟作为ICS输出时钟源*/
673     ICS->C1 =  ICS->C1 | (ICS_C1_IREFS_MASK);
674     ICS->C1 = (ICS->C1 & ~(ICS_C1_CLKS_MASK)) | ICS_C1_CLKS(1);
675 
676         /*等待时钟源发生改变*/
677 #if defined(IAR)
678     asm(
679         "nop \n"
680         "nop \n"
681     );
682 #elif defined(__MWERKS__)
683     asm{
684         nop
685         nop
686         };
687 #endif
688     while(((ICS->S & ICS_S_CLKST_MASK) >> ICS_S_CLKST_SHIFT) != 1);/*内部时钟成为ICS输出时钟源*/
689     while(!(ICS->S & ICS_S_IREFST_MASK)); /*内部时钟成为FLL的参考时钟*/
690 
691     /*
692      * 现在ICS输出时钟源为内部时钟
693      */
694 
695 #if defined(CPU_NV32)
696         /*对选中的时钟源做2分频*/
697     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
698     {
699         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
700     }
701 #else
702     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
703 #endif
704 
705     /*
706      * 禁用OSC模块
707      */
708     OSC_Disable();
709 }
710 
711 
712 /*****************************************************************************//*!
713    *
714    * @ 概要 将ICS的工作模式由当前的FBE模式转换成FEE模式
715    *
716    * @ 参数 pConfig   指向配置结构体.
717    *
718    * @ 无返回
719    *
720    * @ 成功/失败的标准 :无
721    * @ 参看  ICS_ConfigType
722    *****************************************************************************/
FBE_to_FEE(ICS_ConfigType * pConfig)723 void FBE_to_FEE(ICS_ConfigType *pConfig)
724 {
725 
726         /*选择FLL输出作为输出时钟源*/
727     ICS->C1 = (ICS->C1 & ~(ICS_C1_CLKS_MASK));
728 
729         /*等待ICS输出时钟源发生改变*/
730 #if defined(IAR)
731     asm(
732         "nop \n"
733         "nop \n"
734     );
735 #elif defined(__MWERKS__)
736     asm{
737         nop
738         nop
739         };
740 #endif
741     while(ICS->S & ICS_S_CLKST_MASK);
742 
743 
744     /*
745     * 现在ICS输出时钟源为FLL输出
746      * 注释: 外部时钟频率 <= 20MHz
747      */
748 #if defined(CPU_NV32)
749          /*对选中的ICS输出时钟源做2分频*/
750     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
751     {
752         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
753     }
754 #else
755     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
756 #endif
757          /* LOLS清零 */
758     ICS->S |= ICS_S_LOLS_MASK;
759 }
760 
761 
762 /*****************************************************************************//*!
763    *
764    * @ 概要 将ICS的工作模式由当前的FBE模式转变成FEI模式
765    *
766    * @ 参数 pConfig    指向配置结构体
767    *
768    * @ 无返回
769    *
770    * @ 成功/失败的标准 :无
771    * @ 参看  ICS_ConfigType
772    *****************************************************************************/
FBE_to_FEI(ICS_ConfigType * pConfig)773 void FBE_to_FEI(ICS_ConfigType *pConfig)
774 {
775     /* 选择内部时钟作为FLL的参考时钟*/
776     /*选择FLL输出做为ICS输出时钟源*/
777 
778     ICS->C1 =  ICS->C1 | (ICS_C1_IREFS_MASK);
779     ICS->C1 = (ICS->C1 & ~(ICS_C1_CLKS_MASK));
780 
781         /*等待时钟源改变*/
782 #if defined(IAR)
783     asm(
784         "nop \n"
785         "nop \n"
786     );
787 #elif defined(__MWERKS__)
788     asm{
789         nop
790         nop
791         };
792 #endif
793     while((ICS->S & ICS_S_CLKST_MASK));   /*FLL输出成为ICS输出时钟源*/
794     while(!(ICS->S & ICS_S_IREFST_MASK)); /*内部时钟中成为FLL参考时钟*/
795 
796   /*
797    * 现在FLL输出成为ICS输出时钟源
798    */
799 
800 #if defined(CPU_NV32)
801 
802        /*对选中的时钟源做2分频*/
803     if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) != 1)
804     {
805         ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(1);
806     }
807 #else
808     ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
809 #endif
810          /*LOLS清零*/
811     ICS->S |= ICS_S_LOLS_MASK;
812 
813     /*
814      *禁用OSC模块
815      */
816     OSC_Disable();
817 }
818 
819 /*****************************************************************************//*!
820    *
821    * @ 概要 将ICS的工作模式由当前的FBE模式转变为FBELP模式
822    *
823    * @ 参数  pConfig   指向配置结构体.
824    *
825    * @ 无返回
826    *
827    * @ 成功/失败的标准 :无
828    * @ 参看  ICS_ConfigType
829    *****************************************************************************/
FBE_to_FBELP(ICS_ConfigType * pConfig)830 void FBE_to_FBELP(ICS_ConfigType *pConfig)
831 {
832     /* enter low power mode */
833         /*进入低功耗模式*/
834     ICS->C2 = ICS->C2 | (ICS_C2_LP_MASK);
835 }
836 /*****************************************************************************//*!
837    *
838    * @ 概要 将ICS的工作模式由当前的FBELP模式转换成FBE模式
839    *
840    * @ 参数  pConfig     指向配置结构体.
841    *
842    * @ 无返回
843    *
844    * @ 成功/失败的标准 :无
845    * @ 参看  ICS_ConfigType
846    *****************************************************************************/
FBELP_to_FBE(ICS_ConfigType * pConfig)847 void FBELP_to_FBE(ICS_ConfigType *pConfig)
848 {
849     /* enter low power mode */
850         /*禁用低功耗模式*/
851     ICS->C2 = ICS->C2 & ~(ICS_C2_LP_MASK);
852 }
853 
854 /*****************************************************************************//*!
855    *
856    * @ 概要 将ICS的工作模式由当前的FBILP转换到FBI模式
857    *
858    * @ 参数  pConfig  指向配置结构体.
859    *
860    * @ 无返回
861    *
862    * @ 成功/失败的标准 :无
863    * @ 参看  ICS_ConfigType
864    *****************************************************************************/
FBILP_to_FBI(ICS_ConfigType * pConfig)865 void FBILP_to_FBI(ICS_ConfigType *pConfig)
866 {
867     /* enter low power mode */
868         /*禁用低功耗模式*/
869     ICS->C2 = ICS->C2 & ~(ICS_C2_LP_MASK);
870 }
871 
872 /*****************************************************************************//*!
873    *
874    * @ 概要 调整内部内部时钟 (IRC).
875    *
876    * @ 参数  u16TrimValue   调整值
877    *
878    * @ 无返回
879    *
880    * @ 成功/失败的标准 :无
881    *****************************************************************************/
882 
ICS_Trim(uint16_t u16TrimValue)883 void ICS_Trim(uint16_t u16TrimValue)
884 {
885    ICS->C3 =  (uint8_t) u16TrimValue;  /*将调整值写入寄存器*/
886    ICS->C4 = (ICS->C4 & ~(ICS_C4_SCFTRIM_MASK)) | ((u16TrimValue>>8) & 0x01);
887    while(!(ICS->S & ICS_S_LOCK_MASK));
888 }
889 /*****************************************************************************//*!
890    *
891    * @ 概要 对外部参考时钟进行分频,使得分频结果在FLL可以锁定的31.25k~39.0625k内
892    *
893    * @ 参数 u32ClkFreqKHz    参考时钟频率.
894    *
895    * @ 无返回
896    *
897    * @ 成功/失败的标准 :无
898    *****************************************************************************/
899 
ICS_SetClkDivider(uint32_t u32ClkFreqKHz)900 void ICS_SetClkDivider(uint32_t u32ClkFreqKHz)
901 {
902 
903     switch(u32ClkFreqKHz)
904     {
905         case 8000L:
906         case 10000L:
907             /* 8MHz or 10MHz*/
908             ICS->C1 = (ICS->C1 & ~(ICS_C1_RDIV_MASK)) | ICS_C1_RDIV(3);
909                                                                          /*8MHz分频结果是 8000/256 = 31.25K */
910                                                                         /*10MHz分频结果是 8000/256 = 31.25K*/
911             break;
912         case 4000L:
913             /* 4MHz */
914             ICS->C1 = (ICS->C1 & ~(ICS_C1_RDIV_MASK)) | ICS_C1_RDIV(2);
915                                                                         /*4MHz分频结果是 4000/128 = 31.25K*/
916             break;
917         case 12000L:
918             /* 12MHz */
919             ICS->C1 = (ICS->C1 & ~(ICS_C1_RDIV_MASK)) | ICS_C1_RDIV(3);
920                                                                         /*12MHz分频结果是12000/512 = 23.43K*/
921             break;
922         case 16000L:
923             /* 16MHz */
924             ICS->C1 = (ICS->C1 & ~(ICS_C1_RDIV_MASK)) | ICS_C1_RDIV(4);
925                                                                         /* 16MHz分频结果是 16000/512 = 31.25K */
926             break;
927         case 20000L:
928             /* 20MHz */
929             ICS->C1 = (ICS->C1 & ~(ICS_C1_RDIV_MASK)) | ICS_C1_RDIV(4);
930                                                                         /*20MHz分频结果是 20000/512 = 39.0625K */
931             break;
932         case 32L:
933             /* 32KHz */
934             ICS->C1  &= ~(ICS_C1_RDIV_MASK);
935             break;
936         default:
937             break;
938     }
939 }
940 /*****************************************************************************//*!
941    *
942    * @ 概要 初始化ICS模块根据定义所需要的总线时钟频率.
943    *
944    * @ 参数 pConfig  指向配置结构体.
945    *
946    * @ 无返回
947    *
948    * @ 成功/失败的标准 :无
949    * @ 参看  ICS_ConfigType
950    *****************************************************************************/
951 
952 
ICS_Init(ICS_ConfigType * pConfig)953 void ICS_Init(ICS_ConfigType *pConfig)
954 {
955   if(pConfig->u8ClkMode == ICS_CLK_MODE_FEE)
956   {
957         pConfig->oscConfig.bIsCryst = 1;   /* OSC的输出选择选择振动器时钟源 */
958         pConfig->oscConfig.bWaitInit = 1;  /* 等待振荡器初始化化完成 */
959 
960       /*选择FEE模式,OSC输出选择振荡器时钟源*/
961         FEI_to_FEE(pConfig);
962   }
963   else if (pConfig->u8ClkMode == ICS_CLK_MODE_FEE_OSC)
964   {
965         pConfig->oscConfig.bIsCryst = 0;     /*OSC输出时钟选择EEXTAL引脚的外部时钟源*/
966 
967      /*选择FEE工作模式;OSC输出时钟选择EEXTAL引脚的外部时钟源*/
968         FEI_to_FEE_OSC(pConfig);
969   }
970   else if (pConfig->u8ClkMode == ICS_CLK_MODE_FBE_OSC)
971   {
972         pConfig->oscConfig.bIsCryst = 0;  /* is clock:OSC输出时钟选择EXTAL引脚的外部时钟源 */
973         /* 选择FBE工作模式;OSC输出时钟选择EXTAL引脚的外部时钟源*/
974         FEI_to_FBE_OSC(pConfig);
975   }
976     else if(pConfig->u8ClkMode == ICS_CLK_MODE_FBELP )
977     {
978     pConfig->oscConfig.bIsCryst = 1;        /* OSC的输出时钟选择选择振动器时钟源 */
979         pConfig->oscConfig.bWaitInit = 1;       /*等待振荡器初始化化完成 */
980 
981         /* 选择FBE模式,OSC的输出时钟选择选择振动器时钟源*/
982                     FEI_to_FBE(pConfig);    /*先选择PBE模式*/
983             FBE_to_FBELP(pConfig);   /*选择FBELP*/
984             ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
985     }
986         else if(pConfig->u8ClkMode == ICS_CLK_MODE_FBILP )
987     {
988 
989             /* OSC输出时钟选择EXTAL引脚的外部时钟源*/
990             pConfig->oscConfig.bIsCryst = 0;
991 
992             /* 选择FBE模式,OSC输出时钟选择EXTAL引脚的外部时钟源*/
993               FEI_to_FBI(pConfig);
994           FBI_to_FBILP(pConfig);
995           ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
996     }
997   else
998   {
999 
1000        /*ICS默认工作模式FEI模式*/
1001         #if defined(CPU_NV32)
1002         if(((ICS->C2 & ICS_C2_BDIV_MASK)>>5) == 1)
1003         {
1004             ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
1005         }
1006         #else
1007             ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(0);
1008         #endif
1009   }
1010 
1011 }
1012 /*****************************************************************************//*!
1013    *
1014    * @ 概要 对ICS模块各寄存器进行复位.
1015    *
1016    * @ 无参数
1017    *
1018    * @ 无返回
1019    *
1020    * @ 成功/失败的标准 :无
1021    * @ 参看  ICS_Init
1022    *****************************************************************************/
1023 
ICS_DeInit(void)1024 void ICS_DeInit(void)
1025 {
1026     ICS->C1 = ICS_C1_DEFAULT;
1027     ICS->C2 = ICS_C2_DEFAULT;
1028     ICS->C3 = ICS_C3_DEFAULT;
1029     ICS->C4 = ICS_C4_DEFAULT;
1030     while(ICS->S != ICS_S_DEFAULT)
1031         ;
1032 }
1033 
1034 /*****************************************************************************//*!
1035    *
1036    * @ 概要 通过设定的参数初始化XOSC
1037    *
1038    * @ 参数  pConfig   指向osc配置结构体
1039    *
1040    * @ 无返回
1041    *
1042    * @ 成功/失败的标准 :无
1043    *****************************************************************************/
OSC_Init(OSC_ConfigType * pConfig)1044 void OSC_Init(OSC_ConfigType *pConfig)
1045 {
1046     uint8   cr = 0;
1047     /*
1048      *
1049      */
1050     if(pConfig->bGain) /*高增益振荡器选择*/
1051     {
1052         /* high gain:选择高增益模式 */
1053         cr |= OSC_CR_HGO_MASK ;
1054     }
1055 
1056     if(pConfig->bRange)  /*频率范围的选择*/
1057     {
1058         cr |= OSC_CR_RANGE_MASK; /*选择高频范围 */
1059     }
1060 
1061     if(pConfig->bStopEnable) /*停止模式下的OSC使能*/
1062     {
1063         cr |= OSC_CR_OSCSTEN_MASK; /*OSC在停止模式下保持使能*/
1064     }
1065 
1066     if(pConfig->bIsCryst)     /*OSC输出选择*/
1067     {
1068         cr |= OSC_CR_OSCOS_MASK; /*选择振荡器时钟*/
1069     }
1070 
1071     if(pConfig->bEnable)  /*OSC使能*/
1072     {
1073         cr |= OSC_CR_OSCEN_MASK;
1074     }
1075 
1076     OSC->CR = cr;   /*数值写入控制寄存器*/
1077 
1078     if(pConfig->bWaitInit)
1079     {
1080 
1081         /*
1082      *等待初始化完成
1083          */
1084         while(!(OSC->CR & OSC_CR_OSCINIT_MASK));
1085 
1086     }
1087 }
1088 
1089 /*****************************************************************************//*!
1090    *
1091    * @ 概要 重置OSC模块,使其恢复到默认状态.
1092    *
1093    * @ 无输参数
1094    *
1095    * @ 无返回
1096    *
1097    * @ 成功/失败的标准 :无
1098    * @ 参看   ICS_Init
1099    *****************************************************************************/
1100 
OSC_DeInit(void)1101 void OSC_DeInit(void)
1102 {
1103     OSC->CR = OSC_CR_DEFAULT;
1104 }
1105 
1106 
1107 
1108 
1109 
1110