STM32

Unix时间戳

BKP

读写备份寄存器

main.c

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"

uint8_t KeyNum;

uint16_t ArrayWrite[] = {0x1234,0x2134};
uint16_t ArrayRead[2];

int main(void)
{
	OLED_Init();
	Key_Init();
    
    OLED_ShowString(1,1,"W:");
    OLED_ShowString(2,1,"R:");
    
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
    
	PWR_BackupAccessCmd(ENABLE);//使能备份访问控制
    
    //BKP_WriteBackupRegister(BKP_DR1,0x1234);//对DR1寄存器写入数据(4个字节数据)
    //OLED_ShowHexNum(1,1,BKP_ReadBackupRegister(BKP_DR1),4);//对DR1寄存器中进行读取操作
    
	while(1)
	{
		KeyNum = Key_GetNum();
        if(KeyNum == 1)
        {
            ArrayWrite[0]++;
            ArrayWrite[1]++;
            
            BKP_WriteBackupRegister(BKP_DR1,ArrayWrite[0]);
            BKP_WriteBackupRegister(BKP_DR2,ArrayWrite[1]);
            
            OLED_ShowHexNum(1,3,ArrayWrite[0],4);
            OLED_ShowHexNum(1,8,ArrayWrite[1],4);
        }
        ArrayRead[0] = BKP_ReadBackupRegister(BKP_DR1);
        ArrayRead[1] = BKP_ReadBackupRegister(BKP_DR2);
        
         OLED_ShowHexNum(2,3,ArrayRead[0],4);
         OLED_ShowHexNum(2,8,ArrayRead[1],4);
	}
	
}
实时时钟

MyRTC.c

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include "time.h"

uint16_t MyRTC_Time[] = {2024,2,16,16,44,55};

void MyRTC_SetTime(void);

/**
  * @brief  初始化RTC
  * @param  无
  * @retval 无
  */
void MyRTC_Init(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
    
    PWR_BackupAccessCmd(ENABLE);
    
    if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
        //判断系统是否完全断电(没有标志位说明完全断电过,则进行重新初始化)
    {
         RCC_LSEConfig(RCC_LSE_ON);//打开外部低速时钟
    
    while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET);//等待LSE启动完成
    
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//选择RTCCLK时钟源
    
    RCC_RTCCLKCmd(ENABLE);//使能时钟
    
    RTC_WaitForSynchro();//等待时钟同步
    RTC_WaitForLastTask();//等待上次操作完成(进行写入操作后都进行一次等待)
    
    RTC_SetPrescaler(32768 - 1);//配置预分频器(对32768Hz分频)分频出来为1Hz即1s
    //对PRL,CNT,ALR寄存器写入前都需要配置CNF位,这里库函数已经进行封装过了
    RTC_WaitForLastTask();//等待上次操作完成(进行写入操作后都进行一次等待)
    
//    RTC_SetCounter(1672588795);//从哪个数开始计时(起始数目)
//    RTC_WaitForLastTask();//等待上次操作完成(进行写入操作后都进行一次等待)
    
    MyRTC_SetTime();
        
     BKP_WriteBackupRegister(BKP_DR1,0xA5A5);//写入标志位
   }
   else
    {
        //则不会进行重新初始化
        RTC_WaitForSynchro();//等待时钟同步
        RTC_WaitForLastTask();//等待上次操作完成(进行写入操作后都进行一次等待)
    }
   
}

/**
  * @brief  设定RTC时间
  * @param  无
  * @retval 无
  */
void MyRTC_SetTime(void)
{
    time_t time_cnt;
    struct tm time_date;
    
    time_date.tm_year = MyRTC_Time[0] - 1900;//从1900开始计数
    time_date.tm_mon = MyRTC_Time[1] - 1;//从0开始计数
    time_date.tm_mday = MyRTC_Time[2];
    time_date.tm_hour = MyRTC_Time[3];
    time_date.tm_min = MyRTC_Time[4];
    time_date.tm_sec = MyRTC_Time[5];
    
    time_cnt = mktime(&time_date);//将日期时间转换为秒数
    
    RTC_SetCounter(time_cnt);//从哪个数开始计时(起始数目)
    RTC_WaitForLastTask();//等待上次操作完成(进行写入操作后都进行一次等待)
    //将所得秒数转移到CNT作为起始数据
}

/**
  * @brief  读取RTC时间
  * @param  无
  * @retval 无
  */
void MyRTC_ReadTime(void)
{
    time_t time_cnt;
    struct tm time_date;
    
    time_cnt = RTC_GetCounter();
    time_date = *(localtime(&time_cnt));
    
    MyRTC_Time[0] = time_date.tm_year + 1900;//从1900开始计数
    MyRTC_Time[1] = time_date.tm_mon + 1;//从0开始计数
    MyRTC_Time[2] = time_date.tm_mday;
    MyRTC_Time[3] = time_date.tm_hour;
    MyRTC_Time[4] = time_date.tm_min;
    MyRTC_Time[5] = time_date.tm_sec;
}

PWR

如果要修改主频则在system_stm32f10x.c进行修改,将#define SYSCLK_FREQ_72MHz 72000000进行注释,将你所需要的频率解注释即可。

修改主频

main.c

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"

uint8_t KeyNum;

int main(void)
{
	OLED_Init();
	
    OLED_ShowString(1,1,"SYSCLK");
    OLED_ShowNum(1,8,SystemCoreClock,8);
    
    
	while(1)
	{
		OLED_ShowString(2,1,"Running");
        Delay_ms(500);
        OLED_ShowString(2,1,"        ");
        Delay_ms(500);
	}
	
}

将72M主频改为36M实验现象为Delay函数的延时翻倍

睡眠模式

使用之前写的串口发送+接收。

当加上 __WFI(); 这句指令后,程序进入睡眠模式,并通过中断唤醒

main.c

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"

uint8_t RxData;

int main(void)
{
	OLED_Init();
    
    OLED_ShowString(1,1,"RxData:");
    
	Serial_Init();
    
	while(1)    
	{
        
        //中断方式接收
        if(Serial_GetRxFlag() == 1)
        {
            RxData = Serial_GetRxData();
            OLED_ShowHexNum(1,8,RxData,2);
            Serial_SendByte(RxData);//数据回传
            
        }
        OLED_ShowString(2,1,"Running");
        Delay_ms(100);
         OLED_ShowString(2,1,"       ");
        Delay_ms(100);
        
        __WFI();//使用中断唤醒(睡眠模式) 
	}
	
}

这时当没有数据收发时,字符不会显示,只有收发数据时,才会闪烁一次

停止(低功耗)模式

使用之前红外对射计次程序。因为其不需要内部晶振,故能使用低功耗模式

main.c

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"

uint8_t KeyNum;

int main(void)
{
	OLED_Init();
	CountSensor_Init();
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//先开启PWR时钟
	
	OLED_ShowString(1,1,"Count:");
	
	
	while(1)
	{
		OLED_ShowNum(1,7,CountSensor_Get(),5);
        //如果外部一直没有中断信号,那么这个get就是没有意义的耗电操作
        
        OLED_ShowString(2,1,"Running");
        Delay_ms(100);
        OLED_ShowString(2,1,"       ");
        Delay_ms(100);
        
        PWR_EnterSTOPMode(PWR_Regulator_ON,PWR_STOPEntry_WFI);//进入停止模式
        SystemInit();
        //由于退出停止模式会进入HSI(8M)故会变慢,此时重新Init恢复72M主频
    }
	
}
待机模式

这里使用的是实时时钟程序。待机模式下,LSE不会断电。

main.c

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyRTC.h"

uint8_t KeyNum;

int main(void)
{
	OLED_Init();
	MyRTC_Init();
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
    
    OLED_ShowString(1,1,"CNT:");
    OLED_ShowString(2,1,"ALR:");
    OLED_ShowString(3,1,"ALRF:");
    
    PWR_WakeUpPinCmd(ENABLE);//wakeup功能,不需要进行引脚初始化
    //将PA^0接高电平即可唤醒
    
    uint32_t Alarm = RTC_GetCounter() + 10;
    //设定闹钟为当前计数十秒后,由于不能直接读出,使用中间变量完成
    RTC_SetAlarm(Alarm);
    OLED_ShowNum(2,6,Alarm,10);//显示闹钟响了的时间
    
	while(1)
	{
        OLED_ShowNum(1,6,RTC_GetCounter(),10);
        OLED_ShowNum(3,6,RTC_GetFlagStatus(RTC_FLAG_ALR),1);//显示闹钟标志位
        
        OLED_ShowString(4,1,"Running");
        Delay_ms(100);
        OLED_ShowString(4,1,"       ");
        Delay_ms(100);
         OLED_ShowString(4,9,"STANDBY");
        Delay_ms(1000);
        OLED_ShowString(4,9,"       ");
        Delay_ms(1000);
        
        OLED_Clear();
        
        PWR_EnterSTANDBYMode();//进入待机模式
    }
	
}
相关推荐
善 .3 小时前
单片机的内存是指RAM还是ROM
单片机·嵌入式硬件
超级码农ProMax3 小时前
STM32——“SPI Flash”
stm32·单片机·嵌入式硬件
Asa3194 小时前
stm32点灯Hal库
stm32·单片机·嵌入式硬件
end_SJ5 小时前
初学stm32 --- 外部中断
stm32·单片机·嵌入式硬件
gantengsheng6 小时前
基于51单片机和OLED12864的小游戏《贪吃蛇》
单片机·嵌入式硬件·游戏·51单片机
嵌入式小强工作室7 小时前
stm32 查找进硬件错误方法
stm32·单片机·嵌入式硬件
委员8 小时前
基于NodeMCU的物联网窗帘控制系统设计
单片机·mcu·物联网·智能家居·iot
wenchm8 小时前
细说STM32F407单片机DMA方式读写SPI FLASH W25Q16BV
stm32·单片机·嵌入式硬件
南城花随雪。8 小时前
单片机:实现自动关机电路(附带源码)
单片机·嵌入式硬件
逝灮8 小时前
【蓝桥杯——物联网设计与开发】拓展模块4 - 脉冲模块
stm32·单片机·嵌入式硬件·mcu·物联网·蓝桥杯·脉冲测量