原子的第一个例程流水灯中用了 Stm32_Clock_Init()函数,现在来解析一下:
引用时Stm32_Clock_Init(9);
定义(此处省略了跑OS时的代码)
看程序前,请确保理解了这个时钟树(并对RCC寄存器组有了解)
void Stm32_Clock_Init(unsigned char PLL)
{
unsigned char temp = 0;
MYRCC_DeInit(); //复位一些RC寄存器与向量表
RCC->CR |= 0x00010000; //开启HSE(由于战舰是外接了8MHZ的晶振,所以要用)
while(!(RCC->CR >> 17)); //等待HSE完全开启
RCC->CFGR = 0x00000400; //PPRE1 /2 //APB1为2分频
PLL -= 2; //由于CFGR寄存器中000代表二倍频,所以111代表9倍频,即7,所以9要-2变成7,其实引用此函数时的9是要9倍频,达到SYSCLK为72Hz,
RCC->CFGR |= (unsigned int)PLL << 18; // PLL X 9//写入9倍频
RCC->CFGR |= 1 << 16; //打开SRC选择器,即选用HSE作为倍频
FLASH->ACR |= 0x32; //2个周期的延时,具体详见STM32F10xxx闪存编程手册,很详细,如果你不想看,就暂且将它想成这里是向FLASH的ACR寄存器中写入0x32,而这个延时是以后保证程序不跑飞用的。
RCC->CR |= 0x01000000; //打开PLL倍频器
while(!(RCC->CR >> 25)); //等待PLL倍频器打开
RCC->CFGR |= 0x00000002;//SYSCLK时钟来源为PLL
while(temp != 0x02)
{
temp = RCC->CFGR >> 2;
temp &= 0x03;
}由SWS寄存器看出是否成功切换SYSCLK源
}
现在来看一下那个复位及设置向量表函数
void MYRCC_DeInit(void)
{
RCC->APB1RSTR = 0x00000000;
RCC->APB2RSTR = 0x00000000;
RCC->AHBENR = 0x00000014;
RCC->APB2ENR = 0x00000000;
RCC->APB1ENR = 0x00000000;
//以上的设置是这些寄存的复位值
RCC->CR |= 0x00000001; //由于是复位,所以就打开了内部的HSI,注意这里和Stm32_Clock_Init()里设置的将HSE作为SYSCLK并不冲突,因为这在本函数之后的位置
RCC->CFGR &= (0xf8ff0000);//复位SW,HPRE,PPRE1,PPRE2,ADCPRE,MCO
RCC->CR &= 0xfef6ffff;//复位HSEON,CSSON,PLLON
RCC->CR &= 0xfffbffff;//复位HSEBYP
RCC->CFGR &= 0xff80ffff;//复位PLLSRC,PLLXTPRE,PLLMUL,USBPRE
RCC->CIR = 0x00000000;//关闭所有中断
MY_NVIC_SetVectorTable(0x08000000,0x0);//由于一开始将向量表放在FLASH区,并设置偏移为0
}
好现在来看那个MY_NVIC_SetVectorTable函数
void MY_NVIC_SetVectorTable(unsigned int NVIC_VectTab, unsigned int Offset)
{
SCB->VTOR = NVIC_VectTab | (Offset & (unsigned int)0x1fffff80);
}
关于这个函数中的SCB是cortex-m3中关于系统控制的寄存器组,VTOR是关于向量表初始值及其移位的寄存器具体见Cortex-M3参考手册中关于嵌套向量中断控制寄存器的描述,在这我截个图