//THUMB指令不支持汇编内联
//采用如下方法实现执行汇编指令WFI __asm void WFI_SET(void) {
WFI; }
解释:这里用到了一个WFI_SET();函数,该函数其实是在C 语言里面嵌入一条汇编指令,因为CM3 内核的STM32 支持的THUMB 指令,并不能内嵌汇编,所以需要通过这个方法来实现汇编代码的嵌入。
/进入待机模式
void Sys_Standby(void) {
SCB->SCR|=1<<2;//使能SLEEPDEEP位 (SYS->CTRL) RCC->APB1ENR|=1<<28; //使能电源时钟 PWR->CSR|=1<<8; //设置WKUP用于唤醒 PWR->CR|=1<<2; //清除Wake-up 标志 PWR->CR|=1<<1; //PDDS置位 WFI_SET(); //执行WFI指令 }
解释:STM32 提供了3 种低功耗模式,以达到不同层次的降低功耗的目的,这三种模式如下:
睡眠模式(CM3 内核停止工作,外设仍在运行); 停止模式(所有的时钟都停止); 待机模式;
其中睡眠模式又分为有深度睡眠和睡眠之分。Sys_SleepDeep 函数用来使STM32 进入待机
模式,在该模式下,STM32 所消耗的功耗最低。下面是一个STM32 的低功耗一览表:
下表展示了如何进入和退出待机模式,关于待机模式的更详细介绍请参考《STM32 参考手册》第4.3 节(40 页)。
//系统软复位
void Sys_Soft_Reset(void) {
SCB->AIRCR =0X05FA0000|(u32)0x04; }
解释:软复位归根到底就是对SCB-> AIRCR 进行了一次操作,只要把位2置位即可。
//JTAG模式设置,用于设置JTAG的模式
//mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭;
void JTAG_Set(u8 mode) {
u32 temp; temp=mode; temp<<=25;
RCC->APB2ENR|=1<<0; //开启辅助时钟 AFIO->MAPR&=0XF8FFFFFF; //清除MAPR的[26:24] AFIO->MAPR|=temp; //设置jtag模式 }
解释:
STM32 支持JTAG 和SWD 两种仿真接口,他们和普通的IO 口共用,当需要使用普通IO口的时候,则必须先禁止JTAG/SWD。STM32 在默认状态下是开启JTAG 的,所以那些和JTAG共用的IO 口,在默认状态下是不能做普通IO 口使用的。我们可以通过AFIO_MAPR 寄存器的24~26 位来修改STM32 的JTAG 配置,从而切换为普通IO 口或者其他状态。AFIO_MAPR 寄存器的第24~26 位描述如下图所示:
通过该函数,我们就可以方便的设置JTAG 的模式。这里顺便提一下,JTAG 和普通IO 口,可以在仿真的时候,分时复用,不过在您禁止了JTAG 的地方(先禁止,后开启),您必须一步跳过去,也就是这部分代码,您不要执行到里面去观察,直接跳过。这样,您的JTAG 可以在不断线的情况下,继续调试下面的代码。
RCC->APB2ENR|=1<<0; //开启辅助时钟
//系统时钟初始化函数
//pll:选择的倍频数,从2开始,最大值为16 void Stm32_Clock_Init(u8 PLL) { unsigned char temp=0; MYRCC_DeInit(); //复位并配置向量表 RCC->CR|=0x00010000; //外部高速时钟使能HSEON while(!(RCC->CR>>17));//等待外部时钟就绪 RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1; PLL-=2;//抵消2个单位 RCC->CFGR|=PLL<<18; //设置PLL值 2~16 RCC->CFGR|=1<<16; //PLLSRC ON FLASH->ACR|=0x32; //FLASH 2个延时周期 RCC->CR|=0x01000000; //PLLON while(!(RCC->CR>>25));//等待PLL锁定 RCC->CFGR|=0x00000002;//PLL作为系统时钟 while(temp!=0x02) //等待PLL作为系统时钟设置成功 { temp=RCC->CFGR>>2; temp&=0x03; } } 解释: MYRCC_DeInit(); //复位并配置向量表 调用复位与配置向量表函数
RCC->CR|=0x00010000; //外部高速时钟使能HSEON
while(!(RCC->CR>>17));//等待外部时钟就绪
第17位右移17位,正好在第0位,如果第17位为零,则整个数字为零,因为上面刚刚复位过的,所以17位前面都是为零,如果第17位为1,即外部高速时钟就绪,那就不为0,不为0就可以执行以下的语句了。 RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;
RCC->CFGR=0000 0000 0000 0000 0000 0100 0000 0000,[10:8]为100, 那APB1就是2分频,APB2不分频,同理AHB也不分频。