基于野火F407开发板实现电源管理-停止模式
1.创建新工程,工程目录如图:
2.创建bsp_exti.c,bsp_exti.h,main.c这三个文件
bsp_exti.c代码如下:
#include "./exti/bsp_exti.h"
static void NVIC_Config(void)
{
//定义NVIC结构体
NVIC_InitTypeDef NVIC_InitStructure;
//定义中断优先组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//编写NVIC结构体成员
//KEY1引脚
NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//KEY2引脚
NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI_GPIO_Config(void)
{
//定义结构体
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
//开启时钟
RCC_AHB1PeriphClockCmd(KEY1_INT_GPIO_CLK | KEY2_INT_GPIO_CLK,ENABLE);
//使用外部中断时必须开启SYSCFG时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
//配置NVIC
NVIC_Config();
//编写GPIO结构体成员
//KEY1按键的GPIO
GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(KEY1_INT_GPIO_PORT,&GPIO_InitStructure);
//将KEY1连接到SYSCFG
SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE,KEY1_INT_EXTI_PINSOURCE);
//将KEY1引脚连接EXTI中断源
EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
//编写KEY2的结构体成员
GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
GPIO_Init(KEY2_INT_GPIO_PORT,&GPIO_InitStructure);
//将KEY2连接到SYSCFG
SYSCFG_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE,KEY2_INT_EXTI_PINSOURCE);
//将KEY2连接到EXTI中断
EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
bsp_exti.h代码如下:
#ifndef __EXTI_H
#define __EXTI_H
#include "stm32f4xx.h"
//引脚定义
/*******************************************************/
#define KEY1_INT_GPIO_PORT GPIOA
#define KEY1_INT_GPIO_CLK RCC_AHB1Periph_GPIOA
#define KEY1_INT_GPIO_PIN GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE EXTI_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE EXTI_PinSource0
#define KEY1_INT_EXTI_LINE EXTI_Line0
#define KEY1_INT_EXTI_IRQ EXTI0_IRQn
#define KEY1_IRQHandler EXTI0_IRQHandler
#define KEY2_INT_GPIO_PORT GPIOC
#define KEY2_INT_GPIO_CLK RCC_AHB1Periph_GPIOC
#define KEY2_INT_GPIO_PIN GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE EXTI_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE EXTI_PinSource13
#define KEY2_INT_EXTI_LINE EXTI_Line13
#define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn
#define KEY2_IRQHandler EXTI15_10_IRQHandler
void EXTI_GPIO_Config(void);
#endif /* __EXTI_H */
main.c代码如下:
#include "stm32f4xx.h"
#include "./usart/bsp_debug_usart.h"
#include "./led/bsp_led.h"
#include "./exti/bsp_exti.h"
static void Delay(__IO uint32_t nCount);
static void SYSCLKConfig_STOP(void);
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
RCC_ClocksTypeDef clock_status_wakeup, clock_status_config;
uint8_t clock_source_wakeup, clock_source_config;
LED_GPIO_Config();
Debug_USART_Config();
EXTI_GPIO_Config();
printf("\r\n 欢迎使用野火 STM32 F407 开发板。\r\n");
printf("\r\n 野火F407 停止模式例程\r\n");
printf("\r\n 实验说明:\r\n");
printf("\r\n 1.本程序中,绿灯表示STM32正常运行,红灯表示停止状态,蓝灯表示刚从停止状态被唤醒\r\n");
printf("\r\n 2.在停止状态下,可使用KEY1或KEY2唤醒\r\n");
printf("\r\n 3.本实验执行这样一个循环:\r\n ------》亮绿灯(正常运行)->亮红灯(停止模式)->按KEY1或KEY2唤醒->亮蓝灯(刚被唤醒)-----》\r\n");
printf("\r\n 4.在停止状态下,DAP下载器无法给STM32下载程序,\r\n 可按KEY1、KEY2唤醒后下载,\r\n 或按复位键使芯片处于复位状态,然后在电脑上点击下载按钮,再释放复位按键,即可下载\r\n");printf("\r\n 欢迎使用野火 STM32 F407 开发板。\r\n");
printf("\r\n 野火F407 停止模式例程\r\n");
printf("\r\n 实验说明:\r\n");
printf("\r\n 1.本程序中,绿灯表示STM32正常运行,红灯表示停止状态,蓝灯表示刚从停止状态被唤醒\r\n");
printf("\r\n 2.在停止状态下,可使用KEY1或KEY2唤醒\r\n");
printf("\r\n 3.本实验执行这样一个循环:\r\n ------》亮绿灯(正常运行)->亮红灯(停止模式)->按KEY1或KEY2唤醒->亮蓝灯(刚被唤醒)-----》\r\n");
printf("\r\n 4.在停止状态下,DAP下载器无法给STM32下载程序,\r\n 可按KEY1、KEY2唤醒后下载,\r\n 或按复位键使芯片处于复位状态,然后在电脑上点击下载按钮,再释放复位按键,即可下载\r\n");
while(1)
{
printf("\r\n stm32运行正常,绿灯亮起\r\n");
LED_GREEN;
Delay(0x3FFFFFF);
/*任务执行完毕,进入停止模式*/
printf("\r\n 进入停止模式,按KEY1或KEY2引脚能唤醒\r\n");
LED_RED;
/*如果进入停止模式,FLASH要进入掉电状态*/
PWR_FlashPowerDownCmd(ENABLE);
/*进入停止模式,将电压调节器设为低功耗模式,等待中断唤醒*/
PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);
//等待中断被唤醒,按下KEY1或KEY2按键
/*被唤醒*/
//获取刚被唤醒时的状态
clock_source_wakeup = RCC_GetSYSCLKSource();
//时钟频率
RCC_GetClocksFreq(&clock_status_wakeup);
//重启HSE,PLLCLK
SYSCLKConfig_STOP();
//获取配置后的时钟状态
clock_source_config = RCC_GetSYSCLKSource();
RCC_GetClocksFreq(&clock_status_config);
printf("\r\n 重新配置后的状态:\r\n");
printf("SYSCLK频率:%d,\r\n HCLK频率:%d,\r\n PCLK1频率:%d,\r\n PCLK2频率:%d,\r\n 时钟源:%d\n",
clock_status_config.SYSCLK_Frequency,
clock_status_config.HCLK_Frequency,
clock_status_config.PCLK1_Frequency,
clock_status_config.PCLK2_Frequency,
clock_source_config);
printf("\r\n刚唤醒的时钟状态:\r\n");
printf(" SYSCLK频率:%d,\r\n HCLK频率:%d,\r\n PCLK1频率:%d,\r\n PCLK2频率:%d,\r\n 时钟源:%d (0表示HSI,8表示PLLCLK)\n",
clock_status_wakeup.SYSCLK_Frequency,
clock_status_wakeup.HCLK_Frequency,
clock_status_wakeup.PCLK1_Frequency,
clock_status_wakeup.PCLK2_Frequency,
clock_source_wakeup);
LED_BLUE;
Delay(0x1FFFFFF);
printf("\r\n 已退出停止模式 \r\n");
}
}
static void SYSCLKConfig_STOP(void)
{
//使能HSE
RCC_HSEConfig(RCC_HSE_ON);
//等待HSE准备就绪
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY)==RESET)
{
}
//使能PLL
RCC_PLLCmd(ENABLE);
//等待PLL准备就绪
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)
{
}
//选择PLL作为系统时钟
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
//等待PLL被选择为系统时钟
while (RCC_GetSYSCLKSource()!=0x08)
{
}
}
static void Delay(__IO uint32_t nCount)
{
for(;nCount != 0;nCount--);
}
3.代码编译成功,烧录进开发板