Chinaunix首页 | 论坛 | 博客
  • 博客访问: 224807
  • 博文数量: 52
  • 博客积分: 15
  • 博客等级: 民兵
  • 技术积分: 390
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-06 09:31
文章分类

全部博文(52)

文章存档

2015年(1)

2014年(44)

2013年(7)

我的朋友

分类: 嵌入式

2014-05-30 09:37:00

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 等相关代码参照 )
User/main.c
01 #include    
02 #include "system.h"
03 #include "usart.h" 
04 #include "bkp.h"
05  
06 #define LED1 PAout(4)
07 #define LED2 PAout(5)
08  
09 void Gpio_Init(void);
10  
11 int 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  
45 void 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  
10 extern u16 Read_Bkp(u8 reg);
11  
12 void 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
002 #include "bkp.h"
003  
004 void 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  **/
021 void 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  
062 u16 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 但是不用打开其时钟和设置引脚模式
104 void 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
2  
3 void Bkp_Init(void);
4  
5 void Write_Bkp(u8 reg,u16 data);
6  
7 u16 Read_Bkp(u8 reg);
8  
9 void 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  
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);
014  
015 void PrintBKP(void);
016 void WriteBKP(u16 Data,u8 DRNumber);
017 u8   CheckBKP(void);
018  
019 int 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    
046 void 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  
060 void 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  
070 void 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   
113 void 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  
136 void 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  
148 void 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  
166 u8 CheckBKP(void)
167 {
168     if( BKP_ReadBackupRegister(BKP_DR10) == 0xAE86 )   // 如果此位数据丢失,则BPK数据丢失
169         return 1;
170     else
171         return 0;
172 }
173  
174 void 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  
192 int 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  
05 extern void PrintBKP(void);
06  
07 void TAMPER_IRQHandler(void)
08 {
09     printf("\r\n A Tamper is coming .\r\n");
10     PrintBKP();
11     BKP_ClearITPendingBit();
12     BKP_ClearFlag();
13  
14 }
阅读(2477) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~