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
}
相关推荐
FreakStudio7 天前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
✎ ﹏梦醒͜ღ҉繁华落℘12 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
u1521096484913 天前
S.S.Audio PRO A2音频隔离器
嵌入式硬件·音视频·实时音视频·视频编解码·视频
zd84510150013 天前
RS485 总线详解
单片机·嵌入式硬件
半条-咸鱼13 天前
【STM32】I2C协议原理、HAL读写与OLED显示操作
嵌入式硬件·c·信息与通信
牛根生同志13 天前
SPI数据收发的时候 TXE与RXNE标志位置位的时机
stm32·spi·transfer
wohoo_wangzi13 天前
苏州晟雅泰电子:关于W25Q128JVSIQ这个芯片物料的参数,规格及应用领域
嵌入式硬件
goldenrolan13 天前
学习型红外控制系统稳定性挂测工装专项总结
软件测试·python·stm32·嵌入式·红外
✎ ﹏梦醒͜ღ҉繁华落℘13 天前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展13 天前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件