前言
自己学习stm32的一些小笔记
下面这些内容需要 STM32中文参考手册_V10配合使用
资料连接:
https://pan.baidu.com/s/1uY7SjmHKLwy3xbqYulnJPw 提取码 uk62
一、STM32F103ZE时钟初始化
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;//对CR寄存器进行操作 8mhz振荡器
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;//使HSEON, CSSON and PLLON位置0
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;//使HSEBYP 置0
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR &= (uint32_t)0xFF80FFFF;//使PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE置零
....
SetSysClock();
首先,这些是stm32时钟初始化的部分语句,这些是直接操作RCC寄存器中的RCC_CR ,RCC_CFGR,RCC_CIR等等寄存器。这些寄存器都是32位的
这些寄存器详细信息可以在stm32中文参考手册中找到,罗列上述用到的寄存器信息(详细信息会写在文章末尾)
首先看到寄存器是32位,首先打开HSEON开启内部8MHZ振荡器
RCC->CR |= (uint32_t)0x00000001;RCC->CR是一个结构体指向CR寄存器,与0x00000001进行或运算,就是把最后一位赋值给1即HSION=1;
ps:(0x00000001是一个十六进制的00000001,这个是表示每一位上的数字代表的二进制的0000的四位,所以每一个代表四个二进制位,一共8个数,所以4*8=32对应寄存器的32位,)。
由此,可以根据寄存器位来编写我们所需要的寄存器位。将相应的位置零之后进入到SetSysClock();
二、SetSysClock()解读
1.引入库
代码如下(示例):
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
SetSysClockTo56();
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
#endif
这是配置相应频率的时钟,在这里直接使用系统初始配置的72M时钟,(修改其他频率可以直接修改宏定义)。
2.SetSysClockTo72()解读
代码如下(示例):
RCC->CR |= ((uint32_t)RCC_CR_HSEON);//第16位使能
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;//每次使能都需要等待稳定,由硬件置一表示当前状态是否稳定。判断是否等待就绪
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;//稳定
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
**/* FLASH先不管 */**
FLASH->ACR |= FLASH_ACR_PRFTBE;
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;//HCLK = SYSCLK要使它相等,需要不分频
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;//同上
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;//第十位置1,表示HCLK 2分频
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);//因为HSE默认8Mhz 所以9倍频输出为72Mhz
```RCC->CR |= RCC_CR_PLLON;//配置完打开PLL
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source *///设置pll时钟
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)0x08)
{}
/********RCC_CR寄存器宏定义**********/
#define RCC_CR_HSION ((uint32_t)0x00000001)
#define RCC_CR_HSIRDY ((uint32_t)0x00000002)
#define RCC_CR_HSITRIM ((uint32_t)0x000000F8)
#define RCC_CR_HSICAL ((uint32_t)0x0000FF00)
#define RCC_CR_HSEON ((uint32_t)0x00010000)
#define RCC_CR_HSERDY ((uint32_t)0x00020000)
#define RCC_CR_HSEBYP ((uint32_t)0x00040000)
#define RCC_CR_CSSON ((uint32_t)0x00080000)
#define RCC_CR_PLLON ((uint32_t)0x01000000)
#define RCC_CR_PLLRDY ((uint32_t)0x02000000)
//
#define RCC_CFGR_HPRE_DIV1 ((uint32_t)0x00000000)
#define RCC_CFGR_PPRE2_DIV1 ((uint32_t)0x00000000)
#define RCC_CFGR_PPRE1_DIV2 ((uint32_t)0x00000400)
#define RCC_CFGR_PLLSRC_HSE ((uint32_t)0x00010000)
#define RCC_CFGR_PLLMULL9 ((uint32_t)0x001C0000)
#define RCC_CFGR_SW_PLL ((uint32_t)0x00000002)
总结
这种将数值代入,跟寄存器位的功能对比就一目了然,记忆更深刻。