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 * 系统时钟设定 27 *****************************************************************************************************************************************/ 28 #define SYS_CLK_20MHz 0 //0 内部高频20MHz RC振荡器 29 #define SYS_CLK_40MHz 1 //1 内部高频40MHz RC振荡器 30 #define SYS_CLK_32KHz 2 //2 内部低频32KHz RC振荡器 31 #define SYS_CLK_XTAL 3 //3 外部晶体振荡器(2-30MHz) 32 #define SYS_CLK_PLL 4 //4 片内锁相环输出 33 34 #define SYS_CLK SYS_CLK_PLL 35 36 37 #define SYS_CLK_DIV_1 0 38 #define SYS_CLK_DIV_2 1 39 40 #define SYS_CLK_DIV SYS_CLK_DIV_1 41 42 43 #define __HSI (20000000UL) //高速内部时钟 44 #define __LSI ( 32000UL) //低速内部时钟 45 #define __HSE (20000000UL) //高速外部时钟 46 47 48 /********************************** PLL 设定 ********************************************** 49 * VCO输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV 50 * PLL输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV / OUTDIV = VCO输出频率 / OUTDIV 51 * 注意:VCO输出频率需要在 [600MHz, 1200MHz] 之间 52 *****************************************************************************************/ 53 #define SYS_PLL_SRC SYS_CLK_20MHz //可取值SYS_CLK_20MHz、SYS_CLK_XTAL 54 55 #define PLL_IN_DIV 5 56 57 #define PLL_FB_DIV 60 58 59 60 #define PLL_OUT_DIV8 0 61 #define PLL_OUT_DIV4 1 62 #define PLL_OUT_DIV2 2 63 64 #define PLL_OUT_DIV PLL_OUT_DIV8 65 66 67 68 uint32_t SystemCoreClock = __HSI; //System Clock Frequency (Core Clock) 69 uint32_t CyclesPerUs = (__HSI / 1000000); //Cycles per micro second 70 71 72 /****************************************************************************************************************************************** 73 * 函数名称: 74 * 功能说明: This function is used to update the variable SystemCoreClock and must be called whenever the core clock is changed 75 * 输 入: 76 * 输 出: 77 * 注意事项: 78 ******************************************************************************************************************************************/ SystemCoreClockUpdate(void)79void SystemCoreClockUpdate(void) 80 { 81 if(SYS->CLKSEL & SYS_CLKSEL_SYS_Msk) //SYS_CLK <= HFCK 82 { 83 if(SYS->CLKSEL & SYS_CLKSEL_HFCK_Msk) //HFCK <= XTAL 84 { 85 SystemCoreClock = __HSE; 86 } 87 else //HFCK <= HRC 88 { 89 if(SYS->HRCCR & SYS_HRCCR_DBL_Msk) //HRC = 40MHz 90 { 91 SystemCoreClock = __HSI*2; 92 } 93 else //HRC = 20MHz 94 { 95 SystemCoreClock = __HSI; 96 } 97 } 98 } 99 else //SYS_CLK <= LFCK 100 { 101 if(SYS->CLKSEL & SYS_CLKSEL_LFCK_Msk) //LFCK <= PLL 102 { 103 if(SYS->PLLCR & SYS_PLLCR_INSEL_Msk) //PLL_SRC <= HRC 104 { 105 SystemCoreClock = __HSI; 106 } 107 else //PLL_SRC <= XTAL 108 { 109 SystemCoreClock = __HSE; 110 } 111 112 SystemCoreClock = SystemCoreClock / PLL_IN_DIV * PLL_FB_DIV * 4 / (2 << (2 - PLL_OUT_DIV)); 113 } 114 else //LFCK <= LRC 115 { 116 SystemCoreClock = __LSI; 117 } 118 } 119 120 if(SYS->CLKDIV & SYS_CLKDIV_SYS_Msk) SystemCoreClock /= 2; 121 122 CyclesPerUs = SystemCoreClock / 1000000; 123 } 124 125 /****************************************************************************************************************************************** 126 * 函数名称: 127 * 功能说明: The necessary initializaiton of systerm 128 * 输 入: 129 * 输 出: 130 * 注意事项: 131 ******************************************************************************************************************************************/ SystemInit(void)132void SystemInit(void) 133 { 134 SYS->CLKEN |= (1 << SYS_CLKEN_ANAC_Pos); 135 136 Flash_Param_at_xMHz(120); 137 138 switch(SYS_CLK) 139 { 140 case SYS_CLK_20MHz: //0 内部高频20MHz RC振荡器 141 switchCLK_20MHz(); 142 break; 143 144 case SYS_CLK_40MHz: //1 内部高频40MHz RC振荡器 145 switchCLK_40MHz(); 146 break; 147 148 case SYS_CLK_32KHz: //2 内部低频32KHz RC振荡器 149 switchCLK_32KHz(); 150 break; 151 152 case SYS_CLK_XTAL: //3 外部晶体振荡器(2-30MHz) 153 switchCLK_XTAL(); 154 break; 155 156 case SYS_CLK_PLL: //4 片内锁相环输出 157 switchCLK_PLL(); 158 break; 159 } 160 161 SYS->CLKDIV &= ~SYS_CLKDIV_SYS_Msk; 162 SYS->CLKDIV |= (SYS_CLK_DIV << SYS_CLKDIV_SYS_Pos); 163 164 SystemCoreClockUpdate(); 165 166 if(SystemCoreClock > 80000000) 167 { 168 Flash_Param_at_xMHz(120); 169 } 170 else if(SystemCoreClock > 40000000) 171 { 172 Flash_Param_at_xMHz(80); 173 } 174 else if(SystemCoreClock > 30000000) 175 { 176 Flash_Param_at_xMHz(40); 177 } 178 else 179 { 180 Flash_Param_at_xMHz(30); 181 } 182 } 183 delay_3ms(void)184static void delay_3ms(void) 185 { 186 uint32_t i; 187 188 if(((SYS->CLKSEL & SYS_CLKSEL_SYS_Msk) == 0) && 189 ((SYS->CLKSEL & SYS_CLKSEL_LFCK_Msk) == 0)) //32KHz 190 { 191 for(i = 0; i < 20; i++) __NOP(); 192 } 193 else 194 { 195 for(i = 0; i < 20000; i++) __NOP(); 196 } 197 } 198 switchCLK_20MHz(void)199void switchCLK_20MHz(void) 200 { 201 SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | 202 (0 << SYS_HRCCR_DBL_Pos); //HRC = 20MHz 203 204 delay_3ms(); 205 206 SYS->CLKSEL &= ~SYS_CLKSEL_HFCK_Msk; //HFCK <= HRC 207 SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK 208 } 209 switchCLK_40MHz(void)210void switchCLK_40MHz(void) 211 { 212 SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | 213 (1 << SYS_HRCCR_DBL_Pos); //HRC = 40MHz 214 215 delay_3ms(); 216 217 SYS->CLKSEL &= ~SYS_CLKSEL_HFCK_Msk; //HFCK <= HRC 218 SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK 219 } 220 switchCLK_32KHz(void)221void switchCLK_32KHz(void) 222 { 223 SYS->CLKEN |= (1 << SYS_CLKEN_RTCBKP_Pos); 224 225 SYS->LRCCR &= ~(1 << SYS_LRCCR_OFF_Pos); 226 227 delay_3ms(); 228 229 SYS->CLKSEL &= ~SYS_CLKSEL_LFCK_Msk; //LFCK <= LRC 230 SYS->CLKSEL &= ~SYS_CLKSEL_SYS_Msk; //SYS_CLK <= LFCK 231 } 232 switchCLK_XTAL(void)233void switchCLK_XTAL(void) 234 { 235 SYS->XTALCR = (1 << SYS_XTALCR_EN_Pos); 236 237 delay_3ms(); 238 delay_3ms(); 239 240 SYS->CLKSEL |= (1 << SYS_CLKSEL_HFCK_Pos); //HFCK <= XTAL 241 SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK 242 } 243 switchCLK_PLL(void)244void switchCLK_PLL(void) 245 { 246 PLLInit(); 247 248 SYS->PLLCR |= (1 << SYS_PLLCR_OUTEN_Pos); 249 250 SYS->CLKSEL |= (1 << SYS_CLKSEL_LFCK_Pos); //LFCK <= PLL 251 SYS->CLKSEL &= ~SYS_CLKSEL_SYS_Msk; //SYS_CLK <= LFCK 252 } 253 PLLInit(void)254void PLLInit(void) 255 { 256 if(SYS_PLL_SRC == SYS_CLK_20MHz) 257 { 258 SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | 259 (0 << SYS_HRCCR_DBL_Pos); //HRC = 20MHz 260 261 delay_3ms(); 262 263 SYS->PLLCR |= (1 << SYS_PLLCR_INSEL_Pos); //PLL_SRC <= HRC 264 } 265 else if(SYS_PLL_SRC == SYS_CLK_XTAL) 266 { 267 SYS->XTALCR = (1 << SYS_XTALCR_EN_Pos); 268 269 delay_3ms(); 270 delay_3ms(); 271 272 SYS->PLLCR &= ~(1 << SYS_PLLCR_INSEL_Pos); //PLL_SRC <= XTAL 273 } 274 275 SYS->PLLDIV &= ~(SYS_PLLDIV_INDIV_Msk | 276 SYS_PLLDIV_FBDIV_Msk | 277 SYS_PLLDIV_OUTDIV_Msk); 278 SYS->PLLDIV |= (PLL_IN_DIV << SYS_PLLDIV_INDIV_Pos) | 279 (PLL_FB_DIV << SYS_PLLDIV_FBDIV_Pos) | 280 (PLL_OUT_DIV<< SYS_PLLDIV_OUTDIV_Pos); 281 282 SYS->PLLCR &= ~(1 << SYS_PLLCR_OFF_Pos); 283 284 while(SYS->PLLLOCK == 0); //等待PLL锁定 285 } 286