久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術學習與研究
當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

stm32 獨立看門狗[操作寄存器+庫函數]

作者:佚名   來源:本站原創   點擊數:  更新時間:2013年06月12日   【字體:

以單片機為核心的微型計算機系統中,單片機經常會受到來自外界電磁場的干擾。
造成程序跑飛,只是程序的正常運行狀態被打斷而進入死循環,從而使單片機控制的系統無法正常工作。看門狗就是一種專門用于檢測單片機程序運行狀態的硬件結構。
 
stm32也是如此。
 
stm32 的獨立看門狗由內部專門的40Khz低速時鐘驅動,即使主時鐘發生故障時,它也仍然有效。這里需要注意的是獨立看門狗的時鐘是一個內部時鐘,所以不是準確的40Khz,而是在30~60Khz之間的一個可變化的時鐘,看門狗的時鐘對時間的要求不是很精確,所以時鐘有偏差可以接受。
 
本例直接操作寄存器實現驗證獨立看門狗的復位功能,設定一個800ms的喂狗時間,在主函數中實現LED閃爍,如果設定一個1s的延時,則觸發獨立看門狗復位,LED常亮。
庫函數實現當外部中斷發生(按下PA0按鍵),長時間不喂狗,引發獨立看門狗復位時,向外用串口輸出復位提示。
 
 
直接操作寄存器
 
使用獨立看門狗,需要了解一下寄存器:
 
鍵值寄存器:(IWDG_KR)
低16位有效的寄存器,只寫寄存器,讀出值恒為0x0000.
軟件必須以一定的間隔寫入0xAAAA,否則,當計數器為0時,看門狗會產生復位。
寫入0x5555表示允許訪問IWDG_PR和IWDG_RLR寄存器。
寫入0xCCCC,啟動看門狗工作。
 
預分頻寄存器:(IWDG_PR)
第三位有效寄存器,用于設置看門狗的分頻系數,最低為4,最高位256.
通過設置PR[2:0]:位來選擇計數器時鐘的預分頻因子。要改變預分頻因子,IWDG_SR寄存器的PVU位必須為0。

    000: 預分頻因子=4                 100: 預分頻因子=64
    001: 預分頻因子=8                 101: 預分頻因子=128
    010: 預分頻因子=16               110: 預分頻因子=256
    011: 預分頻因子=32               111: 預分頻因子=256

重裝載寄存器:(IWDG_RLR)
低12位有效,RL[11:0]。用于定義看門狗計數器的重裝載值。
每當向IWDG_KR寄存器寫入0xAAAA時,重裝載值會被傳送到計數器中。隨后計數器從這個值開始遞減計數。看門狗超時周期可通過此重裝載值和時鐘預分頻值來計算。 只有當IWDG_SR寄存器中的RVU位為0時,才能對此寄存器進行修改。
 
狀態寄存器:(IWDG_SR)
只有低兩位有效。都由硬件置’1’和 清’0’。
RVU[1]: 看門狗計數器重裝載值更新
PVU[0]: 看門狗預分頻值更新
 
代碼如下:  (system.h 和 stm32f10x_it.h 等相關代碼參照 stm32 直接操作寄存器開發環境配置)
User/main.c
01  #include <stm32f10x_lib.h>   
02  #include "system.h"
03  #include "wdg.h"  
04  
05  #define LED1 PAout(4)
06  #define LED2 PAout(5)
07  
08  void Gpio_Init(void);
09  
10  int main(void)
11  {               
12  
13      Rcc_Init(9);             //系統時鐘設置
14  
15      Gpio_Init();
16  
17      Iwdg_Init(3,1000);  //設定為800ms內喂狗
18  
19      while(1){
20          
21          LED1 = !LED1;
22  
23          delay(100000);    //延時100ms后喂狗,LED閃爍
24  
25          //delay(1000000);     //延時1000ms,引發獨立看門狗復位,LED不閃爍
26  
27          Iwdg_Feed();  //喂狗
28  
29      }     
30  
31  }
32  
33  
34  void Gpio_Init(void)
35  {
36      RCC->APB2ENR|=1<<2;    //使能PORTA時鐘             
37  
38      GPIOA->CRL&=0x0000FFFF; // PA0~3設置為浮空輸入,PA4~7設置為推挽輸出
39      GPIOA->CRL|=0x33334444;
40    
41  }
Library/wdg.c   (此文件包含了獨立看門狗和窗口看門狗的驅動函數)
01  #include <stm32f10x_lib.h>
02  #include "wdg.h"
03  
04  /********************************************
05   *
06   *本文件包含窗口看門狗和獨立看門口的相關函數
07   *
08   *********************************************/
09  
10  u8 Wwdg_Cnt = 0x7F;  //計數器值,默認為最大值127
11  
12  //獨立看門狗初始化
13  //參數說明:
14  //          pre:分頻數(0~7),相應分頻因子為4*(2^pre)
15  //          rlr:低12位有[11:0]
16  // 喂狗時間計算: T =  (4*(2^pre)*rlr)/40;(ms)       
17  void Iwdg_Init(u8 pre,u16 rlr)
18  {
19      IWDG ->KR = 0x5555;      //使能對PR RLR寄存器的寫操作
20      IWDG ->PR = pre;     //設置分頻數
21      IWDG ->RLR = rlr;        //設定重裝值
22      IWDG ->KR =  0xAAAA;    //裝載RLR值到看門狗計數器,即喂狗
23      IWDG ->KR =  0xCCCC;    //啟動看門狗
24  }
25  
26  //獨立看門狗喂狗
27  void Iwdg_Feed()
28  {
29      IWDG -> KR = 0xAAAA;  //喂狗
30  }
31  
32  //窗口看門狗初始化
33  //參數說明:
34  //          cnt     計數器的值,最大 127,0x7F
35  //          w_cnt   窗口值,最大 127,0x7F
36  //          pre     預分頻器的時基值,低兩位有效;實際時鐘為: PLCK1/4096/2^pre
37  //需要再主函數中開啟中斷 WWDG_IRQChannel
38  //設定喂狗時間范圍必須在:(WWDG時鐘為PCLK1,36Mhz)
39  //          Tmax =(4096*2^pre*(cnt-63)/36)  (us)
40  //          Tmin =(4096*2^pre*(cnt-w_cnt)/36)   (us)
41  //超出次時間喂狗復位
42  
43  void Wwdg_Init(u8 cnt,u8 w_cnt,u8 pre)
44  {
45      u8 Cnt_Max = 0x7f;    //計數器最大值
46  
47      Wwdg_Cnt = Cnt_Max&cnt;   //設定計數器的值,防止溢出
48  
49      RCC->APB1ENR |= 1<<11;
50  
51      WWDG -> CFR |= pre <<7;  //設定預分頻器的時基,實際分頻值我
52      WWDG -> CFR |= 1<<9;    //使能中斷
53  
54      WWDG -> CFR &= 0xFF80;   //初始化低七位,即窗口值清0
55      WWDG -> CFR |= w_cnt;    // 設定窗口值
56  
57      WWDG -> CR  |= Wwdg_Cnt|(1<<7);  //設定計數器值,并激活開門狗
58  
59  }
60  
61  //窗口看門狗喂狗
62  
63  void Wwdg_Feed()
64  {
65      WWDG->CR |= (Wwdg_Cnt&0x7F);
66      
67  }
Library/wdg.h
1  #include <stm32f10x_lib.h>
2  
3  void Iwdg_Init(u8 pre,u16 rlr);
4  void Iwdg_Feed(void);
5  
6  void Wwdg_Init(u8 cnt,u8 w_cnt,u8);
7  void Wwdg_Feed(void);
 
需要注意的是 獨立看門狗沒有響應的中斷。
 
庫函數操作
 
main.c
view source
print?
001  #include "stm32f10x.h"
002  #include "stdio.h"
003  
004  #define  PRINTF_ON  1
005  
006  void RCC_Configuration(void);
007  void GPIO_Configuration(void);
008  void NVIC_Configuration(void);
009  void USART_Configuration(void);
010  void IWDG_Configuration(void);
011  void EXTI_Configuration(void);
012  
013  vu32 DelayTime;
014  
015  int main(void)
016  {
017      RCC_Configuration();
018      GPIO_Configuration();
019      NVIC_Configuration();
020      USART_Configuration();
021      EXTI_Configuration();
022      IWDG_Configuration();
023  
024      while(1){ 
025          if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET)
026          {
027              printf("\r\n The Stm32 has been reset by IWDG .\r\n");
028              RCC_ClearFlag();
029          }
030  
031          //do sth. here
032          DelayTime = 100000;
033          while(--DelayTime);       
034          // 延時17ms
035                  
036          IWDG_ReloadCounter();   //80ms不喂狗復位
037          GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)(1- GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_4)));
038      } 
039  }
040  
041  void EXTI_Configuration(void)
042  {
043      EXTI_InitTypeDef EXTI_InitStructure;
044  
045      EXTI_InitStructure.EXTI_Line = EXTI_Line0;
046      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
047      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
048      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
049      EXTI_Init(&EXTI_InitStructure);
050  
051      GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
052  
053  }
054  
055  void GPIO_Configuration(void)
056  {
057      GPIO_InitTypeDef GPIO_InitStructure;                                                                                   
058      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
059      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
060      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;         
061      GPIO_Init(GPIOA , &GPIO_InitStructure);
062      
063      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
064      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          
065      GPIO_Init(GPIOA , &GPIO_InitStructure);    
066  
067  
068      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
069      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;       
070      GPIO_Init(GPIOA , &GPIO_InitStructure);
071      
072      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
073      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;         
074      GPIO_Init(GPIOA , &GPIO_InitStructure);
075  
076  }
077  
078  void IWDG_Configuration(void)
079  {
080      RCC_LSICmd(ENABLE);                              //打開LSI
081      while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)==RESET);
082  
083      IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
084      IWDG_SetPrescaler(IWDG_Prescaler_32);
085      IWDG_SetReload(100);      //80ms ,max 0xFFF  0~4095
086      IWDG_ReloadCounter();
087      IWDG_Enable();
088  }
089  
090  
091  void RCC_Configuration(void)
092  {
093      /* 定義枚舉類型變量 HSEStartUpStatus */
094      ErrorStatus HSEStartUpStatus;
095  
096      /* 復位系統時鐘設置*/
097      RCC_DeInit();
098      /* 開啟HSE*/
099      RCC_HSEConfig(RCC_HSE_ON);
100      /* 等待HSE起振并穩定*/
101      HSEStartUpStatus = RCC_WaitForHSEStartUp();
102      /* 判斷HSE起是否振成功,是則進入if()內部 */
103      if(HSEStartUpStatus == SUCCESS)
104      {
105          /* 選擇HCLK(AHB)時鐘源為SYSCLK 1分頻 */
106          RCC_HCLKConfig(RCC_SYSCLK_Div1);
107          /* 選擇PCLK2時鐘源為 HCLK(AHB) 1分頻 */
108          RCC_PCLK2Config(RCC_HCLK_Div1);
109          /* 選擇PCLK1時鐘源為 HCLK(AHB) 2分頻 */
110          RCC_PCLK1Config(RCC_HCLK_Div2);
111          /* 設置FLASH延時周期數為2 */
112          FLASH_SetLatency(FLASH_Latency_2);
113          /* 使能FLASH預取緩存 */
114          FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
115          /* 選擇鎖相環(PLL)時鐘源為HSE 1分頻,倍頻數為9,則PLL輸出頻率為 8MHz * 9 = 72MHz */
116          RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
117          /* 使能PLL */
118          RCC_PLLCmd(ENABLE);
119          /* 等待PLL輸出穩定 */
120          while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
121          /* 選擇SYSCLK時鐘源為PLL */
122          RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
123          /* 等待PLL成為SYSCLK時鐘源 */
124          while(RCC_GetSYSCLKSource() != 0x08);
125      }
126      /* 打開APB2總線上的GPIOA時鐘*/
127      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);
128  
129      //RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP|RCC_APB1Periph_WWDG, ENABLE);
130          
131  }
132  
133   
134  void USART_Configuration(void)
135  {
136      USART_InitTypeDef USART_InitStructure;
137      USART_ClockInitTypeDef USART_ClockInitStructure;
138  
139      USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
140      USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
141      USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;                                                                                                                                                    
142      USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
143      USART_ClockInit(USART1 , &USART_ClockInitStructure);
144  
145      USART_InitStructure.USART_BaudRate = 9600;
146      USART_InitStructure.USART_WordLength = USART_WordLength_8b;
147      USART_InitStructure.USART_StopBits = USART_StopBits_1;
148      USART_InitStructure.USART_Parity = USART_Parity_No;
149      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
150      USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
151      USART_Init(USART1,&USART_InitStructure);
152  
153      USART_Cmd(USART1,ENABLE);
154  }
155  
156  
157  void NVIC_Configuration(void)
158  {
159      NVIC_InitTypeDef NVIC_InitStructure;
160  
161  
162      NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
163      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
164      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
165      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
166      NVIC_Init(&NVIC_InitStructure);
167  
168  
169  }
170  
171  
172  #if  PRINTF_ON
173  
174  int fputc(int ch,FILE *f)
175  {
176      USART_SendData(USART1,(u8) ch);
177      while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
178      return ch;
179  }
180  
181  #endif

關閉窗口

相關文章

主站蜘蛛池模板: 亚洲视频网 | 97精品国产97久久久久久免费 | 伊人网综合在线观看 | 国产午夜精品一区二区三区四区 | 国产在线中文字幕 | 在线免费观看成人 | 青久草视频 | 精品国产一区二区三区日日嗨 | 国产一区二区精品在线观看 | 日韩精品久久久久久 | 成人免费观看男女羞羞视频 | 在线视频中文字幕 | 久久久精| 欧美午夜剧场 | 国产亚洲精品精品国产亚洲综合 | 九九热这里 | 一区二区成人 | 狠狠做六月爱婷婷综合aⅴ 国产精品视频网 | 国产一级片免费在线观看 | 精品国产三级 | 综合色播 | 国产精品a久久久久 | 国产最新精品视频 | 欧美h视频 | 久久黄色| av一二三区 | 亚洲国产一区二区三区四区 | 欧美性受xxxx | 成人在线免费观看av | 古装人性做爰av网站 | 少妇精品亚洲一区二区成人 | 亚洲免费婷婷 | 久久99精品久久 | 欧美aaa一级片 | 日本一道本视频 | 久久一久久 | 欧美在线视频一区二区 | 国产成人精品久久二区二区91 | 日韩一区二区三区在线看 | 日韩一区中文字幕 | heyzo在线 |