stm32 BKP寄存器操作[操作寄存器+库函数]

来源:互联网 发布:第四次人口普查数据 编辑:程序博客网 时间:2024/04/30 08:07
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):
 
BKP_CSR.png

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 等相关代码参照 stm32 直接操作寄存器开发环境配置)
User/main.c
01#include <stm32f10x_lib.h>   
02#include "system.h"
03#include "usart.h" 
04#include "bkp.h"
05 
06#define LED1 PAout(4)
07#define LED2 PAout(5)
08 
09void Gpio_Init(void);
10 
11int main(void)
12{                
13    u16 data,i=10;
14 
15    Rcc_Init(9);                          //系统时钟设置
16 
17    Usart1_Init(72,9600);
18 
19    Bkp_Init();
20 
21    Tamper_Init();
22 
23    Nvic_Init(0,0,TAMPER_IRQChannel,0);   //设置中断
24     
25    Gpio_Init();
26 
27    while(i){
28 
29        Write_Bkp(i,i);
30 
31        data = Read_Bkp(i);
32         
33        printf("\n DR%u = 0x%04X\n",i,data);
34 
35        delay(30000);   //延时30ms
36 
37        i--;
38                                       
39    }
40     
41    while(1);      
42}
43 
44 
45void Gpio_Init(void)
46{
47    RCC->APB2ENR|=1<<2;    //使能PORTA时钟    
48 
49    GPIOA->CRL&=0x0000FFFF; // PA0~3设置为浮空输入,PA4~7设置为推挽输出
50    GPIOA->CRL|=0x33334444;
51 
52     
53    //USART1 串口I/O设置
54 
55    GPIOA -> CRH&=0xFFFFF00F;   //设置USART1 的Tx(PA.9)为第二功能推挽,50MHz;Rx(PA.10)为浮空输入
56    GPIOA -> CRH|=0x000008B0;     
57}
User/stm32f103x_it.c
01#include "stm32f10x_it.h"
02#include "system.h"
03#include "stdio.h"
04 
05#define LED1 PAout(4)
06#define LED2 PAout(5)
07#define LED3 PAout(6)
08#define LED4 PAout(7)
09 
10extern u16 Read_Bkp(u8 reg);
11 
12void TAMPER_IRQHandler(void)
13{
14    u16 i=10,data;
15 
16    LED4 =1 ;
17 
18    printf("\r\n A Tamper is coming .\r\n");
19 
20    while(i){
21 
22        data = Read_Bkp(i);
23         
24        printf("\n DR%u = 0x%04X\n",i,data);
25 
26        delay(30000);   //延时30ms
27 
28        i--;
29                                       
30    }
31 
32    BKP->CSR |= 3<<0;  //清除事件中断标志位
33 
34}
Library/src/bkp.c
001#include <stm32f10x_lib.h>
002#include "bkp.h"
003 
004void Bkp_Init(void)
005{
006    RCC->APB1RSTR |= 1<<27;        //复位BKP寄存器
007    RCC->APB1RSTR &= ~(1<<27);
008 
009    RCC->APB1ENR|=1<<28;     //使能电源时钟     
010    RCC->APB1ENR|=1<<27;     //使能BKP时钟  
011}
012 
013 
014/**
015 
016 *后备寄存器写入操作
017 *reg:寄存器编号
018 *data:要写入的数值
019 *
020 **/
021void Write_Bkp(u8 reg,u16 data)
022
023 
024    PWR->CR|=1<<8;           //取消备份区写保护
025 
026    switch(reg)
027    {
028        case 1:
029            BKP->DR1=data;
030            break;
031        case 2:
032            BKP->DR2=data;
033            break;
034        case 3:
035            BKP->DR3=data;
036            break;
037        case 4:
038            BKP->DR4=data;
039            break;
040        case 5:
041            BKP->DR5=data;
042            break;
043        case 6:
044            BKP->DR6=data;
045            break;
046        case 7:
047            BKP->DR7=data;
048            break;
049        case 8:
050            BKP->DR8=data;
051            break;
052        case 9:
053            BKP->DR9=data;
054            break;
055        case 10:
056            BKP->DR10=data;
057            break;
058    }
059}
060 
061 
062u16 Read_Bkp(u8 reg)
063{
064    u16 data;
065 
066    switch(reg)
067    {
068        case 1:
069            data = BKP->DR1;
070            break;
071        case 2:
072            data = BKP->DR2;
073            break;
074        case 3:
075            data = BKP->DR3;
076            break;
077        case 4:
078            data = BKP->DR4;
079            break;
080        case 5:
081            data = BKP->DR5;
082            break;
083        case 6:
084            data = BKP->DR6;
085            break;
086        case 7:
087            data = BKP->DR7;
088            break;
089        case 8:
090            data = BKP->DR8;
091            break;
092        case 9:
093            data = BKP->DR9;
094            break;
095        case 10:
096            data = BKP->DR10;
097            break;
098    }
099 
100    return data;
101}
102 
103//开启入侵检测,检测引脚为GPIOC13 但是不用打开其时钟和设置引脚模式
104void Tamper_Init()
105{
106 
107    BKP->CSR |= 3<<0;          //清除事件中断标志位
108 
109    BKP->CR  |= 1<<1;          //设定为入侵电平为低电平
110    BKP->CSR |= 1<<2;          //允许入侵中断
111 
112    BKP->CR  |= 1<<0;          //开启入侵检测
113 
114 
115}
Library/inc/bkp.h
1#include <stm32f10x_lib.h>
2 
3void Bkp_Init(void);
4 
5void Write_Bkp(u8 reg,u16 data);
6 
7u16 Read_Bkp(u8 reg);
8 
9void Tamper_Init(void);
 
库函数操作
 
main.c
001#include "stm32f10x.h"
002#include "stdio.h"
003 
004 
005#define  PRINTF_ON  1
006#define  CHECK_CODE  0xAE86
007 
008 
009void RCC_Configuration(void);
010void GPIO_Configuration(void);
011void NVIC_Configuration(void);
012void USART_Configuration(void);
013void BKP_Configuration(void);
014 
015void PrintBKP(void);
016void WriteBKP(u16 Data,u8 DRNumber);
017u8   CheckBKP(void);
018 
019int main(void)
020{
021    RCC_Configuration();
022    GPIO_Configuration();
023    NVIC_Configuration();
024    USART_Configuration();
025    BKP_Configuration();
026     
027 
028 
029    if(CheckBKP())
030    {
031        printf("\r\n The datas are as their initial status. \r\n");
032        WriteBKP(0xA522,2);
033        PrintBKP();
034    }else{
035        printf("\r\n The datas have been changed . \r\n");
036        WriteBKP(0xA53C,1);
037        PrintBKP();
038    
039    while(1);
040}
041 
042 
043 
044 
045   
046void GPIO_Configuration(void)
047{
048    GPIO_InitTypeDef GPIO_InitStructure;
049     
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);
054 
055    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
056    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;          
057    GPIO_Init(GPIOA , &GPIO_InitStructure);
058}
059 
060void BKP_Configuration(void)
061{
062    PWR_BackupAccessCmd(ENABLE);
063    BKP_ClearFlag();
064    BKP_TamperPinLevelConfig(BKP_TamperPinLevel_Low);
065    BKP_ITConfig(ENABLE);
066    BKP_TamperPinCmd(ENABLE);
067}
068 
069 
070void RCC_Configuration(void)
071{
072    /* 定义枚举类型变量 HSEStartUpStatus */
073    ErrorStatus HSEStartUpStatus;
074 
075    /* 复位系统时钟设置*/
076    RCC_DeInit();
077    /* 开启HSE*/
078    RCC_HSEConfig(RCC_HSE_ON);
079    /* 等待HSE起振并稳定*/
080    HSEStartUpStatus = RCC_WaitForHSEStartUp();
081    /* 判断HSE起是否振成功,是则进入if()内部 */
082    if(HSEStartUpStatus == SUCCESS)
083    {
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);
090        /* 设置FLASH延时周期数为2 */
091        FLASH_SetLatency(FLASH_Latency_2);
092        /* 使能FLASH预取缓存 */
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);
096        /* 使能PLL */
097        RCC_PLLCmd(ENABLE);
098        /* 等待PLL输出稳定 */
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);
104    }
105    /* 打开APB2总线上的GPIOA时钟*/
106    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);
107 
108    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP, ENABLE);
109         
110}
111 
112  
113void USART_Configuration(void)
114{
115    USART_InitTypeDef USART_InitStructure;
116    USART_ClockInitTypeDef USART_ClockInitStructure;
117 
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);
123 
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);
131 
132    USART_Cmd(USART1,ENABLE);
133}
134 
135 
136void NVIC_Configuration(void)
137{
138    NVIC_InitTypeDef NVIC_InitStructure;
139 
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);
145 
146}
147 
148void WriteBKP(u16 Data,u8 DRNumber)       // 还可加入一些加密算法;DRNumber (1-9)
149{
150    switch(DRNumber)
151    {  
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);
162    }
163    BKP_WriteBackupRegister(BKP_DR10,CHECK_CODE);
164}
165 
166u8 CheckBKP(void)
167{
168    if( BKP_ReadBackupRegister(BKP_DR10) == 0xAE86 )   // 如果此位数据丢失,则BPK数据丢失
169        return 1;
170    else
171        return 0;
172}
173 
174void PrintBKP(void)
175{
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));
186 
187}
188 
189 
190#if  PRINTF_ON
191 
192int fputc(int ch,FILE *f)
193{
194    USART_SendData(USART1,(u8) ch);
195    while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
196    return ch;
197}
198 
199#endif
 
stm12f10x_it.c
01#include "stm32f10x_it.h"
02 
03#include "stdio.h"
04 
05extern void PrintBKP(void);
06 
07void TAMPER_IRQHandler(void)
08{
09    printf("\r\n A Tamper is coming .\r\n");
10    PrintBKP();
11    BKP_ClearITPendingBit();
12    BKP_ClearFlag();
13 
14}
0 0
原创粉丝点击