STM32复习笔记(六) —— 配置系统时钟
1.系统启动过程
1)设置初始堆栈指针 SP 2)设置初始程序计数器 (PC) 指向复位中断 3)设置向量表 (由各中断地址组成) 4)配置系统时钟 (SystemInit 函数) 5)跳转到C库 __main (最终调用 main 函数)
于 main.c 中编写代码
#include "stm32f10x.h"
int main(void)
{
while(1);
}
打开 Options for Target … - Debug,取消 Run to main() 的勾选 (即不直接跳转到 main 函数) 点击编译,如无错误可进入仿真界面,此时 PC 指向复位中断 点击单步运行 再点击一次单步运行将会跳转至 SystemInit 函数 点击 Step Out 先跳过此函数,回到启动文件 继续点击单步运行,下一步会跳转到C库 __main (最终调用 main 函数) 2.配置系统时钟
于 system_stm32f10x.c 文件中找到 SystemInit 函数 在此函数中找到 SetSysClock 函数,即为系统时钟配置 (固件库内已按默认参数配置) 找到 SetSysClock 函数,默认被配置为 72MHz 重新配置系统时钟,为避免原函数 SetSysClockTo72 的影响,将其注释掉
系统时钟 (SYSCLK) 可以来自 HSI or HSE or PLL,PLL 时钟可以来自 HSI/2 or HSE(HSE/2) 下图以 HSE - PLL - SYSCLK 为例 (假设外接 HSE = 8MHz) 配置过程:将 HSE 的8MHz输入到 PLL,经过 PLL 9倍频 (72MHz),输出为 SYSCLK
3.本例程软件设计思路
1)使用 HSE (8MHz) 配置 PLL 时钟 (9倍频) 作为系统时钟 (8MHz -> 72MHz) 2)配置 GPIOA 的 GPIO_Pin_0 作为LED功能 3)每延时一段时间进行 LED 状态翻转
此例程最好下载到实物芯片中验证
首先将 system_stm32f10x.c 中的 SetSysClockTo72 函数声明与定义注释掉,将 SetSysClockTo72 函数声明与定义替换为 User_SetSysClockTo72 函数声明与定义
static void User_SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CR |= ((uint32_t)0x01 << 16);
do
{
HSEStatus = RCC->CR & ((uint32_t)0x01 << 17);
StartUpCounter++;
}
while((0 == HSEStatus) && (0x0500 != StartUpCounter));
if(0 != (RCC->CR & ((uint32_t)0x01 << 17)))
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if((uint32_t)0x01 == HSEStatus)
{
FLASH->ACR |= FLASH_ACR_PRFTBE;
FLASH->ACR &= ~(uint32_t)0x03;
FLASH->ACR |= (uint32_t)0x02;
RCC->CFGR |= (uint32_t)0x00 << 4;
RCC->CFGR |= (uint32_t)0x00 << 11;
RCC->CFGR |= (uint32_t)0x04 << 8;
RCC->CFGR &= ~((uint32_t)0x3f << 16);
RCC->CFGR |= (uint32_t)0x00 << 17;
RCC->CFGR |= (uint32_t)0x01 << 16;
RCC->CFGR |= (uint32_t)0x07 << 18;
RCC->CR |= (uint32_t)0x01 << 24;
while(0 == (RCC->CR & (uint32_t)0x01 << 25));
RCC->CFGR &= ~((uint32_t)0x03 << 0);
RCC->CFGR |= ((uint32_t)0x02 << 0);
while((uint32_t)0x08 != (RCC->CFGR & ((uint32_t)0x03 << 2)));
}
else
{
}
}
于 main.c 中编写代码
#include "stm32f10x.h"
typedef enum
{
S_GPIO_Mode_OUT = 0x01,
S_GPIO_OType_PP = 0x00
}GPIOA_Config_TypeDef;
void delay_(uint32_t count);
int main(void)
{
uint32_t spinposl = 0x00;
RCC->APB2ENR |= ((uint32_t)1 << 2);
GPIOA->CRL &= ~((uint32_t)0x03 << (spinposl * 4));
GPIOA->CRL |= ((uint32_t)S_GPIO_Mode_OUT << (spinposl * 4));
GPIOA->CRL &= ~((uint32_t)0x03 << ((spinposl * 4) + 2));
GPIOA->CRL |= ((uint32_t)S_GPIO_OType_PP << ((spinposl * 4) + 2));
GPIOA->BRR |= (uint16_t)0x01;
while(1)
{
GPIOA->ODR ^= (uint16_t)0x01;
delay_(500);
}
}
void delay_(uint32_t count)
{
__IO uint32_t delay_count = (12000 * count);
while(delay_count--);
}
4.编译及仿真
点击编译,如无错误可进入仿真界面 打开逻辑分析仪 点击 Setup Logic Analyzer,添加要查看的引脚 选中添加的引脚,修改 Display Type 为 Bit 点击运行 停止并退出仿真,返回 system_stm32f10x.c 文件,修改 User_SetSysClockTo72 函数中配置的 PLL 倍频系数 (由9倍频改为3倍频,即系统时钟由72MHz变为24MHz) 编译后再进入仿真,点击运行 24MHz时输出的波形翻转间隔约为72MHz时输出波形间隔的3倍,与预想结果一致
|