单片机 :STM32F407
开发板:DMF407电机开发板
平台:keil V5.31
HSE 为8MHZ
HSI为16MHZ

一、PVD电压电压检测实验
主函数:
int main(void)
{
uint8_t t = 0;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
pwr_pvd_init(PWR_PVDLEVEL_7); /* PVD 2.9V检测 */
lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
lcd_show_string(30, 70, 200, 16, 16, "PVD TEST", RED);
lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
/* 默认LCD显示电压正常 */
lcd_show_string(30, 110, 200, 16, 16, "PVD Voltage OK! ", BLUE);
while (1)
{
if ((t % 20) == 0)
{
LED0_TOGGLE(); /* 每200ms,翻转一次LED0 */
}
delay_ms(10);
t++;
}
}
配置:
/**
* @brief 初始化PVD电压监视器
* @param pls: 电压等级(PWR_PVD_detection_level)
* @arg PWR_PVDLEVEL_0,2.2V;
* @arg PWR_PVDLEVEL_1,2.3V;
* @arg PWR_PVDLEVEL_2,2.4V;
* @arg PWR_PVDLEVEL_3,2.5V;
* @arg PWR_PVDLEVEL_4,2.6V;
* @arg PWR_PVDLEVEL_5,2.7V;
* @arg PWR_PVDLEVEL_6,2.8V;
* @arg PWR_PVDLEVEL_7,2.9V;
* @retval 无
*/
void pwr_pvd_init(uint32_t pls)
{
PWR_PVDTypeDef pvd_handle = {0};
__HAL_RCC_PWR_CLK_ENABLE();
pvd_handle.PVDLevel = pls;
pvd_handle.Mode = PWR_PVD_MODE_IT_RISING_FALLING;
HAL_PWR_ConfigPVD(&pvd_handle);
HAL_NVIC_SetPriority(PVD_IRQn, 3, 3); /* 抢占优先级3,子优先级3 */
HAL_NVIC_EnableIRQ(PVD_IRQn);
HAL_PWR_EnablePVD();
}
/**
* @brief PVD中断服务函数
* @param 无
* @retval 无
*/
void PVD_IRQHandler(void)
{
HAL_PWR_PVD_IRQHandler();
}
/**
* @brief PVD/AVD中断服务回调函数
* @param 无
* @retval 无
*/
void HAL_PWR_PVDCallback(void)
{
if (__HAL_PWR_GET_FLAG(PWR_FLAG_PVDO)) /* 电压比PLS所选电压还低 */
{
lcd_show_string(30, 130, 200, 16, 16, "PVD Low Voltage!", RED); /* LCD显示电压低 */
LED1(0); /* 点亮绿灯, 表明电压低了 */
}
else
{
lcd_show_string(30, 130, 200, 16, 16, "PVD Voltage OK! ", BLUE);/* LCD显示电压正常 */
LED1(1); /* 灭掉绿灯 */
}
}
测试结果:

二、睡眠模式实验
主函数:

配置:
/**
* @brief 低功耗模式下的按键初始化(用于唤醒睡眠模式/停止模式/待机模式)
* @param 无
* @retval 无
*/
void pwr_key_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
PWR_KEY1_GPIO_CLK_ENABLE(); /* KEY1时钟使能 */
gpio_init_struct.Pin = PWR_KEY1_GPIO_PIN; /* KEY1唤醒按键引脚 */
gpio_init_struct.Mode = GPIO_MODE_IT_FALLING; /* 中断,上升沿 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 下拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(PWR_KEY1_GPIO_PORT, &gpio_init_struct); /* 引脚初始化 */
HAL_NVIC_SetPriority(PWR_KEY1_INT_IRQn, 2, 2); /* 抢占优先级2,子优先级2 */
HAL_NVIC_EnableIRQ(PWR_KEY1_INT_IRQn);
}
/**
* @brief KEY1按键 外部中断服务程序
* @param 无
* @retval 无
*/
void PWR_KEY1_INT_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(PWR_KEY1_GPIO_PIN);
}
/**
* @brief 进入CPU睡眠模式
* @param 无
* @retval 无
*/
void pwr_enter_sleep(void)
{
HAL_SuspendTick(); /* 暂停滴答时钟,防止通过滴答时钟中断唤醒 */
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); /* 执行WFI指令, 进入待机模式 */
}
/**
* @brief 外部中断回调函数
* @param GPIO_Pin:中断线引脚
* @note 此函数会被PWR_WKUP_INT_IRQHandler()调用
* @retval 无
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == PWR_KEY1_GPIO_PIN)
{
/* HAL_GPIO_EXTI_IRQHandler()函数已经为我们清除了中断标志位,所以我们进了回调函数可以不做任何事 */
}
}
实验结果:
按下按键0,进入睡眠模式,绿灯常亮;按下按键1,退出睡眠,绿灯灭,红灯闪烁。
三、停止模式实验:
主函数:

配置:
void pwr_enter_stop(void)
{
__HAL_RCC_PWR_CLK_ENABLE();
HAL_SuspendTick(); /* 暂停滴答时钟,防止通过滴答时钟中断唤醒 */
/* 当SVOS3进入停止模式时,设置稳压器为低功耗模式,等待中断唤醒 */
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
}
实验结果:
按下按键0进入停止模式,按下按键1退出。
四、待机模式实验
主函数:

配置:
/**
* @brief 低功耗模式下的按键初始化(用于唤醒睡眠模式/停止模式/待机模式)
* @param 无
* @retval 无
*/
void pwr_key_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
PWR_KEY1_GPIO_CLK_ENABLE(); /* KEY1时钟使能 */
gpio_init_struct.Pin = PWR_KEY1_GPIO_PIN; /* KEY1唤醒按键引脚 */
gpio_init_struct.Mode = GPIO_MODE_IT_FALLING; /* 中断,上升沿 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 下拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(PWR_KEY1_GPIO_PORT, &gpio_init_struct); /* 引脚初始化 */
HAL_NVIC_SetPriority(PWR_KEY1_INT_IRQn, 2, 2); /* 抢占优先级2,子优先级2 */
HAL_NVIC_EnableIRQ(PWR_KEY1_INT_IRQn);
PWR_WKUP_GPIO_CLK_ENABLE(); /* WKUP时钟使能 */
gpio_init_struct.Pin = PWR_WKUP_GPIO_PIN; /* WK_UP引脚 */
gpio_init_struct.Mode = GPIO_MODE_IT_RISING; /* 中断,上升沿 */
gpio_init_struct.Pull = GPIO_PULLDOWN; /* 下拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(PWR_WKUP_GPIO_PORT, &gpio_init_struct); /* WK_UP引脚初始化 */
HAL_NVIC_SetPriority(PWR_WKUP_INT_IRQn, 2, 2); /* 抢占优先级2,子优先级2 */
HAL_NVIC_EnableIRQ(PWR_WKUP_INT_IRQn);
}
/**
* @brief 进入待机模式
* @param 无
* @retval 无
*/
void pwr_enter_standby(void)
{
__HAL_RCC_AHB1_FORCE_RESET(); /* 复位所有IO口 */
while(WKUP_KD); /* 等待WK_UP按键松开(在有RTC中断时,必须等WK_UP松开再进入待机) */
__HAL_RCC_PWR_CLK_ENABLE(); /* 使能PWR时钟 */
__HAL_RCC_BACKUPRESET_FORCE(); /* 复位备份区域 */
HAL_PWR_EnableBkUpAccess(); /* 后备区域访问使能 */
/* STM32F4,当开启了RTC相关中断后,必须先关闭RTC中断,再清中断标志位,然后重新设置 */
/* RTC中断,再进入待机模式才可以正常唤醒,否则会有问题. */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
__HAL_RTC_WRITEPROTECTION_DISABLE(&g_rtc_handle); /* 关闭RTC写保护 */
/* 关闭RTC相关中断,可能在RTC实验打开了 */
__HAL_RTC_WAKEUPTIMER_DISABLE_IT(&g_rtc_handle, RTC_IT_WUT);
__HAL_RTC_TIMESTAMP_DISABLE_IT(&g_rtc_handle, RTC_IT_TS);
__HAL_RTC_ALARM_DISABLE_IT(&g_rtc_handle, RTC_IT_ALRA|RTC_IT_ALRB);
/* 清除RTC相关中断标志位 */
__HAL_RTC_ALARM_CLEAR_FLAG(&g_rtc_handle, RTC_FLAG_ALRAF|RTC_FLAG_ALRBF);
__HAL_RTC_TIMESTAMP_CLEAR_FLAG(&g_rtc_handle, RTC_FLAG_TSF);
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&g_rtc_handle, RTC_FLAG_WUTF);
__HAL_RCC_BACKUPRESET_RELEASE(); /* 备份区域复位结束 */
__HAL_RTC_WRITEPROTECTION_ENABLE(&g_rtc_handle); /* 使能RTC写保护 */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); /* 清除Wake_UP标志 */
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); /* 设置WKUP用于唤醒 */
HAL_PWR_EnterSTANDBYMode(); /* 进入待机模式 */
}
测试结果:
按下按键0,进入待机模式,LCD灭;
按下按键1,无反应。
将PA0接5.0V,启动,容易死机。