关闭

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

376人阅读 评论(0) 收藏 举报
分类:
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
#include <stm32f10x_lib.h>	
#include "system.h"
#include "usart.h" 	
#include "bkp.h" 

#define LED1 PAout(4)
#define LED2 PAout(5)

void Gpio_Init(void);

int main(void)
{				  
	u16 data,i=10;

	Rcc_Init(9); 			 			  //系统时钟设置

	Usart1_Init(72,9600);

	Bkp_Init();

	Tamper_Init();

	Nvic_Init(0,0,TAMPER_IRQChannel,0);	  //设置中断
   	
	Gpio_Init();

	while(i){

		Write_Bkp(i,i);

		data = Read_Bkp(i);
	   	
		printf("\n DR%u = 0x%04X\n",i,data);

		delay(30000);   //延时30ms

		i--;
									  
	}
	
	while(1);		
}


void Gpio_Init(void)
{
	RCC->APB2ENR|=1<<2;    //使能PORTA时钟 	

	GPIOA->CRL&=0x0000FFFF; // PA0~3设置为浮空输入,PA4~7设置为推挽输出
	GPIOA->CRL|=0x33334444; 

	
	//USART1 串口I/O设置

	GPIOA -> CRH&=0xFFFFF00F;   //设置USART1 的Tx(PA.9)为第二功能推挽,50MHz;Rx(PA.10)为浮空输入
	GPIOA -> CRH|=0x000008B0;	  
}
User/stm32f103x_it.c
#include "stm32f10x_it.h"
#include "system.h"
#include "stdio.h"

#define LED1 PAout(4)
#define LED2 PAout(5)
#define LED3 PAout(6)
#define LED4 PAout(7)

extern u16 Read_Bkp(u8 reg);

void TAMPER_IRQHandler(void)
{
	u16 i=10,data;

	LED4 =1 ;

	printf("\r\n A Tamper is coming .\r\n");

	while(i){

		data = Read_Bkp(i);
	   	
		printf("\n DR%u = 0x%04X\n",i,data);

		delay(30000);   //延时30ms

		i--;
									  
	}

	BKP->CSR |= 3<<0;	//清除事件中断标志位

}
Library/src/bkp.c
#include <stm32f10x_lib.h>
#include "bkp.h"

void Bkp_Init(void)
{
	RCC->APB1RSTR |= 1<<27;		//复位BKP寄存器
	RCC->APB1RSTR &= ~(1<<27);

	RCC->APB1ENR|=1<<28;     //使能电源时钟	    
	RCC->APB1ENR|=1<<27;     //使能BKP时钟	  
}


/**
 *  
 *后备寄存器写入操作
 *reg:寄存器编号
 *data:要写入的数值 
 *
 **/
void Write_Bkp(u8 reg,u16 data)
{  

	PWR->CR|=1<<8;           //取消备份区写保护 

	switch(reg)
	{
		case 1:
			BKP->DR1=data;
			break;
		case 2:
			BKP->DR2=data;
			break;
		case 3:
			BKP->DR3=data;
			break; 
		case 4:
			BKP->DR4=data;
			break;
		case 5:
			BKP->DR5=data;
			break;
		case 6:
			BKP->DR6=data;
			break;
		case 7:
			BKP->DR7=data;
			break;
		case 8:
			BKP->DR8=data;
			break;
		case 9:
			BKP->DR9=data;
			break;
		case 10:
			BKP->DR10=data;
			break;
	} 
}


u16 Read_Bkp(u8 reg)
{ 
	u16 data;

	switch(reg)
	{
		case 1:
			data = BKP->DR1;
			break;
		case 2:
			data = BKP->DR2;
			break;
		case 3:
			data = BKP->DR3;
			break; 
		case 4:
			data = BKP->DR4;
			break;
		case 5:
			data = BKP->DR5;
			break;
		case 6:
			data = BKP->DR6;
			break;
		case 7:
			data = BKP->DR7;
			break;
		case 8:
			data = BKP->DR8;
			break;
		case 9:
			data = BKP->DR9;
			break;
		case 10:
			data = BKP->DR10;
			break;
	} 

	return data;
}

//开启入侵检测,检测引脚为GPIOC13 但是不用打开其时钟和设置引脚模式
void Tamper_Init()
{

    BKP->CSR |= 3<<0;			//清除事件中断标志位

	BKP->CR  |= 1<<1;			//设定为入侵电平为低电平
	BKP->CSR |= 1<<2;			//允许入侵中断

	BKP->CR  |= 1<<0;			//开启入侵检测


}
Library/inc/bkp.h
#include <stm32f10x_lib.h>

void Bkp_Init(void);

void Write_Bkp(u8 reg,u16 data);

u16 Read_Bkp(u8 reg);

void Tamper_Init(void);
 
库函数操作
 
main.c
#include "stm32f10x.h"
#include "stdio.h"


#define	 PRINTF_ON  1
#define  CHECK_CODE  0xAE86


void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void USART_Configuration(void);
void BKP_Configuration(void);

void PrintBKP(void);
void WriteBKP(u16 Data,u8 DRNumber);
u8	 CheckBKP(void);

int main(void)
{
  	RCC_Configuration();
  	GPIO_Configuration();
	NVIC_Configuration();
	USART_Configuration();
	BKP_Configuration();
	


	if(CheckBKP())
	{
		printf("\r\n The datas are as their initial status. \r\n");
		WriteBKP(0xA522,2);
		PrintBKP();
	}else{
		printf("\r\n The datas have been changed . \r\n");
		WriteBKP(0xA53C,1);
		PrintBKP();
	}  
	while(1);
}




  
void GPIO_Configuration(void)
{
  	GPIO_InitTypeDef GPIO_InitStructure;
	
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;			
  	GPIO_Init(GPIOA , &GPIO_InitStructure); 

  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;			
  	GPIO_Init(GPIOA , &GPIO_InitStructure); 
}

void BKP_Configuration(void)
{
	PWR_BackupAccessCmd(ENABLE);
	BKP_ClearFlag();
	BKP_TamperPinLevelConfig(BKP_TamperPinLevel_Low);
	BKP_ITConfig(ENABLE);
	BKP_TamperPinCmd(ENABLE);
}


void RCC_Configuration(void)
{
	/* 定义枚举类型变量 HSEStartUpStatus */
	ErrorStatus HSEStartUpStatus;

  	/* 复位系统时钟设置*/
  	RCC_DeInit();
  	/* 开启HSE*/
  	RCC_HSEConfig(RCC_HSE_ON);
  	/* 等待HSE起振并稳定*/
  	HSEStartUpStatus = RCC_WaitForHSEStartUp();
	/* 判断HSE起是否振成功,是则进入if()内部 */
  	if(HSEStartUpStatus == SUCCESS)
  	{
    	/* 选择HCLK(AHB)时钟源为SYSCLK 1分频 */
    	RCC_HCLKConfig(RCC_SYSCLK_Div1); 
    	/* 选择PCLK2时钟源为 HCLK(AHB) 1分频 */
    	RCC_PCLK2Config(RCC_HCLK_Div1); 
    	/* 选择PCLK1时钟源为 HCLK(AHB) 2分频 */
    	RCC_PCLK1Config(RCC_HCLK_Div2);
    	/* 设置FLASH延时周期数为2 */
    	FLASH_SetLatency(FLASH_Latency_2);
    	/* 使能FLASH预取缓存 */
    	FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
    	/* 选择锁相环(PLL)时钟源为HSE 1分频,倍频数为9,则PLL输出频率为 8MHz * 9 = 72MHz */
    	RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
    	/* 使能PLL */ 
    	RCC_PLLCmd(ENABLE);
    	/* 等待PLL输出稳定 */
    	while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
    	/* 选择SYSCLK时钟源为PLL */
    	RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    	/* 等待PLL成为SYSCLK时钟源 */
    	while(RCC_GetSYSCLKSource() != 0x08);
  	} 
  	/* 打开APB2总线上的GPIOA时钟*/
  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP, ENABLE);
		
}

 
void USART_Configuration(void)
{
	USART_InitTypeDef USART_InitStructure;
	USART_ClockInitTypeDef USART_ClockInitStructure;

	USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
	USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
	USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;                                                                                                                                                      
	USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
	USART_ClockInit(USART1 , &USART_ClockInitStructure);

	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
	USART_Init(USART1,&USART_InitStructure);

 	USART_Cmd(USART1,ENABLE);
}


void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;

	NVIC_InitStructure.NVIC_IRQChannel = TAMPER_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

}

void WriteBKP(u16 Data,u8 DRNumber)		  // 还可加入一些加密算法;DRNumber (1-9)
{
	switch(DRNumber)
	{	
		case 0x01: BKP_WriteBackupRegister(BKP_DR1,Data); break;
		case 0x02: BKP_WriteBackupRegister(BKP_DR2,Data); break;
		case 0x03: BKP_WriteBackupRegister(BKP_DR3,Data); break;
		case 0x04: BKP_WriteBackupRegister(BKP_DR4,Data); break;
		case 0x05: BKP_WriteBackupRegister(BKP_DR5,Data); break;
		case 0x06: BKP_WriteBackupRegister(BKP_DR6,Data); break;
		case 0x07: BKP_WriteBackupRegister(BKP_DR7,Data); break;
		case 0x08: BKP_WriteBackupRegister(BKP_DR8,Data); break;
		case 0x09: BKP_WriteBackupRegister(BKP_DR9,Data); break;
		default:    BKP_WriteBackupRegister(BKP_DR1,Data); 
	}
	BKP_WriteBackupRegister(BKP_DR10,CHECK_CODE); 
}

u8 CheckBKP(void)
{
	if( BKP_ReadBackupRegister(BKP_DR10) == 0xAE86 )   // 如果此位数据丢失,则BPK数据丢失
		return 1;
	else
		return 0;
}

void PrintBKP(void)
{
	printf("DR1 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR1));
	printf("DR2 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR2));
	printf("DR3 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR3));
	printf("DR4 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR4));
	printf("DR5 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR5));
	printf("DR6 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR6));
	printf("DR7 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR7));
	printf("DR8 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR8));
	printf("DR9 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR9));
	printf("DR10 = 0x%04X\t",BKP_ReadBackupRegister(BKP_DR10));

}


#if	 PRINTF_ON

int fputc(int ch,FILE *f)
{
	USART_SendData(USART1,(u8) ch);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
	return ch;
}

#endif
 
stm12f10x_it.c
#include "stm32f10x_it.h"

#include "stdio.h"

extern void PrintBKP(void);

void TAMPER_IRQHandler(void)
{
	printf("\r\n A Tamper is coming .\r\n");
	PrintBKP();
	BKP_ClearITPendingBit();
	BKP_ClearFlag();

}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    最新评论
    个人资料
    • 访问:40810次
    • 积分:136
    • 等级:
    • 排名:千里之外
    • 原创:5篇
    • 转载:110篇
    • 译文:1篇
    • 评论:2条