stm32休眠和唤醒,和内部flash

stm32正在使用,如果是带充电电池的,是可以不靠断电关机的.有些就完全不关机.比如摩托车的远程启动. 这里是一个休眠的方法.休眠后的耗电量的非常小的几乎可以忽略不计.

引入

复制代码
 #include "stm32f10x_exti.h"//并在stdPeriph_Driver里引入
 #include "stm32f10x_pwr.h"

还要引入一个按钮, 常开按键

main.c

c 复制代码
#include "Store.h" //把store.c .h和myflash.c.h四个文件加入 且魔法棒的c的include paths也加入,然后stdPeriph_dirver里add ..._flash.c

#define BUTTON_PORT     GPIOB  //注意要改Button_Init
#define BUTTON_PIN      GPIO_Pin_0  // 你的开关接 PB0
#define BUTTON_EXTI     EXTI_Line0
#define BUTTON_IRQ      EXTI0_IRQn

void  Delay (uint32_t nCount)
{
      /* SysTick 简易延时,72MHz 主频下大约 1ms */
    while (nCount--)
    {
        volatile uint32_t count = 7200;
        while (count--);
    }
}

/* -------- 按键 GPIO + EXTI 初始化 -------- */
void Button_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    EXTI_InitTypeDef  EXTI_InitStruct;
    NVIC_InitTypeDef  NVIC_InitStruct;

    /* 1. 开启时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);

    /* 2. PA0 配置为上拉输入 */
    GPIO_InitStruct.GPIO_Pin  = BUTTON_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);

    /* 3. 将 PB0 映射到 EXTI Line0 */
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);

    /* 4. EXTI 配置:下降沿触发(按键按下 = 拉低) */
    EXTI_InitStruct.EXTI_Line    = BUTTON_EXTI;
    EXTI_InitStruct.EXTI_Mode    = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStruct);

    /* 5. NVIC 配置 */
    NVIC_InitStruct.NVIC_IRQChannel                   = BUTTON_IRQ;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority  = 0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority         = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd                 = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
}
/* -------- EXTI0 中断服务函数 -------- */
void EXTI0_IRQHandler(void)
{
    if (EXTI_GetITStatus(BUTTON_EXTI) != RESET)
    {
        EXTI_ClearITPendingBit(BUTTON_EXTI);
        /* 中断里不做复杂操作,唤醒即可返回 */
    }
}
/* -------- 进入 STOP 模式 -------- */
static void Enter_Stop_Mode(void)
{
    /*
     * STOP 模式特点:
     *   - 所有时钟停止,1.8V 域关闭
     *   - SRAM 和寄存器内容保持不变
     *   - 可通过 EXTI 中断唤醒
     *   - 唤醒后默认使用 HSI(8MHz),需重新配置 PLL 恢复 72MHz
     */

    /* 关闭 LED,降低功耗 */
    GPIO_SetBits(LED_PORT, LED_PIN);

    /* 清除 EXTI 挂起位,防止残留中断立刻唤醒 */
    EXTI_ClearFlag(BUTTON_EXTI);

    /* 进入 STOP 模式
     * 参数 1:PWR_Regulator_ON 保持调压器正常运行,唤醒速度快但休眠功耗稍高;PWR_Regulator_LowPower 调压器进入低功耗模式,功耗更低但唤醒时间会长一些。
								对于按键唤醒这种对速度不敏感的场景,用 PWR_Regulator_LowPower 就好
     * 参数 2:入口方式   ------ PWR_STOPEntry_WFI 等待中断 */
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
}
/* -------- STOP 唤醒后恢复系统时钟(72MHz HSE + PLL) -------- */
static void SYSCLK_Restore(void)
{
    /*
     * 从 STOP 模式唤醒后,系统时钟默认切换到 HSI(8MHz)。
     * 如果之前使用 HSE + PLL 跑到 72MHz,这里需要重新配置。
     */
    ErrorStatus HSEStartUpStatus;

    RCC_DeInit();
    RCC_HSEConfig(RCC_HSE_ON);
    HSEStartUpStatus = RCC_WaitForHSEStartUp();

    if (HSEStartUpStatus == SUCCESS)
    {
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
        FLASH_SetLatency(FLASH_Latency_2);   /* 72MHz 需要 2 个等待周期 */

        RCC_HCLKConfig(RCC_SYSCLK_Div1);
        RCC_PCLK2Config(RCC_HCLK_Div1);
        RCC_PCLK1Config(RCC_HCLK_Div2);

        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  /* 8MHz × 9 = 72MHz */
        RCC_PLLCmd(ENABLE);
        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        while (RCC_GetSYSCLKSource() != 0x08);
    }
}
int main(void)
{
		int16_t count = 0;
		uint8_t is_sleeping = 0;
		/* 开启 PWR 时钟(进入低功耗模式前必须开启) */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
		/* Infinite loop */
    while (1){
    			if (GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN) == Bit_RESET)
			{
					Delay(20);   /* 消抖 */
					if (GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN) == Bit_RESET)
					{
							/* 等待按键释放,避免松手时再次触发 */
							while (GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN) == Bit_RESET);
							Delay(20);
							
							/* --- 代码收尾 ---*/
							printf("sleep \n");
							SaveFlush();
							res = f_mount(0, NULL);   // 卸载SD 卡
							SD_DeInit();//关闭 SD 卡 SPI 外设
							
							/* ---- 进入休眠 ---- */
							Enter_Stop_Mode();

							/* ====== 从这里开始是唤醒后的代码 ====== */

							/* 恢复 72MHz 系统时钟 */
							SYSCLK_Restore();

							/* 重新初始化外设(时钟恢复后需要重配) */
							SD_Init();
							LED_Init();
							Button_Init();
							//hx711初始化
							GPIO_hx711_Config();
							HX711_Init();
							f_mount(0,&fs);	
	
							printf("waked up \n");
							Delay(100);
							
					}
			}
			//count = count + 1;//检验全局变量在休眠后是否丢失 (即使可以,重要变量还是存内部flash)(不会丢失)(最好用static)
			//printf("%d\n",count);
			Delay(10);
			}

表现: 按一下, 就会进入休眠.打印sleep. 再按一下唤醒打印waked up.

sleep的状态下,

//printf("%d\n",count); Delay(10);

这块代码是不会执行的

内部flash

比较简单,单独说

c 复制代码
#include "Store.h" //把store.c .h和myflash.c.h四个文件加入 且魔法棒的c的include paths也加入,然后stdPeriph_dirver里add ..._flash.c

Store_Init();				//参数存储模块初始化,在上电的时候将闪存的数据加载回Store_Data,实现掉电不丢失

while(1)
{
		i = Store_Data[1]; //读取内部flash
		printf("i: %d\n", i);
		OSTimeDlyHMSM(0,0,0,400,OS_OPT_TIME_HMSM_STRICT,&err); //延时400ms
		Store_Data[1] = i + 1;
		Store_Save(); //存储内部flash
}
相关推荐
wangduqiang7471 小时前
stm32写sd卡
stm32·单片机·嵌入式硬件
你疯了抱抱我1 小时前
【STM32】配置vscode+C工具链+Cortex-Debug开发环境,IC:STM32F411CEU6
c语言·vscode·stm32
点灯小铭1 小时前
基于51单片机的LED点阵汉字显示系统设计
数据库·单片机·嵌入式硬件·毕业设计·51单片机·课程设计·期末大作业
橡木树的叶子2 小时前
STM32单片机+RGB三色灯模块+七色灯颜色数据发送到串口调试助手+源代码(使用cubuemx+vscode实现操作)
stm32·单片机·计算机外设
踏着七彩祥云的小丑2 小时前
嵌入式测试学习第 30 天:功耗测试、待机电流、工作电流测试
单片机·嵌入式硬件·学习
潜创微科技2 小时前
2026年专业创作KVM方案服务商选型指南:技术、场景与服务的全维度评估
嵌入式硬件·音视频
大阳1232 小时前
ARM.9(RGBLCD,PWM)
c语言·开发语言·汇编·单片机·嵌入式硬件·pwm·rgblcd
济6172 小时前
ROS开发专栏---ROS2 机械臂应用入门(1)---JointState 消息解析与机械臂往复运动控制实验---适配Ubuntu 22.04
嵌入式硬件·嵌入式·ros2·机器人开发·机器人方向
caimouse2 小时前
ReactOS 项目目录工程分析文档
stm32·单片机·嵌入式硬件