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)33void 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)100void 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)151void 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)209void 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)272void 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)330void 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)384void 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)438void 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)490void 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)542void 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)596void 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)617void 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)669void 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)723void 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)773void 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)830void 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)847void 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)865void 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)883void 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)900void 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)953void 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)1024void 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)1044void 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)1101void OSC_DeInit(void) 1102 { 1103 OSC->CR = OSC_CR_DEFAULT; 1104 } 1105 1106 1107 1108 1109 1110