关闭

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

469人阅读 评论(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
查看评论

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

BKP是“BACKUP”的缩写,stm32f103RCTE的内部配备了10个16位宽度的BKP寄存器。在主电源切断或系统产生复位时间时,BKP寄存器仍然可以在备用电源的支持下保持其内容。  BKP在实际应用中可以存入重要数据,防止被恶意查看,或用于断电回复等。   本例实现...
  • hao95165
  • hao95165
  • 2014-08-14 11:14
  • 1355

STM32 下的库函数和寄存器操作比较

以 led闪烁中的flashLed函数例子:库函数操作简单,但是效率不如寄存器操作的高; 寄存器操作很复杂,因为要熟悉上百个寄存器,但是程序效率很高/**下面是通过直接操作库函数的方式实现IO控制**/ while(1) { GPIO_ResetBits(GPIOB,GPIO_Pin_9...
  • mao0514
  • mao0514
  • 2015-08-15 11:10
  • 4518

stm32点个灯[操作寄存器+库函数]

stm32的使用和51单片机不同,单片机接上晶振接上电源 直接就可以操作io口,但是stm32的时钟是 经过了倍频器放大频率的,然后再由锁相环输出稳定的时钟频率。 这么做的带来了很多好处,虽然stm32的外部时钟只有8Mhz ,经过倍频器后就可以得到好几种的时钟频率 给不同的外设提供不同的时钟频率。...
  • qutiezhu
  • qutiezhu
  • 2016-08-30 21:12
  • 653

STM32---初学者用库函数好还是直接对寄存器操作比较好

首先,两个都是C语言。 从51过渡过来的话,就先说寄存器操作。每个MCU都有自己的寄存器,51是功能比较简单的一种,相应的寄存器也比较少,我们常用的就那么几个,像P0 P1 SMOD TMOD之类的,这些存在于标准头文件reg.h里面,因为少,所以大家就直接这么去操作了,每一位对应的意义随便翻一下手...
  • u010349006
  • u010349006
  • 2014-12-03 11:18
  • 2629

stm32 USART 串口通信[操作寄存器+库函数]

串口通信虽然在如今的电脑上使用的越来越少,因为其在通信速率,距离已经不适应pc的要求,取而代之的是USB口。但是在嵌入式领域,USART仍然广泛运用着。    stm32的最多可以提供5路串口,有分数波特率发生器、支持同步单线通信和半双工单线通信、具有DMA等。使用USART...
  • minyuanxiani
  • minyuanxiani
  • 2014-03-18 16:21
  • 4330

STM32之BKP后备域库函数介绍

1.BKP_DeInit函数的功能是将外设BKP的全部寄存器重设为默认值。 2.BKP_TamperPinLevelConfig函数的功能是设置侵入检测引脚的有效电平。 .BKP_TamperPinLevel可取的值有.BKP_TamperPinLevel_High/_Low.分别是检测高低电平...
  • Cherish511842885
  • Cherish511842885
  • 2016-10-12 21:11
  • 1956

STM32寄存器操作简单介绍

STM32单片机可以使用库函数进行操作,再加上现在越来越强大的MDK ARM编译环境,使用库函数开发简直是不二的选择,但是工具越来越强大的同时意味着对编程人员降低了要求,在很大程度上降低了准入门槛,我们因此高兴吗?我倒是觉得这很像温水煮青蛙,所以库函数固然好用却也不应该抛弃最初的做法——寄存器操作。...
  • spu20134823091
  • spu20134823091
  • 2016-09-03 18:43
  • 2925

STM32寄存器操作和库函数操作区别

STM32寄存器操作和库函数操作区别 2016-03-05 00:10:11 分享: 标签: STM32 库函数 寄存器 结构体 /*********************** 结构体操作点亮LED ********************************/ &...
  • qq_35893742
  • qq_35893742
  • 2017-07-09 17:21
  • 521

STM32——GPIO之从库函数到寄存器的前因后果

例子为单片机的“Hello World”级的流水灯实验——虽然只有一个,其中并不是将完整的代码给出,只是给出关键部分来说明“如何调用ST公司的的库来完成对硬件的控制,以及对库文件代码进行跟踪和分析至寄存器级”。所以从第一段代码往下看就可以了,要用到的函数和变量大部分会说明,至于寄存器级的,那就只能翻...
  • mao0514
  • mao0514
  • 2015-08-15 16:52
  • 1687

stm32 独立看门狗[操作寄存器+库函数]

以单片机为核心的微型计算机系统中,单片机经常会受到来自外界电磁场的干扰。 造成程序跑飞,只是程序的正常运行状态被打断而进入死循环,从而使单片机控制的系统无法正常工作。看门狗就是一种专门用于检测单片机程序运行状态的硬件结构。   stm32也是如此。   stm32 的独...
  • minyuanxiani
  • minyuanxiani
  • 2014-03-18 16:10
  • 1091
    最新评论
    个人资料
    • 访问:71568次
    • 积分:217
    • 等级:
    • 排名:千里之外
    • 原创:6篇
    • 转载:111篇
    • 译文:1篇
    • 评论:3条