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();//进入待机模式
}
}