STM32单片机_4(入门完结篇)
·
第十三章PWR电源控制






1修改主频
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);
}
}
只要在时钟文件里面修改主频就可以了
2睡眠模式+串口
uint8_t Data;
int main(void)
{
OLED_Init();
Serial_Init();
OLED_ShowString(1, 1, "RxData:");
while (1)
{
if(Serial_GetFlag()==1)
{
Data = Serial_GetRxData();
Serial_SendByte(Data);
//标志位硬件置0, 不需要我们动
OLED_ShowHexNum(1, 8, Data, 2);
}
OLED_ShowString(2, 1, "Running");
Delay_ms(500);
OLED_ShowString(2, 1, " ");
Delay_ms(500);
__WFI();//中断唤醒
}
}
每一次来一个中断, 先执行中断, 然后whle循环重新开始执行一次, 再次进入睡眠
3停止模式+红外计次
应为这里用的是外部中断, 外部中断不需要内部的时钟, 可以满足停止模式的要求
int main(void)
{
OLED_Init();
CountSensor_Init();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
OLED_ShowString(1,1,"count:");
while (1)
{
OLED_ShowNum(1, 7, CountSensor_Get(), 5);
OLED_ShowString(2, 1, "Running");
Delay_ms(500);
OLED_ShowString(2, 1, " ");
Delay_ms(500);
PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
SystemInit();//停止模式之后主频变为8KM, 这时候我重新设置主频为72
}
}
使用停止模式和待机模式都要开启PWR的时钟, 因为需要用到PWR外设的操作
4实时时钟+待机模式
待机模式退出的时候程序从头开始执行, 而且使用待机模式的时候都是为了极度省电, 所以在待机模式之前可以把能关的都关了
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);//而且不需要GPIO初始化
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(100);
OLED_Clear();
PWR_EnterSTANDBYMode();
}
}
第十四章看门狗
独立看门狗


计数器减到0的时候就会触发复位
所以就要在减到0之前就要去喂狗 
代码展示
main.c
uint8_t KeyNum;
int main(void)
{
OLED_Init();
Key_Init();
OLED_ShowString(1, 1, "IWDG TEST");
//判断复位是谁产生的
if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST)==SET)
{
RCC_ClearFlag();
OLED_ShowString(2, 1, "IWDGRST");
Delay_ms(500);
OLED_ShowString(2, 1, " ");
Delay_ms(500);
}
else
{
OLED_ShowString(3, 1, "RST");
Delay_ms(500);
OLED_ShowString(3, 1, " ");
Delay_ms(500);
}
//1开启LSI时钟, 自动开启
//2解除写保护
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
//配置预分频, 从装值
IWDG_SetPrescaler(IWDG_Prescaler_16);
IWDG_SetReload(2499);//1000ms
IWDG_ReloadCounter();//先喂一次狗, 这样第一次的时间就是1000ms
IWDG_Enable();
while (1)
{
Key_GetNum();//一直按着就会阻塞
IWDG_ReloadCounter();
OLED_ShowString(4, 1, "FEED");
Delay_ms(200);
OLED_ShowString(4, 1, " ");
Delay_ms(600);
}
}
窗口看门狗

上面的CFR寄存器就是最早时间喂狗的实现 


代码展示:
main.c
uint8_t KeyNum;
int main(void)
{
OLED_Init();
Key_Init();
OLED_ShowString(1, 1, "WWDG TEST");
//判断复位是谁产生的
if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST)==SET)
{
RCC_ClearFlag();
OLED_ShowString(2, 1, "WWDGRST");
Delay_ms(500);
OLED_ShowString(2, 1, " ");
Delay_ms(500);
}
else
{
OLED_ShowString(3, 1, "RST");
Delay_ms(500);
OLED_ShowString(3, 1, " ");
Delay_ms(500);
}
//开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
//配置寄存器, 计算超时时间和窗口时间
WWDG_SetPrescaler(WWDG_Prescaler_8);
WWDG_SetWindowValue(21 | 0x40);//30ms
WWDG_Enable(54 | 0x40);//同时要设置T6位 50ms 这里相当于一次喂狗
while (1)
{
Key_GetNum();//一直按着就会阻塞
OLED_ShowString(4, 1, "FEED");
Delay_ms(20);
OLED_ShowString(4, 1, " ");
Delay_ms(20);
WWDG_SetCounter(54 | 0x40);
}
}
第十五章FLASH闪存











这是一个用芯片闪存的弊端

因为SRAM是掉电丢失的, 而FLASH掉电不丢失, 这样我们就可以将SRAM的数据在掉电之前转移到FLASH里面, 然后上电的时候就可以先去恢复数据 
这个地方可以修改程序的分配空间, 可以改小一点, 最后几页可以留给自己用 , 而且其实位置也可以去修改
代码展示:
My_FLASH.c : 底层代码 -> 就是读, 擦除, 写的三个基本功能
其实库里面都是封装好了, 我们只是去调用相应的函数
#include "stm32f10x.h" // Device header
//读
uint32_t MyFLASH_ReadWord(uint32_t Address)
{
return *((__IO uint32_t *)(Address));
}
uint16_t MyFLASH_ReadHalfWord(uint32_t Address)
{
return *((__IO uint16_t *)(Address));
}
uint8_t MyFLASH_ReadByte(uint32_t Address)
{
return *((__IO uint8_t *)(Address));
}
//擦除
void MyFLASH_ErasePages(void)
{
FLASH_Unlock();
FLASH_EraseAllPages();
FLASH_Lock();
}
void MyFLASH_ErasePage(uint32_t PageAddress)
{
FLASH_Unlock();
FLASH_ErasePage(PageAddress);
FLASH_Lock();
}
//写入
void MyFLASH_ProgramWord(uint32_t Address, uint32_t Data)
{
FLASH_Unlock();
FLASH_ProgramWord(Address, Data);
FLASH_Lock();
}
void MyFLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
{
FLASH_Unlock();
FLASH_ProgramHalfWord(Address, Data);
FLASH_Lock();
}
Store.c
这里面就是实现数据从SRAM保存到FLASH里面, 从而掉电不丢失,(因为操作SRAM很方便)
#include "stm32f10x.h" // Device header
#include "MyFLASH.h"
#define STORE_START_ADDRESS 0x0800FC00
#define COUNT 512
uint16_t Store_Data[COUNT];
void Store_Init(void)
{
if(MyFLASH_ReadHalfWord(STORE_START_ADDRESS)!=0xA5A5)
{
MyFLASH_ErasePage(STORE_START_ADDRESS);
MyFLASH_ProgramHalfWord(STORE_START_ADDRESS, 0xA5A5);
for(uint16_t i = 1;i<COUNT;i++)
{
MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i*2 , 0x0000);//这是写了两个字节所以i*2
}
}
//上电就把数据恢复到SRAM
for(uint16_t i = 0;i<COUNT;i++)
{
Store_Data[i] = MyFLASH_ReadHalfWord(STORE_START_ADDRESS + i*2);
}
}
void Store_Save(void)
{
MyFLASH_ErasePage(STORE_START_ADDRESS);
for(uint16_t i = 0;i<COUNT;i++)
{
MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i*2 , Store_Data[i]);
}
}
void Store_Clear(void)
{
for(uint16_t i = 1;i<COUNT;i++)
{
Store_Data[i] = 0x0000;
}
Store_Save();
}
读取电子签名

代码展示
uint8_t KeyNum;
int main(void)
{
OLED_Init();
OLED_ShowString(1, 1, "F_SIZE:");
OLED_ShowHexNum(1, 8, *((__IO uint16_t *)(0x1FFFF7E0)), 4);
OLED_ShowString(2, 1, "U_ID:");
OLED_ShowHexNum(2, 6, *((__IO uint16_t *)(0x1FFFF7E8)), 4);
OLED_ShowHexNum(2, 11, *((__IO uint16_t *)(0x1FFFF7E8 + 0x02)), 4);
OLED_ShowHexNum(3, 1, *((__IO uint32_t *)(0x1FFFF7E8 + 0x04)), 8);
OLED_ShowHexNum(4, 1, *((__IO uint32_t *)(0x1FFFF7E8 + 0x08)), 8);
while (1)
{
}
其实就是练习一下用地址去读取寄存器
在此STM32入门完结
更多推荐



所有评论(0)