Unix时间戳
BKP
读写备份寄存器
main.c
#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
#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
#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
#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
#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
#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();//进入待机模式}}