stm32之備份寄存器(BKP)應用(侵入檢測中斷)

原文鏈接:https://blog.csdn.net/weixin_42653531/article/details/99744158

版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/weixin_42653531/article/details/99744158
前言:很多的嵌入式設備使用過程中,當系統掉電時,往往需要把一些用戶設置的參數保存起來,或者是將掉電前的一些狀態信息保存,或者是統計系統重啓次數。保存這些動態信息其實有很多種方法,第一種:在系統掉電前保存到片內flash,但是對flash的讀寫是按頁操作,對於保存一些少量的數據來說並不合算。第二種:在系統掉電前保存在片外的EEPROM,可以根據需要選用合適的EEPROM存儲的大小,但這樣需要增加額外電路,增加成本。第三種:利用片內的備份寄存器裏的後備數據寄存器存儲。對於一些中、小型容量產品來說,有10個16位的數據後備寄存器。與前兩種不同,它需要將引腳接上電池,否則數據會丟失。下面對備份寄存器深入瞭解。

1.備份寄存器的特性
     ● 20字節數據後備寄存器(中容量和小容量產品),或84字節數據後備寄存器(大容量和互聯型產品)

     ● 用來管理防侵入檢測並具有中斷功能的狀態/控制寄存器

     ● 用來存儲RTC校驗值的校驗寄存器。

     ● 在PC13引腳(當該引腳不用於侵入檢測時)上輸出RTC校準時鐘,RTC鬧鐘脈衝或者秒脈衝

備份寄存器在後備供電區域裏,當電源被切斷,他們仍然由維持供電。當系統在待機模式下被喚醒,或系統復位或電源復位時,他們也不會被複位。下面主要介紹入侵檢測和數據後備寄存器的應用,關於RTC部分單獨一篇介紹。備份寄存器之所以與RTC有關,是因爲RTC在電源切斷後也是需要保持計數。

2.侵入檢測功能
當TAMPER引腳(即PC.13)上的信號從0變成1或者從1變成0(取決於備份控制寄存器BKP_CR的TPAL位),會產生一個侵入檢測事件(即使切斷)。侵入檢測事件將所有數據備份寄存器內容清除。

然而爲了避免丟失侵入事件,侵入檢測信號是邊沿檢測的信號與侵入檢測允許位的邏輯與,從而在侵入檢測引腳被允許前發生的侵入事件也可以被檢測到。

● 當TPAL=0時(高電平有效):如果在啓動侵入檢測TAMPER引腳前(通過設置TPE位)該引腳已經爲高電平,一旦啓動侵入檢測功能,則會產生一個額外的侵入事件(儘管在TPE位置’1’後並沒有出現上升沿)。

● 當TPAL=1時(低電平有效):如果在啓動侵入檢測引腳TAMPER前(通過設置TPE位)該引腳已經爲低電平,一旦啓動侵入檢測功能,則會產生一個額外的侵入事件(儘管在TPE位置’1’後並沒有出現下降沿)。

注意:對TAMPER引腳的檢測,可以是邊沿觸發(上升沿、下降沿),也可以是電平觸發,後者需要啓用中斷配合,下面會講解。產生侵入事件會將備份寄存器復位,產生事件的同時也可以通過軟件使能中斷,進入一個侵入檢測中斷TAMPER_IRQHandler。當然中斷不使能,事件仍然會發生。

3.代碼設計
涉及到的寄存器不逐一介紹,下面通過標準庫裏的函數進行開發。如果需要直接操作寄存器可以打開相應庫函數的定義,函數裏面也是執行寄存器的操作,將其內容複製出來即可。

#include "stm32f10x.h"
#include "stdio.h"
 
 
void TAMPER_ITConfig(void);
static void NVIC_Configuration(void);
static void USART1_Config(void);
 
int main(void)
{    
    unsigned short i;
    char ch;
    
        USART1_Config();//串口1輸出調試信息
        NVIC_Configuration();//配置串口接收中斷的優先級
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能電源管理單元的時鐘
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);
    PWR_BackupAccessCmd(ENABLE);//使能後備寄存器訪問
    
        BKP_TamperPinCmd(DISABLE);     //先關閉侵入檢測引腳
        BKP_ITConfig(DISABLE);      //關閉侵入中斷
        BKP_TamperPinLevelConfig(BKP_TamperPinLevel_Low);    //設置檢測引腳低電平有效
        BKP_ClearFlag();    //清除侵入檢測事件
        TAMPER_ITConfig();//配置中斷優先級並打開侵入中斷,不需要進入中斷可以註釋掉這句,並不影響侵入事件的發生
        BKP_TamperPinCmd(ENABLE);//開啓侵入檢測引腳
    
#if 0 //調試方法一
    printf("上電讀取BKP數據:\r\n");
    for(i=0x0004;i<=0x0028;i+=4){    // baseaddr:0x0004~0x0028  共10個16位的數據後備寄存器 
        printf("%c ",BKP_ReadBackupRegister(i));
    }
    printf("\r\n");
    
    printf("往BKP寫入數據:\r\n");
    ch='a';
    for(i=0x0004;i<=0x0028;i+=4){ 
        BKP_WriteBackupRegister(i,ch++);
        printf("%c ",BKP_ReadBackupRegister(i));
    }
    printf("\r\n");    
#else //調試方法二
    i=BKP_ReadBackupRegister(BKP_DR1);
    printf("上電次數%d \r\n",i);
    i++;
    BKP_WriteBackupRegister(BKP_DR1,i);
#endif
    while(1)
    {
        
  }
}
 
void TAMPER_ITConfig(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);//初始化侵入中斷的優先級
    BKP_ITConfig(ENABLE);//使能侵入中斷
}
 
void USART1_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    
    //配置串口1(USART1)時鐘
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
    
       //配置串口1(USART1 Tx (PA.09))
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
  
    //配置串口1 USART1 Rx (PA.10)
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    //串口1模式(USART1 mode)配置 
    USART_InitStructure.USART_BaudRate = 9600;//一般設置爲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_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啓中斷
    
    USART_Cmd(USART1, ENABLE); //使能串口 
    USART_ClearFlag(USART1,USART_FLAG_TC);
}
 
int fputc(int ch, FILE *f)//重寫標準庫的fputc函數
{
    //將Printf內容發往串口
    USART_SendData(USART1, (unsigned char) ch);
    while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);    
    return (ch);
}
 
static void NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);            
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;    
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;        
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;     
    NVIC_Init(&NVIC_InitStructure);
}
在stm32f10x_it.c文件加入:

void TAMPER_IRQHandler(void)
{
    if(BKP_GetITStatus()!=RESET){
        printf("觸發侵入中斷\r\n");
    BKP_ClearITPendingBit();//清除侵入檢測中斷
    BKP_ClearFlag();//清除侵入檢測事件
            
    //如果將下面兩句執行,那麼就變成電平觸發,導致的現象:若PC.13引腳保持有效電平,則系統會反覆進入中斷
         //BKP_TamperPinCmd(DISABLE);
         //BKP_TamperPinCmd(ENABLE);
    }
}
首先需要準備兩個獨立的電源,將板子的和PC.13(侵入檢測引腳)接到一個電源(因爲我的板子沒有電池),將接到另一個電源,並且將兩個電源共地。並串口1接到電腦,利用電腦上位機顯示調試打印信息。

其次,編譯下載程序,打開串口助手,按下板子的復位鍵(我這裏按了四次),也可以切斷再上電反覆四次,如下圖:

可看出,不管系統復位還是掉電,上電次數得到了記錄。下面將PC.13引腳從高電平且換到低電平(產生一個侵入信號),再進行系統復位或重新上電(我這裏按了兩次復位):

可看出,侵入事件發生後,備份寄存器裏的數據被複位。當掉電時,PC.13引腳仍然在檢測,若出現下降沿,備份寄存器也會進行復位,這個可以自行驗證。還有上面提到的電平觸發,也可以自行驗證。我自己驗證過,這裏不做贅述。

 

 

 

<<書中有路勤爲徑,學海無涯苦作舟。———韓愈>>
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章