F0的频率随意切换

This commit is contained in:
Stone 2014-08-22 16:21:53 +00:00
parent 7a13fdcd7d
commit 21b9c6070d
4 changed files with 108 additions and 196 deletions

View File

@ -1,194 +1,101 @@
#include "stm32.h" #include "stm32.h"
static void SetSysClock(void); extern "C"
uint32_t SystemCoreClock = 48000000;
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
void SystemInit (void)
{
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE and MCOSEL[2:0] bits */
RCC->CFGR &= (uint32_t)0xF8FFB80C;
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */
RCC->CFGR &= (uint32_t)0xFFC0FFFF;
/* Reset PREDIV1[3:0] bits */
RCC->CFGR2 &= (uint32_t)0xFFFFFFF0;
/* Reset USARTSW[1:0], I2CSW, CECSW and ADCSW bits */
RCC->CFGR3 &= (uint32_t)0xFFFFFEAC;
/* Reset HSI14 bit */
RCC->CR2 &= (uint32_t)0xFFFFFFFE;
/* Disable all interrupts */
RCC->CIR = 0x00000000;
/* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */
SetSysClock();
}
/**
* @brief Update SystemCoreClock according to Clock Register Values
* The SystemCoreClock variable contains the core clock (HCLK), it can
* be used by the user application to setup the SysTick timer or configure
* other parameters.
*
* @note Each time the core clock (HCLK) changes, this function must be called
* to update SystemCoreClock variable value. Otherwise, any configuration
* based on this variable will be incorrect.
*
* @note - The system frequency computed by this function is not the real
* frequency in the chip. It is calculated based on the predefined
* constant and the selected clock source:
*
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
*
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
*
* - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
* or HSI_VALUE(*) multiplied/divided by the PLL factors.
*
* (*) HSI_VALUE is a constant defined in stm32f0xx.h file (default value
* 8 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (**) HSE_VALUE is a constant defined in stm32f0xx.h file (default value
* 8 MHz), user has to ensure that HSE_VALUE is same as the real
* frequency of the crystal used. Otherwise, this function may
* have wrong result.
*
* - The result of this function could be not correct when using fractional
* value for HSE crystal.
* @param None
* @retval None
*/
void SystemCoreClockUpdate (void)
{ {
uint32_t tmp = 0, pllmull = 0, pllsource = 0, prediv1factor = 0; uint32_t SystemCoreClock = 48000000;
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
/* Get SYSCLK source -------------------------------------------------------*/ void SystemInit (void)
tmp = RCC->CFGR & RCC_CFGR_SWS; {
SystemCoreClock = 48000000;
switch (tmp)
{ /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */
case 0x00: /* HSI used as system clock */ SetSysClock(SystemCoreClock);
SystemCoreClock = HSI_VALUE; }
break;
case 0x04: /* HSE used as system clock */ void SetSysClock(unsigned int clock)
SystemCoreClock = HSE_VALUE; {
break; __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
case 0x08: /* PLL used as system clock */ uint32_t mull, pll;
/* Get PLL clock source and multiplication factor ----------------------*/
pllmull = RCC->CFGR & RCC_CFGR_PLLMULL; /* Set HSION bit */
pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; RCC->CR |= (uint32_t)0x00000001;
pllmull = ( pllmull >> 18) + 2;
/* Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE and MCOSEL[2:0] bits */
if (pllsource == 0x00) RCC->CFGR &= (uint32_t)0xF8FFB80C;
{
/* HSI oscillator clock divided by 2 selected as PLL clock entry */ /* Reset HSEON, CSSON and PLLON bits */
SystemCoreClock = (HSI_VALUE >> 1) * pllmull; RCC->CR &= (uint32_t)0xFEF6FFFF;
}
else /* Reset HSEBYP bit */
{ RCC->CR &= (uint32_t)0xFFFBFFFF;
prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1;
/* HSE oscillator clock selected as PREDIV1 clock entry */ /* Reset PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */
SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; RCC->CFGR &= (uint32_t)0xFFC0FFFF;
}
break; /* Reset PREDIV1[3:0] bits */
default: /* HSI used as system clock */ RCC->CFGR2 &= (uint32_t)0xFFFFFFF0;
SystemCoreClock = HSI_VALUE;
break; /* Reset USARTSW[1:0], I2CSW, CECSW and ADCSW bits */
} RCC->CFGR3 &= (uint32_t)0xFFFFFEAC;
/* Compute HCLK clock frequency ----------------*/
/* Get HCLK prescaler */ /* Reset HSI14 bit */
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; RCC->CR2 &= (uint32_t)0xFFFFFFFE;
/* HCLK clock frequency */
SystemCoreClock >>= tmp; /* Disable all interrupts */
} RCC->CIR = 0x00000000;
/** /* SYSCLK, HCLK, PCLK configuration ----------------------------------------*/
* @brief Configures the System clock frequency, AHB/APBx prescalers and Flash /* Enable HSE */
* settings. RCC->CR |= ((uint32_t)RCC_CR_HSEON);
* @note This function should be called only once the RCC clock configuration
* is reset to the default reset state (done in SystemInit() function). /* Wait till HSE is ready and if Time out is reached exit */
* @param None do
* @retval None {
*/ HSEStatus = RCC->CR & RCC_CR_HSERDY;
static void SetSysClock(void) StartUpCounter++;
{ } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
uint32_t mull, pll; if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
/* SYSCLK, HCLK, PCLK configuration ----------------------------------------*/ HSEStatus = (uint32_t)0x01;
/* Enable HSE */ }
RCC->CR |= ((uint32_t)RCC_CR_HSEON); else
{
/* Wait till HSE is ready and if Time out is reached exit */ HSEStatus = (uint32_t)0x00;
do }
{
HSEStatus = RCC->CR & RCC_CR_HSERDY; if (HSEStatus != (uint32_t)0x01) return;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); /* Enable Prefetch Buffer and set Flash Latency */
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{ /* HCLK = SYSCLK */
HSEStatus = (uint32_t)0x01; RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
}
else /* PCLK = HCLK */
{ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;
HSEStatus = (uint32_t)0x00;
} /* PLL configuration = HSE * 6 = 48 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
if (HSEStatus == (uint32_t)0x01) //RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6);
{ // 支持多种倍频
/* Enable Prefetch Buffer and set Flash Latency */ mull = clock / 8000000;
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY; pll = ((mull - 2) * 4) << 16;
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | pll);
/* HCLK = SYSCLK */ SystemCoreClock = 8000000 * mull;
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* Enable PLL */
/* PCLK = HCLK */ RCC->CR |= RCC_CR_PLLON;
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;
/* Wait till PLL is ready */
/* PLL configuration = HSE * 6 = 48 MHz */ while((RCC->CR & RCC_CR_PLLRDY) == 0) { }
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
//RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6); /* Select PLL as system clock source */
// Ö§³Ö¶àÖÖ±¶Æµ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
mull = SystemCoreClock / 8000000; RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
pll = ((mull - 2) * 4) << 16;
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | pll); /* Wait till PLL is used as system clock source */
SystemCoreClock = 8000000 * mull; while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL) { }
}
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
} }

View File

@ -57,4 +57,9 @@
#error "请在Keil项目配置C/C++页定义芯片平台如STM32F0/STM32F1/STM32F4" #error "请在Keil项目配置C/C++页定义芯片平台如STM32F0/STM32F1/STM32F4"
#endif #endif
extern "C"
{
void SetSysClock(unsigned int clock);
}
#endif #endif

10
Sys.cpp
View File

@ -355,7 +355,7 @@ TSys::TSys()
MessagePort = 0; // COM1; MessagePort = 0; // COM1;
IsGD = Get_JTAG_ID() == 0x7A3; IsGD = Get_JTAG_ID() == 0x7A3;
if(IsGD) Clock = 120000000; //if(IsGD) Clock = 120000000;
#ifdef STM32F0 #ifdef STM32F0
void* p = (void*)0x1FFFF7AC; // 手册里搜索UID优先英文手册 void* p = (void*)0x1FFFF7AC; // 手册里搜索UID优先英文手册
@ -441,11 +441,11 @@ void TSys::Init(void)
// 如果当前频率不等于配置,则重新配置时钟 // 如果当前频率不等于配置,则重新配置时钟
if(Clock != clock.SYSCLK_Frequency) if(Clock != clock.SYSCLK_Frequency)
{ {
SystemCoreClock = Clock; SetSysClock(Clock);
SystemInit();
RCC_GetClocksFreq(&clock);
Clock = clock.SYSCLK_Frequency;
} }
RCC_GetClocksFreq(&clock);
Clock = clock.SYSCLK_Frequency;
#else #else
Clock = clock.SYSCLK_Frequency; Clock = clock.SYSCLK_Frequency;
#endif #endif

4
Sys.h
View File

@ -4,7 +4,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "Platform/stm32.h" #include "Platform\stm32.h"
/* 类型定义 */ /* 类型定义 */
typedef char sbyte; typedef char sbyte;
@ -32,7 +32,7 @@ typedef char* String;
/* 引脚定义 */ /* 引脚定义 */
//typedef ushort Pin; //typedef ushort Pin;
#include "Platform/Pin.h" #include "Platform\Pin.h"
/* 串口定义 */ /* 串口定义 */
#define COM1 0 #define COM1 0