system_SWM320.c 8.2 KB

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