ics.c 28 KB

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