BKP是“BACKUP”的缩写,stm32f103RCTE的内部配备了10个16位宽度的BKP寄存器。在主电源切断或系统产生复位时间时,BKP寄存器仍然可以在备用电源的支持下保持其内容。
BKP在实际应用中可以存入重要数据,防止被恶意查看,或用于断电回复等。
本例实现对BKP寄存器的读写操作,和入侵检测和处理。主程序中写入寄存器后,依次打印出10个BKP寄存器数据,然后触发GPIOC13的入侵中断(输入低电平),在中断中打印出入侵事件发生后的寄存器内容(复位为0 )。
直接操作寄存器
用到的寄存器描述如下:
备份数据寄存器x(BKP_DRx) (x = 1 … 10):低16位[15:0]有效,用来写入或读出备份数据。
备份控制寄存器(BKP_CR):
低两位有效。
TPAL[1]:侵入检测TAMPER引脚有效电平(TAMPER pin active level)
-
0:侵入检测TAMPER引脚上的高电平会清除所有数据备份寄存器(如果TPE位为1)
-
1:侵入检测TAMPER引脚上的低电平会清除所有数据备份寄存器(如果TPE位为1)
TPE[0]:启动侵入检测TAMPER引脚(TAMPER pin enable)
-
0:侵入检测TAMPER引脚作为通用IO口使用
-
1:开启侵入检测引脚作为侵入检测使用
备份控制/状态寄存器(BKP_CSR):
TIF[9]:侵入中断标志(Tamper interrupt flag) 0:无侵入中断 1:产生侵入中断
当检测到有侵入事件且TPIE位为1时,此位由硬件置1。
通过向CTI位写1来清除此标志位(同时也清除了中断)。如果TPIE位被清除,则此位也会被清除。
TEF[8]:侵入事件标志(Tamper event flag) 0:无侵入事件 1:检测到侵入事件
当检测到侵入事件时此位由硬件置1。通过向CTE位写1可清除此标志位
TPIE[2]:允许侵入TAMPER引脚中断(TAMPER pin interrupt enable)
0:禁止侵入检测中断 1:允许侵入检测中断(BKP_CR寄存器的TPE位也必须被置1)
注1:侵入中断无法将系统内核从低功耗模式唤醒。 注2:仅当系统复位或由待机模式唤醒后才复位该位。
CTI[1]:清除侵入检测中断(Clear tamper interrupt)
0:无效 1:清除侵入检测中断和TIF侵入检测中断标志
CTE[0]:清除侵入检测事件(Clear tamper event)
0:无效 1:清除TEF侵入检测事件标志(并复位侵入检测器)。
要写入BKP寄存器数据必须在 PWR->CR中取消备份区写保护,才可以写入BKP数据。stm32开启入侵检测也不需要设置GPIOC的时钟和输入输出模式。
代码如下:(system.h 和 stm32f10x_it.h 等相关代码参照 )
User/main.c
23
|
Nvic_Init(0,0,TAMPER_IRQChannel,0); //设置中断
|
33
|
printf("\n DR%u = 0x%04X\n",i,data);
|
35
|
delay(30000); //延时30ms
|
47
|
RCC->APB2ENR|=1<<2; //使能PORTA时钟
|
49
|
GPIOA->CRL&=0x0000FFFF; // PA0~3设置为浮空输入,PA4~7设置为推挽输出
|
50
|
GPIOA->CRL|=0x33334444;
|
55
|
GPIOA -> CRH&=0xFFFFF00F; //设置USART1 的Tx(PA.9)为第二功能推挽,50MHz;Rx(PA.10)为浮空输入
|
56
|
GPIOA -> CRH|=0x000008B0;
|
User/stm32f103x_it.c
01
|
#include "stm32f10x_it.h"
|
10
|
extern u16 Read_Bkp(u8 reg);
|
12
|
void TAMPER_IRQHandler(void)
|
18
|
printf("\r\n A Tamper is coming .\r\n");
|
24
|
printf("\n DR%u = 0x%04X\n",i,data);
|
26
|
delay(30000); //延时30ms
|
32
|
BKP->CSR |= 3<<0; //清除事件中断标志位
|
Library/src/bkp.c
006
|
RCC->APB1RSTR |= 1<<27; //复位BKP寄存器
|
007
|
RCC->APB1RSTR &= ~(1<<27);
|
009
|
RCC->APB1ENR|=1<<28; //使能电源时钟
|
010
|
RCC->APB1ENR|=1<<27; //使能BKP时钟
|
021
|
void Write_Bkp(u8 reg,u16 data)
|
024
|
PWR->CR|=1<<8; //取消备份区写保护
|
103
|
//开启入侵检测,检测引脚为GPIOC13 但是不用打开其时钟和设置引脚模式
|
107
|
BKP->CSR |= 3<<0; //清除事件中断标志位
|
109
|
BKP->CR |= 1<<1; //设定为入侵电平为低电平
|
110
|
BKP->CSR |= 1<<2; //允许入侵中断
|
112
|
BKP->CR |= 1<<0; //开启入侵检测
|
Library/inc/bkp.h
5
|
void Write_Bkp(u8 reg,u16 data);
|
9
|
void Tamper_Init(void);
|
库函数操作
main.c
001
|
#include "stm32f10x.h"
|
006
|
#define CHECK_CODE 0xAE86
|
009
|
void RCC_Configuration(void);
|
010
|
void GPIO_Configuration(void);
|
011
|
void NVIC_Configuration(void);
|
012
|
void USART_Configuration(void);
|
013
|
void BKP_Configuration(void);
|
016
|
void WriteBKP(u16 Data,u8 DRNumber);
|
022
|
GPIO_Configuration();
|
023
|
NVIC_Configuration();
|
024
|
USART_Configuration();
|
031
|
printf("\r\n The datas are as their initial status. \r\n");
|
035
|
printf("\r\n The datas have been changed . \r\n");
|
046
|
void GPIO_Configuration(void)
|
048
|
GPIO_InitTypeDef GPIO_InitStructure;
|
050
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
|
051
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
052
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
053
|
GPIO_Init(GPIOA , &GPIO_InitStructure);
|
055
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
|
056
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
057
|
GPIO_Init(GPIOA , &GPIO_InitStructure);
|
060
|
void BKP_Configuration(void)
|
062
|
PWR_BackupAccessCmd(ENABLE);
|
064
|
BKP_TamperPinLevelConfig(BKP_TamperPinLevel_Low);
|
065
|
BKP_ITConfig(ENABLE);
|
066
|
BKP_TamperPinCmd(ENABLE);
|
070
|
void RCC_Configuration(void)
|
072
|
/* 定义枚举类型变量 HSEStartUpStatus */
|
073
|
ErrorStatus HSEStartUpStatus;
|
078
|
RCC_HSEConfig(RCC_HSE_ON);
|
080
|
HSEStartUpStatus = RCC_WaitForHSEStartUp();
|
081
|
/* 判断HSE起是否振成功,是则进入if()内部 */
|
082
|
if(HSEStartUpStatus == SUCCESS)
|
084
|
/* 选择HCLK(AHB)时钟源为SYSCLK 1分频 */
|
085
|
RCC_HCLKConfig(RCC_SYSCLK_Div1);
|
086
|
/* 选择PCLK2时钟源为 HCLK(AHB) 1分频 */
|
087
|
RCC_PCLK2Config(RCC_HCLK_Div1);
|
088
|
/* 选择PCLK1时钟源为 HCLK(AHB) 2分频 */
|
089
|
RCC_PCLK1Config(RCC_HCLK_Div2);
|
091
|
FLASH_SetLatency(FLASH_Latency_2);
|
093
|
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
|
094
|
/* 选择锁相环(PLL)时钟源为HSE 1分频,倍频数为9,则PLL输出频率为 8MHz * 9 = 72MHz */
|
095
|
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
|
099
|
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
|
100
|
/* 选择SYSCLK时钟源为PLL */
|
101
|
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
|
102
|
/* 等待PLL成为SYSCLK时钟源 */
|
103
|
while(RCC_GetSYSCLKSource() != 0x08);
|
105
|
/* 打开APB2总线上的GPIOA时钟*/
|
106
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);
|
108
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP, ENABLE);
|
113
|
void USART_Configuration(void)
|
115
|
USART_InitTypeDef USART_InitStructure;
|
116
|
USART_ClockInitTypeDef USART_ClockInitStructure;
|
118
|
USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
|
119
|
USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
|
120
|
USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
|
121
|
USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
|
122
|
USART_ClockInit(USART1 , &USART_ClockInitStructure);
|
124
|
USART_InitStructure.USART_BaudRate = 9600;
|
125
|
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
126
|
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
127
|
USART_InitStructure.USART_Parity = USART_Parity_No;
|
128
|
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
129
|
USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
|
130
|
USART_Init(USART1,&USART_InitStructure);
|
132
|
USART_Cmd(USART1,ENABLE);
|
136
|
void NVIC_Configuration(void)
|
138
|
NVIC_InitTypeDef NVIC_InitStructure;
|
140
|
NVIC_InitStructure.NVIC_IRQChannel = TAMPER_IRQn;
|
141
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
142
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
143
|
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
144
|
NVIC_Init(&NVIC_InitStructure);
|
148
|
void WriteBKP(u16 Data,u8 DRNumber) // 还可加入一些加密算法;DRNumber (1-9)
|
152
|
case 0x01: BKP_WriteBackupRegister(BKP_DR1,Data); break;
|
153
|
case 0x02: BKP_WriteBackupRegister(BKP_DR2,Data); break;
|
154
|
case 0x03: BKP_WriteBackupRegister(BKP_DR3,Data); break;
|
155
|
case 0x04: BKP_WriteBackupRegister(BKP_DR4,Data); break;
|
156
|
case 0x05: BKP_WriteBackupRegister(BKP_DR5,Data); break;
|
157
|
case 0x06: BKP_WriteBackupRegister(BKP_DR6,Data); break;
|
158
|
case 0x07: BKP_WriteBackupRegister(BKP_DR7,Data); break;
|
159
|
case 0x08: BKP_WriteBackupRegister(BKP_DR8,Data); break;
|
160
|
case 0x09: BKP_WriteBackupRegister(BKP_DR9,Data); break;
|
161
|
default: BKP_WriteBackupRegister(BKP_DR1,Data);
|
163
|
BKP_WriteBackupRegister(BKP_DR10,CHECK_CODE);
|
168
|
if( BKP_ReadBackupRegister(BKP_DR10) == 0xAE86 ) // 如果此位数据丢失,则BPK数据丢失
|
176
|
printf("DR1 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR1));
|
177
|
printf("DR2 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR2));
|
178
|
printf("DR3 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR3));
|
179
|
printf("DR4 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR4));
|
180
|
printf("DR5 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR5));
|
181
|
printf("DR6 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR6));
|
182
|
printf("DR7 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR7));
|
183
|
printf("DR8 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR8));
|
184
|
printf("DR9 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR9));
|
185
|
printf("DR10 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR10));
|
192
|
int fputc(int ch,FILE *f)
|
194
|
USART_SendData(USART1,(u8) ch);
|
195
|
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
|
stm12f10x_it.c
01
|
#include "stm32f10x_it.h"
|
05
|
extern void PrintBKP(void);
|
07
|
void TAMPER_IRQHandler(void)
|
09
|
printf("\r\n A Tamper is coming .\r\n");
|
11
|
BKP_ClearITPendingBit();
|
阅读(2477) | 评论(0) | 转发(0) |