看门狗定时器的用途是在软件出问题时执行系统复位功能,这可以防止系统无限期地挂起。除此之外,看门狗定时器还支持将CPU 从掉电模式唤醒的功能。看门狗定时器包含一个18 位的自由运行计数器,定时溢出间隔可编程。

特征

 18-位自由运行WDT 计数器用于看门狗定时器超时间隔。
 可选择的超时间隔 (2^4 ~ 2^18),超时间隔为104 ms ~ 26.316 s (如果WDT_CLK = 10 kHz)。
 复位周期 = (1 / 10 kHz) * 63,如果WDT_CLK = 10 kHz

对应的寄存器是这个

  1. #define WDT_BASE (APB1PERIPH_BASE + 0x04000) ///< WDT register base address
  2.  
  3. #define APB1PERIPH_BASE ((uint32_t)0x40000000) ///< APB1 base address
  4.  
  5. #define CLK_APBCLK_WDT_EN_Pos (0) /*!< CLK_T::APBCLK: WDT_EN Position */
  6. #define CLK_APBCLK_WDT_EN_Msk (0x1ul << CLK_APBCLK_WDT_EN_Pos) /*!< CLK_T::APBCLK: WDT_EN Mask
  1. typedef struct {
  2.  
  3. /**
  4. * PWRCTL
  5. * ===================================================================================================
  6. * Offset: 0x00 System Power Down Control Register
  7. * ---------------------------------------------------------------------------------------------------
  8. * |Bits |Field |Descriptions
  9. * | :----: | :----: | :---- |
  10. * |[0] |HXT_EN |HXT Control
  11. * | | |This is a protected register. Please refer to open lock sequence to program it.
  12. * | | |The bit default value is set by flash controller user configuration register config0 [26].
  13. * | | |0 = Disabled.
  14. * | | |1 = Enabled.
  15. * | | |HXT is disabled by default.
  16. * |[1] |LXT_EN |LXT Control
  17. * | | |This is a protected register. Please refer to open lock sequence to program it.
  18. * | | |0 = Disabled.
  19. * | | |1 = Enabled.
  20. * | | |LXT is disabled by default.
  21. * |[2] |HIRC_EN |HIRC Control
  22. * | | |This is a protected register. Please refer to open lock sequence to program it.
  23. * | | |0 = Disabled.
  24. * | | |1 = Enabled.
  25. * | | |HIRC is enabled by default.
  26. * |[3] |LIRC_EN |LIRC Control
  27. * | | |This is a protected register. Please refer to open lock sequence to program it.
  28. * | | |0 = Disabled.
  29. * | | |1 = Enabled.
  30. * | | |LIRC is enabled by default.
  31. * |[4] |WK_DLY |Wake-Up Delay Counter Enable
  32. * | | |This is a protected register. Please refer to open lock sequence to program it.
  33. * | | |When chip wakes up from Power-down mode, the clock control will delay 4096 clock cycles to wait HXT stable or 16 clock cycles to wait HIRC stable.
  34. * | | |0 = Delay clock cycle Disabled.
  35. * | | |1 = Delay clock cycle Enabled.
  36. * |[5] |PD_WK_IE |Power-Down Mode Wake-Up Interrupt Enable
  37. * | | |This is a protected register. Please refer to open lock sequence to program it.
  38. * | | |0 = Disabled.
  39. * | | |1 = Enabled.
  40. * | | |PD_WK_INT will be set if both PD_WK_IS and PD_WK_IE are high.
  41. * |[6] |PD_EN |Chip Power-Down Mode Enable Bit
  42. * | | |This is a protected register. Please refer to open lock sequence to program it.
  43. * | | |When CPU sets this bit, the chip power down is enabled and chip will not enter Power-down mode until CPU sleep mode is also active
  44. * | | |When chip wakes up from Power-down mode, this bit will be auto cleared.
  45. * | | |When chip is in Power-down mode, the LDO, HXT and HIRC will be disabled, but LXT and LIRC are not controlled by Power-down mode.
  46. * | | |When power down, the PLL and system clock (CPU, HCLKx and PCLKx) are also disabled no matter the Clock Source selection.
  47. * | | |Peripheral clocks are not controlled by this bit, if peripheral Clock Source is from LXT or LIRC.
  48. * | | |In Power-down mode, flash macro power is ON.
  49. * | | |0 = Chip operated in Normal mode.
  50. * | | |1 = Chip power down Enabled.
  51. * |[8] |HXT_SELXT |HXT SELXT
  52. * | | |This is a protected register. Please refer to open lock sequence to program it.
  53. * | | |0 = High frequency crystal loop back path Disabled. It is used for external oscillator.
  54. * | | |1 = High frequency crystal loop back path Enabled. It is used for external crystal.
  55. * |[9] |HXT_GAIN |HXT Gain Control Bit
  56. * | | |This is a protected register. Please refer to open lock sequence to program it.
  57. * | | |Gain control is used to enlarge the gain of crystal to make sure crystal wok normally.
  58. * | | |If gain control is enabled, crystal will consume more power than gain control off.
  59. * | | |0 = Gain control Disabled. It means HXT gain is always high.
  60. * | | |For 16MHz to 24MHz crystal.
  61. * | | |1 = Gain control Enabled. HXT gain will be high lasting 2ms then low. This is for power saving.
  62. * | | |For 4MHz to 16MHz crystal.
  63. * |[10] |LXT_SCNT |LXT Stable Time Control
  64. * | | |This is a protected register. Please refer to open lock sequence to program it.
  65. * | | |0 = Delay 4096 LXT before LXT output.
  66. * | | |1 = Delay 8192 LXT before LXT output.
  67. * |[12:11] |HXT_HF_ST |HXT Frequency Selection
  68. * | | |Set this bit to meet HXT frequency selection (Recommended)
  69. * | | |00 = HXT frequency is from 4 MHz to 12 MHz.
  70. * | | |01 = HXT frequency is from 12 MHz to 16 MHz.
  71. * | | |10 = HXT frequency is from 16 MHz to 24 MHz.
  72. * | | |11 = Reserved.
  73. */
  74. __IO uint32_t PWRCTL;
  75.  
  76. /**
  77. * AHBCLK
  78. * ===================================================================================================
  79. * Offset: 0x04 AHB Devices Clock Enable Control Register
  80. * ---------------------------------------------------------------------------------------------------
  81. * |Bits |Field |Descriptions
  82. * | :----: | :----: | :---- |
  83. * |[0] |GPIO_EN |GPIO Controller Clock Enable
  84. * | | |0 = Disabled.
  85. * | | |1 = Enabled.
  86. * |[1] |DMA_EN |DMA Controller Clock Enable
  87. * | | |0 = Disabled.
  88. * | | |1 = Enabled.
  89. * |[2] |ISP_EN |Flash ISP Controller Clock Enable
  90. * | | |0 = Disabled.
  91. * | | |1 = Enabled.
  92. * |[3] |EBI_EN |EBI Controller Clock Enable
  93. * | | |0 = Disabled.
  94. * | | |1 = Enabled.
  95. * |[4] |SRAM_EN |SRAM Controller Clock Enable
  96. * | | |0 = Disabled.
  97. * | | |1 = Enabled.
  98. * |[5] |TICK_EN |System Tick Clock Enable
  99. * | | |0 = Disabled.
  100. * | | |1 = Enabled.
  101. */
  102. __IO uint32_t AHBCLK;
  103.  
  104. /**
  105. * APBCLK
  106. * ===================================================================================================
  107. * Offset: 0x08 APB Devices Clock Enable Control Register
  108. * ---------------------------------------------------------------------------------------------------
  109. * |Bits |Field |Descriptions
  110. * | :----: | :----: | :---- |
  111. * |[0] |WDT_EN |Watchdog Timer Clock Enable Control
  112. * | | |This is a protected register. Please refer to open lock sequence to program it.
  113. * | | |This bit is used to control the WDT APB clock only, The WDT engine Clock Source is from LIRC.
  114. * | | |0 = Disabled.
  115. * | | |1 = Enabled.
  116. * |[1] |RTC_EN |Real-Time-Clock Clock Enable Control
  117. * | | |This bit is used to control the RTC APB clock only, The RTC engine Clock Source is from LXT.
  118. * | | |0 = Disabled.
  119. * | | |1 = Enabled.
  120. * |[2] |TMR0_EN |Timer0 Clock Enable Control
  121. * | | |0 = Disabled.
  122. * | | |1 = Enabled.
  123. * |[3] |TMR1_EN |Timer1 Clock Enable Control
  124. * | | |0 = Disabled.
  125. * | | |1 = Enabled.
  126. * |[4] |TMR2_EN |Timer2 Clock Enable Control
  127. * | | |0 = Disabled.
  128. * | | |1 = Enabled.
  129. * |[5] |TMR3_EN |Timer3 Clock Enable Control
  130. * | | |0 = Disabled.
  131. * | | |1 = Enabled.
  132. * |[6] |FDIV_EN |Frequency Divider Output Clock Enable Control
  133. * | | |0 = Disabled.
  134. * | | |1 = Enabled.
  135. * |[7] |SC2_EN |SmartCard 2 Clock Enable Control
  136. * | | |0 = Disabled.
  137. * | | |1 = Enabled.
  138. * |[8] |I2C0_EN |I2C0 Clock Enable Control
  139. * | | |0 = Disabled.
  140. * | | |1 = Enabled.
  141. * |[9] |I2C1_EN |I2C1 Clock Enable Control
  142. * | | |0 = Disabled.
  143. * | | |1 = Enabled.
  144. * |[12] |SPI0_EN |SPI0 Clock Enable Control
  145. * | | |0 = Disabled.
  146. * | | |1 = Enabled.
  147. * |[13] |SPI1_EN |SPI1 Clock Enable Control
  148. * | | |0 = Disabled.
  149. * | | |1 = Enabled.
  150. * |[14] |SPI2_EN |SPI2 Clock Enable Control
  151. * | | |0 = Disabled.
  152. * | | |1 = Enabled.
  153. * |[16] |UART0_EN |UART0 Clock Enable Control
  154. * | | |0 = Disabled.
  155. * | | |1 = Enabled.
  156. * |[17] |UART1_EN |UART1 Clock Enable Control
  157. * | | |0 = Disabled.
  158. * | | |1 = Enabled.
  159. * |[20] |PWM0_CH01_EN|PWM0 Channel 0 And Channel 1Clock Enable Control
  160. * | | |0 = Disabled.
  161. * | | |1 = Enabled.
  162. * |[21] |PWM0_CH23_EN|PWM0 Channel 2 And Channel 3 Clock Enable Control
  163. * | | |0 = Disabled.
  164. * | | |1 = Enabled.
  165. * |[22] |PWM1_CH01_EN|PWM1 Channel 0 And Channel 1 Clock Enable Control
  166. * | | |0 = Disabled.
  167. * | | |1 = Enabled.
  168. * |[23] |PWM1_CH23_EN|PWM1 Channel 2 And Channel 3 Clock Enable Control
  169. * | | |0 = Disabled.
  170. * | | |1 = Enabled.
  171. * |[25] |DAC_EN |12-Bit DAC Clock Enable Control
  172. * | | |0 = Disabled.
  173. * | | |1 = Enabled.
  174. * |[26] |LCD_EN |LCD Controller Clock Enable Control
  175. * | | |0 = Disabled.
  176. * | | |1 = Enabled.
  177. * |[27] |USBD_EN |USB FS Device Controller Clock Enable Control
  178. * | | |0 = Disabled.
  179. * | | |1 = Enabled.
  180. * |[28] |ADC_EN |Analog-Digital-Converter (ADC) Clock Enable Control
  181. * | | |0 = Disabled.
  182. * | | |1 = Enabled.
  183. * |[29] |I2S_EN |I2S Clock Enable Control
  184. * | | |0 = Disabled.
  185. * | | |1 = Enabled.
  186. * |[30] |SC0_EN |SmartCard 0 Clock Enable Control
  187. * | | |0 = Disabled.
  188. * | | |1 = Enabled.
  189. * |[31] |SC1_EN |SmartCard 1 Clock Enable Control
  190. * | | |0 = Disabled.
  191. * | | |1 = Enabled.
  192. */
  193. __IO uint32_t APBCLK;
  194.  
  195. /**
  196. * CLKSTATUS
  197. * ===================================================================================================
  198. * Offset: 0x0C Clock status monitor Register
  199. * ---------------------------------------------------------------------------------------------------
  200. * |Bits |Field |Descriptions
  201. * | :----: | :----: | :---- |
  202. * |[0] |HXT_STB |HXT Clock Source Stable Flag
  203. * | | |0 = HXT clock is not stable or not enable.
  204. * | | |1 = HXT clock is stable.
  205. * |[1] |LXT_STB |LXT Clock Source Stable Flag
  206. * | | |0 = LXT clock is not stable or not enable.
  207. * | | |1 = LXT clock is stable.
  208. * |[2] |PLL_STB |PLL Clock Source Stable Flag
  209. * | | |0 = PLL clock is not stable or not enable.
  210. * | | |1 = PLL clock is stable.
  211. * |[3] |LIRC_STB |LIRC Clock Source Stable Flag
  212. * | | |0 = LIRC clock is not stable or not enable.
  213. * | | |1 = LIRC clock is stable.
  214. * |[4] |HIRC_STB |HIRC Clock Source Stable Flag
  215. * | | |0 = HIRC clock is not stable or not enable.
  216. * | | |1 = HIRC clock is stable.
  217. * |[7] |CLK_SW_FAIL|Clock Switch Fail Flag
  218. * | | |0 = Clock switch success.
  219. * | | |1 = Clock switch fail.
  220. * | | |This bit will be set when target switch Clock Source is not stable. This bit is write 1 clear
  221. */
  222. __I uint32_t CLKSTATUS;
  223.  
  224. /**
  225. * CLKSEL0
  226. * ===================================================================================================
  227. * Offset: 0x10 Clock Source Select Control Register 0
  228. * ---------------------------------------------------------------------------------------------------
  229. * |Bits |Field |Descriptions
  230. * | :----: | :----: | :---- |
  231. * |[2:0] |HCLK_S |HCLK Clock Source Selection
  232. * | | |This is a protected register. Please refer to open lock sequence to program it.
  233. * | | |Note:
  234. * | | |Before Clock Source switches, the related clock sources (pre-select and new-select) must be turn on
  235. * | | |The 3-bit default value is reloaded with the value of CFOSC (Config0[26:24]) in user configuration register in Flash controller by any reset.
  236. * | | |Therefore the default value is either 000b or 111b.
  237. * | | |000 = HXT
  238. * | | |001 = LXT
  239. * | | |010 = PLL Clock
  240. * | | |011 = LIRC
  241. * | | |111 = HIRC
  242. * | | |Others = Reserved
  243. */
  244. __IO uint32_t CLKSEL0;
  245.  
  246. /**
  247. * CLKSEL1
  248. * ===================================================================================================
  249. * Offset: 0x14 Clock Source Select Control Register 1
  250. * ---------------------------------------------------------------------------------------------------
  251. * |Bits |Field |Descriptions
  252. * | :----: | :----: | :---- |
  253. * |[1:0] |UART_S |UART 0/1 Clock Source Selection (UART0 And UART1 Use The Same Clock Source Selection)
  254. * | | |00 = HXT
  255. * | | |01 = LXT
  256. * | | |10 = PLL Clock
  257. * | | |11 = HIRC
  258. * |[3:2] |ADC_S |ADC Clock Source Selection
  259. * | | |00 = HXT
  260. * | | |01 = LXT
  261. * | | |10 = PLL Clock
  262. * | | |11 = HIRC
  263. * |[5:4] |PWM0_CH01_S|PWM0 Channel 0 And Channel 1 Clock Source Selection
  264. * | | |PWM0 channel 0 and channel 1 use the same Engine clock source, both of them with the same prescaler
  265. * | | |00 = HXT
  266. * | | |01 = LXT
  267. * | | |10 = HCLK
  268. * | | |11 = HIRC
  269. * |[7:6] |PWM0_CH23_S|PWM0 Channel 2 And Channel 3 Clock Source Selection
  270. * | | |PWM0 channel 2 and channel 3 use the same Engine clock source, both of them with the same prescaler
  271. * | | |00 = HXT
  272. * | | |01 = LXT
  273. * | | |10 = HCLK
  274. * | | |11 = HIRC
  275. * |[10:8] |TMR0_S |Timer0 Clock Source Selection
  276. * | | |000 = HXT
  277. * | | |001 = LXT
  278. * | | |010 = LIRC
  279. * | | |011 = External Pin
  280. * | | |111 = HIRC
  281. * | | |Others = Reserved
  282. * |[14:12] |TMR1_S |Timer1 Clock Source Selection
  283. * | | |000 = HXT
  284. * | | |001 = LXT
  285. * | | |010 = LIRC
  286. * | | |011 = External Pin
  287. * | | |111 = HIRC
  288. * | | |Others = Reserved
  289. * |[18] |LCD_S |LCD Clock Source Selection
  290. * | | |0 = Clock Source from LXT.
  291. * | | |1 = Reserved.
  292. */
  293. __IO uint32_t CLKSEL1;
  294.  
  295. /**
  296. * CLKSEL2
  297. * ===================================================================================================
  298. * Offset: 0x18 Clock Source Select Control Register 2
  299. * ---------------------------------------------------------------------------------------------------
  300. * |Bits |Field |Descriptions
  301. * | :----: | :----: | :---- |
  302. * |[3:2] |FRQDIV_S |Clock Divider Clock Source Selection
  303. * | | |00 = HXT
  304. * | | |01 = LXT
  305. * | | |10 = HCLK
  306. * | | |11 = HIRC
  307. * |[5:4] |PWM1_CH01_S|PWM1 Channel 0 And Channel 1 Clock Source Selection
  308. * | | |PWM1 channel 0 and channel 1 use the same Engine clock source, both of them with the same pre-scale
  309. * | | |00 = HXT
  310. * | | |01 = LXT
  311. * | | |10 = HCLK
  312. * | | |11 = HIRC
  313. * |[7:6] |PWM1_CH23_S|PWM1 Channel 2 And Channel 2 Clock Source Selection
  314. * | | |PWM1 channel 2 and channel 3 use the same Engine clock source, both of them with the same pre-scale
  315. * | | |00 = HXT
  316. * | | |01 = LXT
  317. * | | |10 = HCLK
  318. * | | |11 = HIRC
  319. * |[10:8] |TMR2_S |Timer2 Clock Source Selection
  320. * | | |000 = HXT
  321. * | | |001 = LXT
  322. * | | |010 = LIRC
  323. * | | |011 = External Pin
  324. * | | |111 = HIRC
  325. * | | |Others = Reserved
  326. * |[14:12] |TMR3_S |Timer3 Clock Source Selection
  327. * | | |000 = HXT
  328. * | | |001 = LXT
  329. * | | |010 = LIRC
  330. * | | |011 = External Pin
  331. * | | |111 = HIRC
  332. * | | |Others = Reserved
  333. * |[17:16] |I2S_S |I2S Clock Source Selection
  334. * | | |00 = HXT
  335. * | | |01 = PLL Clock
  336. * | | |10 = HIRC
  337. * | | |11 = HIRC
  338. * |[19:18] |SC_S |SC Clock Source Selection
  339. * | | |00 = HXT
  340. * | | |01 = PLL Clock
  341. * | | |10 = HIRC
  342. * | | |11 = HIRC
  343. * | | |Note: SC0,SC1 and SC2 use the same Clock Source selection but they have different clock divider number.
  344. * |[20] |SPI0_S |SPI0 Clock Source Selection
  345. * | | |0 = PLL.
  346. * | | |1 = HCLK.
  347. * |[21] |SPI1_S |SPI1 Clock Source Selection
  348. * | | |0 = PLL.
  349. * | | |1 = HCLK.
  350. * |[22] |SPI2_S |SPI2 Clock Source Selection
  351. * | | |0 = PLL.
  352. * | | |1 = HCLK.
  353. */
  354. __IO uint32_t CLKSEL2;
  355.  
  356. /**
  357. * CLKDIV0
  358. * ===================================================================================================
  359. * Offset: 0x1C Clock Divider Number Register 0
  360. * ---------------------------------------------------------------------------------------------------
  361. * |Bits |Field |Descriptions
  362. * | :----: | :----: | :---- |
  363. * |[3:0] |HCLK_N |HCLK Clock Divide Number From HCLK Clock Source
  364. * | | |The HCLK clock frequency = (HCLK Clock Source frequency) / (HCLK_N + 1).
  365. * |[7:4] |USB_N |USB Clock Divide Number From PLL Clock
  366. * | | |The USB clock frequency = (PLL frequency ) / (USB_N + 1).
  367. * |[11:8] |UART_N |UART Clock Divide Number From UART Clock Source
  368. * | | |The UART clock frequency = (UART Clock Source frequency ) / (UART_N + 1).
  369. * |[15:12] |I2S_N |I2S Clock Divide Number From I2S Clock Source
  370. * | | |The I2S clock frequency = (I2S Clock Source frequency ) / (I2S_N + 1).
  371. * |[23:16] |ADC_N |ADC Clock Divide Number From ADC Clock Source
  372. * | | |The ADC clock frequency = (ADC Clock Source frequency ) / (ADC_N + 1).
  373. * |[31:28] |SC0_N |SC 0 Clock Divide Number From SC 0 Clock Source
  374. * | | |The SC 0 clock frequency = (SC0 Clock Source frequency ) / (SC0_N + 1).
  375. */
  376. __IO uint32_t CLKDIV0;
  377.  
  378. /**
  379. * CLKDIV1
  380. * ===================================================================================================
  381. * Offset: 0x20 Clock Divider Number Register 1
  382. * ---------------------------------------------------------------------------------------------------
  383. * |Bits |Field |Descriptions
  384. * | :----: | :----: | :---- |
  385. * |[3:0] |SC1_N |SC 1 Clock Divide Number From SC 1 Clock Source
  386. * | | |The SC 1 clock frequency = (SC 1 Clock Source frequency ) / (SC1_N + 1).
  387. * |[7:4] |SC2_N |SC 2 Clock Divide Number From SC2 Clock Source
  388. * | | |The SC 2 clock frequency = (SC 2 Clock Source frequency ) / (SC2_N + 1).
  389. */
  390. __IO uint32_t CLKDIV1;
  391.  
  392. /**
  393. * PLLCTL
  394. * ===================================================================================================
  395. * Offset: 0x24 PLL Control Register
  396. * ---------------------------------------------------------------------------------------------------
  397. * |Bits |Field |Descriptions
  398. * | :----: | :----: | :---- |
  399. * |[4:0] |FB_DV |PLL Feedback Divider Control Pins
  400. * | | |Refer to the formulas below the table.
  401. * | | |The range of FB_DV is from 0 to 63.
  402. * |[9:8] |IN_DV |PLL Input Divider Control Pins
  403. * | | |Refer to the formulas below the table.
  404. * |[12] |OUT_DV |PLL Output Divider Control Pins
  405. * | | |Refer to the formulas below the table. This bit MUST be 0 for PLL output low deviation.
  406. * |[16] |PD |Power-Down Mode
  407. * | | |If set the PD_EN bit "1" in PWR_CTL register, the PLL will enter Power-down mode too
  408. * | | |0 = PLL is in normal mode.
  409. * | | |1 = PLL is in power-down mode (default).
  410. * |[17] |PLL_SRC |PLL Source Clock Select
  411. * | | |0 = PLL source clock from HXT.
  412. * | | |1 = PLL source clock from HIRC.
  413. */
  414. __IO uint32_t PLLCTL;
  415.  
  416. /**
  417. * FRQDIV
  418. * ===================================================================================================
  419. * Offset: 0x28 Frequency Divider Control Register
  420. * ---------------------------------------------------------------------------------------------------
  421. * |Bits |Field |Descriptions
  422. * | :----: | :----: | :---- |
  423. * |[3:0] |FSEL |Divider Output Frequency Selection Bits
  424. * | | |The formula of output frequency is
  425. * | | |Fout = Fin/2^(N+1),.
  426. * | | |Where Fin is the input clock frequency, Fout is the frequency of divider output clock and N is the 4-bit value of FSEL[3:0].
  427. * |[4] |FDIV_EN |Frequency Divider Enable Bit
  428. * | | |0 = Frequency Divider Disabled.
  429. * | | |1 = Frequency Divider Enabled.
  430. */
  431. __IO uint32_t FRQDIV;
  432.  
  433. /**
  434. * MCLKO
  435. * ===================================================================================================
  436. * Offset: 0x2C Module Clock Output Register
  437. * ---------------------------------------------------------------------------------------------------
  438. * |Bits |Field |Descriptions
  439. * | :----: | :----: | :---- |
  440. * |[5:0] |MCLK_SEL |Module Clock Output Source Selection (PC.0)
  441. * | | |000000 = ISP_CLK
  442. * | | |000001 = HIRC
  443. * | | |000010 = HXT
  444. * | | |000011 = LXT
  445. * | | |000100 = LIRC
  446. * | | |000101 = PLL output
  447. * | | |000110 = PLL input
  448. * | | |000111 = System Tick
  449. * | | |001000 = HCLK clock
  450. * | | |001010 = PCLK clock
  451. * | | |100000 = TMR0_CLK
  452. * | | |100001 = TMR1_CLK
  453. * | | |100010 = UART0_CLK
  454. * | | |100011 = USB_CLK
  455. * | | |100100 = ADC_CLK
  456. * | | |100101 = WDT_CLK
  457. * | | |100110 = PWM0_CH01_CLK
  458. * | | |100111 = PWM0_CH32_CLK
  459. * | | |101001 = LCD_CLK
  460. * | | |111000 = TMR2_CLK
  461. * | | |111001 = TMR3_CLK
  462. * | | |111010 = UART1_CLK
  463. * | | |111011 = PWM1_CH01_CLK
  464. * | | |111100 = PWM1_CH23_CLK
  465. * | | |111101 = I&sup2;S_CLK
  466. * | | |111110 = SC0_CLK
  467. * | | |111111 = SC1_CLK
  468. * |[7] |MCLK_EN |Module Clock Output Enable
  469. * | | |User can get the module clock output from PC.0 pin via choosing the clock source in the MCLK_SEL bit field and then setting MCLK_EN bit to 1.
  470. * | | |0 = Module clock output Disabled.
  471. * | | |1 = Module clock output Enabled.
  472. * | | |Note: If this bit is enabled, PC.0 will be configured to module clock output and the setting of PC0_MFP will be ineffective
  473. */
  474. __IO uint32_t MCLKO;
  475.  
  476. /**
  477. * WK_INTSTS
  478. * ===================================================================================================
  479. * Offset: 0x30 Wake-up interrupt status
  480. * ---------------------------------------------------------------------------------------------------
  481. * |Bits |Field |Descriptions
  482. * | :----: | :----: | :---- |
  483. * |[0] |PD_WK_IS |Wake-Up Interrupt Status In Chip Power-Down Mode
  484. * | | |This bit indicates that some event resumes chip from Power-down mode
  485. * | | |The status is set if external interrupts, UART, GPIO, RTC, USB, SPI, Timer, WDT, and BOD wake-up occurred.
  486. * | | |Write 1 to clear this bit.
  487. */
  488. __IO uint32_t WK_INTSTS;
  489.  
  490. } CLK_T;

对照datasheet,只需要看APBCLK的部分就可以了。

功能描述

看门狗定时器的用途是在软件出问题时执行系统复位功能,这可以防止系统无限期地挂起。除此之外,看门狗定时器还支持将CPU 从掉电模式唤醒的功能,

此外当 CPU 进入掉电模式时,WDT 计数器会自动重置。

看门狗定时器包含一个18 位的自由运行计数器,定时溢出间隔可编程。

接下来的表格给出了看门狗超时间隔选择,

而接下来的图片给出了看门狗中断信号和复位信号的时序。

 

设置 WTE (WDT_CTL[3]) 使能看门狗定时器和WDT 计数器开始计数。

当计数器达到选择的超时间隔,看门狗定时器中断标志WDT_IS 将被立即被置位,并请求WDT 中断 (如果看门狗定时器中断使能位WDT_IE 置位),同时紧接着超时事件会有一个指定的延时可透过 WTRDSEL 設置,用户必须在该指定延时过期前设置WTR (WDT_CTL[0]) (看门狗定时器复位) 为高来复位18 位 WDT 计数器,以防止芯片复位。

WTR 位在WDT 计数器复位后由硬件自动清零。

通过设置WTIS (WDT_CTL[6:4]),有8 种带指定延时时间的超时间隔可供选择(上面的表格)。

如果在指定延迟时间过期后,WDT 计数器没有被清零,看门狗定时器将置位看门狗定时器复位标志(WDT_RST_IS),并复位CPU。

这个复位将持续63 个 WDT 时钟 (TRST),然后芯片重启,并从复位向量(0x0000_0000) 处重新开始执行程序。

WDT_RST_IS 不会被看门狗复位清零。用户可用软件轮询WDT_RST_IS 来识别复位源是否WDT。

明白了原理,再看一下它们的寄存器,然后找到对应的寄存器,就可以进行配置了

寄存器是什么?在我的理解就是地址,这个地址对应着硬件的

下图是寄存器的基地址和偏移地址:

对应的宏定义为:

  1. #define APB1PERIPH_BASE ((uint32_t)0x40000000) ///< APB1 base address
  2.  
  3. #define WDT_BASE (APB1PERIPH_BASE + 0x04000) ///< WDT register base address
  4. #define WDT ((WDT_T *) WDT_BASE) ///< Pointer to WDT register structure

上文是WDT的基地址,也就是WDT_BA的部分,而下面是它的寄存器对应地址

  1. typedef struct {
  2.  
  3. /**
  4. * CTL
  5. * ===================================================================================================
  6. * Offset: 0x00 Watchdog Timer Control Register
  7. * ---------------------------------------------------------------------------------------------------
  8. * |Bits |Field |Descriptions
  9. * | :----: | :----: | :---- |
  10. * |[0] |WTR |Clear Watchdog Timer
  11. * | | |This is a protected register. Please refer to open lock sequence to program it.
  12. * | | |Set this bit will clear the Watchdog timer.
  13. * | | |0 = No effect.
  14. * | | |1 = Reset the contents of the Watchdog timer.
  15. * | | |Note: This bit will be auto cleared after few clock cycles.
  16. * |[1] |WTRE |Watchdog Timer Reset Function Enable
  17. * | | |This is a protected register. Please refer to open lock sequence to program it.
  18. * | | |Setting this bit will enable the Watchdog timer reset function.
  19. * | | |0 = Watchdog timer reset function Disabled.
  20. * | | |1 = Watchdog timer reset function Enabled.
  21. * |[2] |WTWKE |Watchdog Timer Wake-Up Function Enable
  22. * | | |This is a protected register. Please refer to open lock sequence to program it.
  23. * | | |0 = Watchdog timer Wake-up CPU function Disabled.
  24. * | | |1 = Wake-up function Enabled so that Watchdog timer time-out can wake up CPU from power-down mode.
  25. * |[3] |WTE |Watchdog Timer Enable
  26. * | | |This is a protected register. Please refer to open lock sequence to program it.
  27. * | | |0 = Watchdog timer Disabled (this action will reset the internal counter).
  28. * | | |1 = Watchdog timer Enabled.
  29. * |[6:4] |WTIS |Watchdog Timer Interval Selection
  30. * | | |This is a protected register. Please refer to open lock sequence to program it.
  31. * | | |These three bits select the time-out interval for the Watchdog timer.
  32. * | | |This count is free running counter.
  33. * | | |Please refer to the Table 5-16.
  34. * |[9:8] |WTRDSEL |Watchdog Timer Reset Delay Select
  35. * | | |When watchdog timeout happened, software has a time named watchdog reset delay period to clear watchdog timer to prevent watchdog reset happened.
  36. * | | |Software can select a suitable value of watchdog reset delay period for different watchdog timeout period.
  37. * | | |00 = Watchdog reset delay period is 1026 watchdog clock
  38. * | | |01 = Watchdog reset delay period is 130 watchdog clock
  39. * | | |10 = Watchdog reset delay period is 18 watchdog clock
  40. * | | |11 = Watchdog reset delay period is 3 watchdog clock
  41. * | | |This register will be reset if watchdog reset happened
  42. */
  43. __IO uint32_t CTL;
  44.  
  45. /**
  46. * IER
  47. * ===================================================================================================
  48. * Offset: 0x04 Watchdog Timer Interrupt Enable Register
  49. * ---------------------------------------------------------------------------------------------------
  50. * |Bits |Field |Descriptions
  51. * | :----: | :----: | :---- |
  52. * |[0] |WDT_IE |Watchdog Timer Interrupt Enable
  53. * | | |0 = Watchdog timer interrupt Disabled.
  54. * | | |1 = Watchdog timer interrupt Enabled.
  55. */
  56. __IO uint32_t IER;
  57.  
  58. /**
  59. * ISR
  60. * ===================================================================================================
  61. * Offset: 0x08 Watchdog Timer Interrupt Status Register
  62. * ---------------------------------------------------------------------------------------------------
  63. * |Bits |Field |Descriptions
  64. * | :----: | :----: | :---- |
  65. * |[0] |IS |Watchdog Timer Interrupt Status
  66. * | | |If the Watchdog timer interrupt is enabled, then the hardware will set this bit to indicate that the Watchdog timer interrupt has occurred.
  67. * | | |If the Watchdog timer interrupt is not enabled, then this bit indicates that a time-out period has elapsed.
  68. * | | |0 = Watchdog timer interrupt did not occur.
  69. * | | |1 = Watchdog timer interrupt occurs.
  70. * | | |Note: This bit is read only, but can be cleared by writing "1" to it.
  71. * |[1] |RST_IS |Watchdog Timer Reset Status
  72. * | | |When the Watchdog timer initiates a reset, the hardware will set this bit.
  73. * | | |This flag can be read by software to determine the source of reset.
  74. * | | |Software is responsible to clear it manually by writing "1" to it.
  75. * | | |If WTRE is disabled, then the Watchdog timer has no effect on this bit.
  76. * | | |0 = Watchdog timer reset did not occur.
  77. * | | |1 = Watchdog timer reset occurs.
  78. * | | |Note: This bit is read only, but can be cleared by writing "1" to it.
  79. * |[2] |WAKE_IS |Watchdog Timer Wake-Up Status
  80. * | | |If Watchdog timer causes system to wake up from power-down mode, this bit will be set to high.
  81. * | | |It must be cleared by software with a write "1" to this bit.
  82. * | | |0 = Watchdog timer does not cause system wake-up.
  83. * | | |1 = Wake system up from power-down mode by Watchdog time-out.
  84. * | | |Note1: When system in power-down mode and watchdog time-out, hardware will set WDT_WAKE_IS and WDT_IS.
  85. * | | |Note2: After one engine clock, this bit can be cleared by writing "1" to it
  86. */
  87. __IO uint32_t ISR;
  88.  
  89. } WDT_T;

  1. #define WDT_CTL_WTR_Msk (0x1ul << WDT_CTL_WTR_Pos) /*!< WDT_T::CTL: WTR Mask */
  2.  
  3. #define WDT_CTL_WTRE_Pos (1) /*!< WDT_T::CTL: WTRE Position */
  4. #define WDT_CTL_WTRE_Msk (0x1ul << WDT_CTL_WTRE_Pos) /*!< WDT_T::CTL: WTRE Mask */
  5.  
  6. #define WDT_CTL_WTWKE_Pos (2) /*!< WDT_T::CTL: WTWKE Position */
  7. #define WDT_CTL_WTWKE_Msk (0x1ul << WDT_CTL_WTWKE_Pos) /*!< WDT_T::CTL: WTWKE Mask */
  8.  
  9. #define WDT_CTL_WTE_Pos (3) /*!< WDT_T::CTL: WTE Position */
  10. #define WDT_CTL_WTE_Msk (0x1ul << WDT_CTL_WTE_Pos) /*!< WDT_T::CTL: WTE Mask */
  11.  
  12. #define WDT_CTL_WTIS_Pos (4) /*!< WDT_T::CTL: WTIS Position */
  13. #define WDT_CTL_WTIS_Msk (0x7ul << WDT_CTL_WTIS_Pos) /*!< WDT_T::CTL: WTIS Mask */
  14.  
  15. #define WDT_CTL_WTRDSEL_Pos (8) /*!< WDT_T::CTL: WTRDSEL Position */
  16. #define WDT_CTL_WTRDSEL_Msk (0x3ul << WDT_CTL_WTRDSEL_Pos) /*!< WDT_T::CTL: WTRDSEL Mask */
    //以上部分是否感到眼熟?跟WDT_CTL的地址是一一对应的,后面也是一样,也就是说0bit是WTR,1是WTRE.WTIS是第四位,但是它本身占三位,
    //所以下一个寄存器就会移三位,又保留了一位,所以左移第八位。后面都是一样的
  1. #define WDT_IER_IE_Pos (0) /*!< WDT_T::IER: IE Position */
    #define WDT_IER_IE_Msk (0x1ul << WDT_IER_IE_Pos) /*!< WDT_T::IER: IE Mask */
  2.  
  3. #define WDT_ISR_IS_Pos (0) /*!< WDT_T::ISR: IS Position */
    #define WDT_ISR_IS_Msk (0x1ul << WDT_ISR_IS_Pos) /*!< WDT_T::ISR: IS Mask */
  4.  
  5. #define WDT_ISR_RST_IS_Pos (1) /*!< WDT_T::ISR: RST_IS Position */
  6.  
  7. #define WDT_ISR_RST_IS_Msk (0x1ul << WDT_ISR_RST_IS_Pos) /*!< WDT_T::ISR: RST_IS Mask */
  8.  
  9. #define WDT_ISR_WAKE_IS_Pos (2) /*!< WDT_T::ISR: WAKE_IS Position */ #
    define WDT_ISR_WAKE_IS_Msk (0x1ul << WDT_ISR_WAKE_IS_Pos) /*!< WDT_T::ISR: WAKE_IS Mask */
  10.  
  11. /**@}*/
    /* WDT_CONST */
  12.  
  13. /**@}*/
  14.  
  15. /* end of WDT register group */
  16.  
  17. 上面是它的最底层部分,您看懂了么?其实就是强制地址转换,分配地址,然后根据地址进行。配置寄存器就是给他们一个输入,或者输出。不过虽然本质就是这样,但操作并不简单,
    因为他们的寄存器很多,而且大多要涉及外围电路和外部器件,任何一个环节出错,都不可能达到效果,虽然麻烦,但大部分都是有规律的。
    这里穿插一则寄存器的小知识
  18.  
  19. 在存储器 Block2 这块区域,设计的是片上外设,它们以四个字节为一个单元,共32bit,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。
    我们可以找到每个单元的起始地址,然后通过 C语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,
    这时我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器,
    这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。
  20.  
  21. 当然寄存器有软件的也有硬件的,电路方面在我的新浪博客上面会有描述。

再插一则小知识,是关于强制类型转换的

关于一个

int *ptr=(int *)(&a+1)

问题的探讨

网络上看到这样一道有意思的题目,是关于数组与指针的问题,描述如下:

main()

{

int a[5]={1,2,3,4,5};

int *ptr=(int *)(&a+1);

printf("%d,%d",*(a+1),*(ptr-1));

}

输出为:2,5

请解释以上代码的输出结果。答案如下:

*(a+1)其实很简单就是指a[1],输出为2. 问题关键就在于第二个点,

*(ptr-1)输出为多少?

解释如下,&a+1不是首地址+1,系统会认为加了一个整个a数组,偏移了整个数组a的大小(也就是5个int的大小)。所以

int *ptr=(int *)(&a+1);其实ptr实际是&(a[5]),也就是a+5. 原因为何呢?

&a是数组指针,其类型为int(*)[5]; 而指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同,

a是长度为5的int数组指针,所以要加5*sizeof(int),所以ptr实际是a[5],但是ptr与(&a+1)类型是不一样的,这点非常重要,所以ptr-1只会减去sizeof(int*),

a,&a的地址是一样的,但意思就不一样了,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]。

先看下面这个例子:
struct Test
{
    int Num;
    char *pcName;
    short sDate;
    char cha[2];
    short sBa[4];
}*p;
    假设p 的值为0x100000。如下表表达式的值分别为多少?
p + 0x1 = 0x___ ?
(unsigned long)p + 0x1 = 0x___?
(unsigned int*)p + 0x1 = 0x___?
    我相信会有很多人一开始没看明白这个问题是什么意思。其实我们再仔细看看,这个知识点似曾相识。一个指针变量与一个整数相加减,到底该怎么解析呢?还记得前面我们的表达式“a+1”与“&a+1”之间的区别吗?其实这里也一样。指针变量与一个整数相加减并不是用指针变量里的地址直接加减这个整数。这个整数的单位不是byte 而是元素的个数。所以:p + 0x1 的值为0x100000+sizof(Test)*0x1。至于此结构体的大小为20byte,前面的章节已经详细讲解过。所以p +0x1 的值为:0x100014。(0X100000+20(0X100014)),(unsigned long)p + 0x1 的值呢?这里涉及到强制转换,将指针变量p 保存的值强制转换成无符号的长整型数。任何数值一旦被强制转换,其类型就改变了。所以这个表达式其实就是一个无符号的长整型数加上另一个整数。所以其值为:0x100001。(unsigned int*)p + 0x1 的值呢?这里的p 被强制转换成一个指向无符号整型的指针。所以其值为0x100000+sizof(unsigned int)*0x1,等于0x100004。上面这个问题似乎还没啥技术含量,下面就来个有技术含量的:
在x86 系统下,其值为多少?
int main()
{
    int a[4]={1,2,3,4};
    int *ptr1=(int *)(&a+1);
    int *ptr2=(int *)((int)a+1);
    printf("%x,%x",ptr1[-1],*ptr2);
    return 0;
}
    一个懂汇编的人,这种题实在是小case。
    下面就来分析分析这个问题:根据上面的讲解,&a+1 与a+1 的区别已经清楚。
    ptr1:将&a+1 的值强制转换成int*类型,赋值给int* 类型的变量ptr,ptr1 肯定指到数组a 的下一个int 类型数据了。
    ptr1[-1]被解析成*(ptr1-1),即ptr1 往后退4 个byte。所以其值为0x4。
    ptr2:按照上面的讲解,(int)a+1 的值是元素a[0]的第二个字节的地址。
   然后把这个地址强制转换成int*类型的值赋给ptr2,也就是说*ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。
    好,问题就来了,这连续4 个byte 里到底存了什么东西呢?也就是说元素a[0],a[1]里面的值到底怎么存储的。这就涉及到系统的大小端模式了,如果懂汇编的话,这根本就不是问题。既然不知道当前系统是什么模式,那就得想办法测试。大小端模式与测试的方法在第一章讲解union 关键字时已经详细讨论过了,请翻到彼处参看,这里就不再详述。我们可以用下面这个函数来测试当前系统的模式。
int checkSystem( )
{
    union check
    {
        int i;
        char ch;
    } c;
    c.i = 1;
    return (c.ch ==1);
}
    如果当前系统为大端模式这个函数返回0;如果为小端模式,函数返回1。也就是说如果此函数的返回值为1 的话,*ptr2 的值为0x2000000。
如果此函数的返回值为0 的话,*ptr2 的值为0x100。
关于系统的大小端呢,看下文

小端:低地址存放低位数据;

大端:低地址存放高位数据;

而网络中传输是用大端。

用代码实现大小端利用了共用体的原理实现判断是比较简单的一个方法:

  1. #include <stdio.h>
  2. union n{
  3. int a;
  4. char b;
  5. };
  6. int main(){
  7. union n ss;
  8. ss.a=1;
  9. if(ss.b!=0)
  10. printf("Little\n");
  11. else
  12. printf("Big\n");
  13. return 0;
  14. }

由于共用体中的所有元素都存放在一块内存空间中,而b的起始地址是从int型的起始地址对齐的。所以对一个int型的数据进行写1,如果是大端的话,char型的b就会为1,否则b就为0.

接下来,我们再来看看,上面所包含的寄存器,这是一个很大的量,请耐心看完,相信会有收获的。

既然我们熟悉了底层。那么我们当然不会止步于此,应用层的东西,当然也要做。

在功能描述那一章节时,我们其实已经明白了,它的具体操作和步骤,但是为了我们更加清楚明白和方便调用,我们决定采用库函数的形式,来讲述这个应用,首先我想说的是这只是一个小的官方例程,如果后续会有大型的项目,不涉及保密的话,我会把它共享出来

既然我们要用看门狗,既然要使用它,我们当然要打开它,即进行初始化。

首先选择时钟

  1. void SYS_Init(void)
  2. {
  3.  
  4. /*---------------------------------------------------------------------------------------------------------*/
  5. /* Init System Clock */
  6. /*---------------------------------------------------------------------------------------------------------*/
  7. /* Unlock protected registers */
  8. SYS_UnlockReg();
  9.  
  10. /* Enable External XTAL (4~24 MHz) */
  11. CLK_EnableXtalRC(CLK_PWRCTL_HXT_EN_Msk);
  12.  
  13. /* Enable LIRC */
  14. CLK_EnableXtalRC(CLK_PWRCTL_LIRC_EN_Msk);
  15.  
  16. /* Waiting for 12MHz clock ready */
  17. CLK_WaitClockReady( CLK_CLKSTATUS_HXT_STB_Msk);
  18.  
  19. /* Waiting for LIRC clock ready */
  20. CLK_WaitClockReady( CLK_CLKSTATUS_LIRC_STB_Msk);
  21.  
  22. /* Switch HCLK clock source to HXT */
  23. CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HXT,CLK_HCLK_CLK_DIVIDER(1));
  24.  
  25. /* Enable IP clock */
  26. CLK_EnableModuleClock(UART0_MODULE);
  27. CLK_EnableModuleClock(WDT_MODULE);

/*

#define WDT_MODULE ((1UL<<31)|(3<<29)|(MODULE_NoMsk<<25)|( 0<<20)|(0<<18)|(MODULE_NoMsk<<10)|( 0<<5)|CLK_APBCLK_WDT_EN_Pos )

/*!< Watchdog Timer Module  */

#define MODULE_NoMsk                       0x0                 /*!< Not mask on MODULE index */

#define WDT_MODULE ((1UL<<31)|(3<<29)|(MODULE_NoMsk<<25)|( 0<<20)|(0<<18)|(MODULE_NoMsk<<10)|( 0<<5)|CLK_APBCLK_WDT_EN_Pos )

#define CLK_APBCLK_WDT_EN_Pos (0) /*!< CLK_T::APBCLK: WDT_EN Position */

#define CLK_APBCLK_WDT_EN_Msk (0x1ul << CLK_APBCLK_WDT_EN_Pos) /*!< CLK_T::APBCLK: WDT_EN Mask

*/

  1. /* Select IP clock source */
  2. CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_UART_CLK_DIVIDER(1));
  3. CLK_SetModuleClock(WDT_MODULE, 0, 0);
  4.  
  5. /* Update System Core Clock */
  6. /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
  7. SystemCoreClockUpdate();
  8.  
  9. /*---------------------------------------------------------------------------------------------------------*/
  10. /* Init I/O Multi-function */
  11. /*---------------------------------------------------------------------------------------------------------*/
  12. /* Set GPB multi-function pins for UART0 RXD and TXD */
  13. SYS->PB_L_MFP &= ~(SYS_PB_L_MFP_PB0_MFP_Msk | SYS_PB_L_MFP_PB1_MFP_Msk);
  14. SYS->PB_L_MFP |= (SYS_PB_L_MFP_PB1_MFP_UART0_TX | SYS_PB_L_MFP_PB0_MFP_UART0_RX);
  15. /* Lock protected registers */
  16. SYS_LockReg();
  17.  
  18. }

void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
{
uint32_t u32tmp=0,u32sel=0,u32div=0;

  1.  

if(MODULE_CLKDIV_Msk(u32ModuleIdx)!=MODULE_NoMsk) {
u32div =(uint32_t)&CLK->CLKDIV0+((MODULE_CLKDIV(u32ModuleIdx))*4);
u32tmp = *(volatile uint32_t *)(u32div);
u32tmp = ( u32tmp & ~(MODULE_CLKDIV_Msk(u32ModuleIdx)<<MODULE_CLKDIV_Pos(u32ModuleIdx)) ) | u32ClkDiv;
*(volatile uint32_t *)(u32div) = u32tmp;
}

#define MODULE_CLKDIV_Msk(x)               ((x >>10) & 0xff)   /*!< Calculate CLKDIV mask offset on MODULE index */

#define MODULE_CLKDIV_Msk(x) ((x >>10) & 0xff) /*!< Calculate CLKDIV mask offset on MODULE index */

#define MODULE_CLKDIV_Pos(x) ((x >>5 ) & 0x1f) /*!< Calculate CLKDIV position offset on MODULE index */

#define MODULE_CLKDIV_Pos(x)               ((x >>5 ) & 0x1f)   /*!< Calculate CLKDIV position offset on MODULE index */

( u32tmp & ~(MODULE_CLKDIV_Msk(u32ModuleIdx)<<MODULE_CLKDIV_Pos(u32ModuleIdx)) ) | u32ClkDiv;

~((1110 0000 0000 0000 0000 0000 0000>>10) <<(1110 0000 0000 0000 0000 0000 >>5))|u32Div mingbaile  zhongyv

//  1110 0000 0000 0000 0000 0000 0000 0000 右移5位为0000 1110 0000 0000 0000 0000 0000 0000 0000

// 1110 0000 0000 0000 0000 0000 0000 0000 右移10位为 0000 0000 0111 0000 0000 0000 0000 0000  0000

//所谓模块就是给时钟的WDT_EN位一个使能

if(MODULE_CLKSEL_Msk(u32ModuleIdx)!=MODULE_NoMsk) {
u32sel = (uint32_t)&CLK->CLKSEL0+((MODULE_CLKSEL(u32ModuleIdx))*4);
u32tmp = *(volatile uint32_t *)(u32sel);
u32tmp = ( u32tmp & ~(MODULE_CLKSEL_Msk(u32ModuleIdx)<<MODULE_CLKSEL_Pos(u32ModuleIdx)) ) | u32ClkSrc;
*(volatile uint32_t *)(u32sel) = u32tmp;
}
}

  1.  

即我们刚开始所讲的设置 WTE (WDT_CTL[3]) 使能看门狗定时器和WDT 计数器开始计数。(在功能描述那一部分第一句)

  1.  

/**
* @brief This function make WDT module start counting with different time-out interval
* @param[in] u32TimeoutInterval Time-out interval period of WDT module. Valid values are:
* - \ref WDT_TIMEOUT_2POW4
* - \ref WDT_TIMEOUT_2POW6
* - \ref WDT_TIMEOUT_2POW8
* - \ref WDT_TIMEOUT_2POW10
* - \ref WDT_TIMEOUT_2POW12
* - \ref WDT_TIMEOUT_2POW14
* - \ref WDT_TIMEOUT_2POW16
* - \ref WDT_TIMEOUT_2POW18
* @param[in] u32ResetDelay Reset delay period while WDT time-out happened. Valid values are:
* - \ref WDT_RESET_DELAY_3CLK
* - \ref WDT_RESET_DELAY_18CLK
* - \ref WDT_RESET_DELAY_130CLK
* - \ref WDT_RESET_DELAY_1026CLK
* @param[in] u32EnableReset Enable WDT reset system function. Valid values are TRUE and FALSE
* @param[in] u32EnableWakeup Enable WDT wake-up system function. Valid values are TRUE and FALSE
* @return None
*/

  1. void WDT_Open(uint32_t u32TimeoutInterval,
  2. uint32_t u32ResetDelay,
  3. uint32_t u32EnableReset,
  4. uint32_t u32EnableWakeup)
  5. {
  6.  
  7. WDT->CTL = u32TimeoutInterval | u32ResetDelay | WDT_CTL_WTE_Msk |
  8. (u32EnableReset << WDT_CTL_WTRE_Pos) |
  9. (u32EnableWakeup << WDT_CTL_WTWKE_Pos);
  10. return;
  11. }

这个意思就是选择它的超时时间,和复位延迟时间和启动系统功能,和复位系统功能

u32TimeoutInterval WDT模块的超时间隔时间。有效值是:
 * - \ ref WDT_TIMEOUT_2POW4
 * - \ ref WDT_TIMEOUT_2POW6
 * - \ ref WDT_TIMEOUT_2POW8
 * - \ ref WDT_TIMEOUT_2POW10
 * - \ ref WDT_TIMEOUT_2POW12
 * - \ ref WDT_TIMEOUT_2POW14
 * - \ ref WDT_TIMEOUT_2POW16
 * - \ ref WDT_TIMEOUT_2POW18

* @param [in] u32ResetDelay发生WDT超时的复位延迟时间。有效值是:
 * - \ ref WDT_RESET_DELAY_3CLK
 * - \ ref WDT_RESET_DELAY_18CLK
 * - \ ref WDT_RESET_DELAY_130CLK
 * - \ ref WDT_RESET_DELAY_1026CLK
 * @param [in] u32EnableReset启用WDT复位系统功能。有效值为TRUE和FALSE
 * @param [in] u32EnableWakeup启用WDT唤醒系统功能。有效值为TRUE和FALSE
 * @返回无
 * /

对应的库函数与表格分别是:

  1. #define WDT_TIMEOUT_2POW4 (0UL << WDT_CTL_WTIS_Pos) /*!< WDT setting for timeout interval = 2^4 * WDT clocks */
  2. #define WDT_TIMEOUT_2POW6 (1UL << WDT_CTL_WTIS_Pos) /*!< WDT setting for timeout interval = 2^6 * WDT clocks */
  3. #define WDT_TIMEOUT_2POW8 (2UL << WDT_CTL_WTIS_Pos) /*!< WDT setting for timeout interval = 2^8 * WDT clocks */
  4. #define WDT_TIMEOUT_2POW10 (3UL << WDT_CTL_WTIS_Pos) /*!< WDT setting for timeout interval = 2^10 * WDT clocks */
  5. #define WDT_TIMEOUT_2POW12 (4UL << WDT_CTL_WTIS_Pos) /*!< WDT setting for timeout interval = 2^12 * WDT clocks */
  6. #define WDT_TIMEOUT_2POW14 (5UL << WDT_CTL_WTIS_Pos) /*!< WDT setting for timeout interval = 2^14 * WDT clocks */
  7. #define WDT_TIMEOUT_2POW16 (6UL << WDT_CTL_WTIS_Pos) /*!< WDT setting for timeout interval = 2^16 * WDT clocks */
  8. #define WDT_TIMEOUT_2POW18 (7UL << WDT_CTL_WTIS_Pos) /*!< WDT setting for timeout interval = 2^18 * WDT clocks */
  9.  
  10. #define WDT_RESET_DELAY_3CLK (3UL << WDT_CTL_WTRDSEL_Pos) /*!< WDT setting reset delay to 3 WDT clocks */
  11. #define WDT_RESET_DELAY_18CLK (2UL << WDT_CTL_WTRDSEL_Pos) /*!< WDT setting reset delay to 18 WDT clocks */
  12. #define WDT_RESET_DELAY_130CLK (1UL << WDT_CTL_WTRDSEL_Pos) /*!< WDT setting reset delay to 130 WDT clocks */
  13. #define WDT_RESET_DELAY_1026CLK (0UL << WDT_CTL_WTRDSEL_Pos) /*!< WDT setting reset delay to 1026 WDT clocks */

我们看一看第二句:

当计数器达到选择的超时间隔,看门狗定时器中断标志WDT_IS将被立即被置位,并请求WDT 中断 (如果看门狗定时器中断使能位WDT_IE 置位),同时紧接着超时事件会有一个指定的延时可透过 WTRDSEL 設置,用户必须在该指定延时过期前设置WTR (WDT_CTL[0]) (看门狗定时器复位) 为高来复位18 位 WDT 计数器,以防止芯片复位。

请求中断就得先有中断,使能中断:

/**
* @brief This function enables the WDT time-out interrupt
* @param None
* @return None
*/

  1. __STATIC_INLINE void WDT_EnableInt(void)
  2. {
  3. WDT->IER = WDT_IER_IE_Msk;
  4. return;
  5. }
  1. /**
  2. \brief Enable External Interrupt
  3. \details Enables a device-specific interrupt in the NVIC interrupt controller.
  4. \param [in] IRQn External interrupt number. Value cannot be negative.
  5. */
  6. __STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
  7. {
  8. NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
  9. }

这两个中断,一个是WDT使能中断,一个是外部中断。我们还要利用定时器进行喂狗操作,所谓喂狗:

看门狗定时器(Watchdog Timer ,看门狗)电路一般有一个输入,这个输入被称作"喂狗".
 
MCU 正常工作的时候,每隔一段时间输出一个信号到喂狗端,给 WDT 清零。如果超过规定的时间不喂狗(一般在程序跑飞时),WDT 定时超过,就会给出一个复位信号到MCU,让MCU 复位,防止MCU 死机。
 
看门狗需要在规定时间内喂狗,这里所说的“规定时间”就是看门狗定时器计数溢出时间,即一旦到达计数阈值,看门狗就会产生复位。CPU必须在这个周期内对这个定时器进行清零处理,让看门狗定时器重新计数,防止看门狗产生复位。

void WDT_IRQHandler(void)
{

// Clear WDT interrupt flag

WDT_CLEAR_TIMEOUT_INT_FLAG();

// Check WDT wake up flag
if(WDT_GET_TIMEOUT_WAKEUP_FLAG()) {
printf("Wake up by WDT\n");
// Clear WDT wake up flag
WDT_CLEAR_TIMEOUT_WAKEUP_FLAG();
}

}

这里面涉及的库函数有下面这些:看完您是否明白了?

#define WDT_ISR_WAKE_IS_Msk (0x1ul << WDT_ISR_WAKE_IS_Pos) /*!< WDT_T::ISR: WAKE_IS Mask */

#define WDT_GET_TIMEOUT_WAKEUP_FLAG() (WDT->ISR & WDT_ISR_WAKE_IS_Msk ? 1 : 0)

#define WDT_CLEAR_TIMEOUT_WAKEUP_FLAG() (WDT->ISR = WDT_ISR_WAKE_IS_Msk)

那么?功能与描述最后这一句,WDT_RST_IS 不会被看门狗复位清零。用户可用软件轮询WDT_RST_IS 来识别复位源是否WDT。

然后,上今天的主菜,主程序上场:

  1. /******************************************************************************
  2. * @file main.c
  3. * @version V1.00
  4. * $Revision: 3 $
  5. * $Date: 14/09/11 7:39p $
  6. * @brief Use WDT to wake up system from Power-down mode periodically.
  7. *
  8. * @note
  9. * Copyright (C) 2013-2014 Nuvoton Technology Corp. All rights reserved.
  10. *****************************************************************************/
  11. #include <stdio.h>
  12. #include "Nano100Series.h"
  13.  
  14. void WDT_IRQHandler(void)
  15. {
  16.  
  17. // Clear WDT interrupt flag
  18. WDT_CLEAR_TIMEOUT_INT_FLAG();
  19.  
  20. // Check WDT wake up flag
  21. if(WDT_GET_TIMEOUT_WAKEUP_FLAG()) {
  22. printf("Wake up by WDT\n");
  23. // Clear WDT wake up flag
  24. WDT_CLEAR_TIMEOUT_WAKEUP_FLAG();
  25. }
  26.  
  27. }
  28.  
  29. void SYS_Init(void)
  30. {
  31.  
  32. /*---------------------------------------------------------------------------------------------------------*/
  33. /* Init System Clock */
  34. /*---------------------------------------------------------------------------------------------------------*/
  35. /* Unlock protected registers */
  36. SYS_UnlockReg();
  37.  
  38. /* Enable External XTAL (4~24 MHz) */
  39. CLK_EnableXtalRC(CLK_PWRCTL_HXT_EN_Msk);
  40.  
  41. /* Enable LIRC */
  42. CLK_EnableXtalRC(CLK_PWRCTL_LIRC_EN_Msk);
  43.  
  44. /* Waiting for 12MHz clock ready */
  45. CLK_WaitClockReady( CLK_CLKSTATUS_HXT_STB_Msk);
  46.  
  47. /* Waiting for LIRC clock ready */
  48. CLK_WaitClockReady( CLK_CLKSTATUS_LIRC_STB_Msk);
  49.  
  50. /* Switch HCLK clock source to HXT */
  51. CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HXT,CLK_HCLK_CLK_DIVIDER(1));
  52.  
  53. /* Enable IP clock */
  54. CLK_EnableModuleClock(UART0_MODULE);
  55. CLK_EnableModuleClock(WDT_MODULE);
  56.  
  57. /* Select IP clock source */
  58. CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_UART_CLK_DIVIDER(1));
  59. CLK_SetModuleClock(WDT_MODULE, 0, 0);
  60.  
  61. /* Update System Core Clock */
  62. /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
  63. SystemCoreClockUpdate();
  64.  
  65. /*---------------------------------------------------------------------------------------------------------*/
  66. /* Init I/O Multi-function */
  67. /*---------------------------------------------------------------------------------------------------------*/
  68. /* Set GPB multi-function pins for UART0 RXD and TXD */
  69. SYS->PB_L_MFP &= ~(SYS_PB_L_MFP_PB0_MFP_Msk | SYS_PB_L_MFP_PB1_MFP_Msk);
  70. SYS->PB_L_MFP |= (SYS_PB_L_MFP_PB1_MFP_UART0_TX | SYS_PB_L_MFP_PB0_MFP_UART0_RX);
  71. /* Lock protected registers */
  72. SYS_LockReg();
  73.  
  74. }
  75.  
  76. int32_t main (void)
  77. {
  78. /* Init System, IP clock and multi-function I/O
  79. In the end of SYS_Init() will issue SYS_LockReg()
  80. to lock protected register. If user want to write
  81. protected register, please issue SYS_UnlockReg()
  82. to unlock protected register if necessary */
  83. SYS_Init();
  84.  
  85. /* Init UART to 115200-8n1 for print message */
  86. UART_Open(UART0, 115200);
  87.  
  88. printf("\nThis sample code demonstrate using WDT to wake system up from power down mode\n");
  89.  
  90. // WDT register is locked, so it is necessary to unlock protect register before configure WDT
  91. SYS_UnlockReg();
  92.  
  93. // WDT timeout every 2^14 WDT clock, disable system reset, enable wake up system
  94. WDT_Open(WDT_TIMEOUT_2POW14, 0, FALSE, TRUE);
  95.  
  96. // Enable WDT timeout interrupt
  97. WDT_EnableInt();
  98. NVIC_EnableIRQ(WDT_IRQn);
  99.  
  100. while(1) {
  101. // Wait 'til UART FIFO empty to get a cleaner console out
  102. while(!UART_IS_TX_EMPTY(UART0));
  103. CLK_PowerDown();
  104. }
  105.  
  106. }
  107.  
  108. /*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/

这其中还有一些我没有讲的太清楚,放心,我会让各位都清楚明白的,我会慢慢去修正,欢迎您的指点

失败正常,跌倒也正常,但是丧失了自信和斗志,只会沉沦,永远见不到太阳。常常幻想有一天我怎样怎样,但是梦醒来的时候,却发现自己一无所有,要想得到,还得继续奔跑。

nano100B的看门狗讲解的更多相关文章

  1. STM32F0xx_看门狗(独立+窗口)配置详细过程

    Ⅰ.概述 对于看门狗,我觉得做单片机或者嵌入式开发的人员来说并不陌生,今天总结STM32F0看门狗的功能,F0的看门狗有两种:独立和窗口看门狗. 今天提供两种看门狗的软件工程实例,供大家下载. 两种看 ...

  2. Linux编程之《看门狗进程》

    Intro 当我们编写服务器代码时,为了让自己的服务器在意外崩溃时能够及时的重启,软件看门狗就显示出它的作用了,该看门狗进程是通过fork一个子进程(业务进程),父进程一旦捕获到了子进程的结束信号就重 ...

  3. S5PV210 看门狗定时和复位

    第一节 S5PV210的看门狗定时器S5PV210上的看门狗定时器相当于一个普通的16bit的定时器,它与PWM定时器的区别是看门狗定时器可以产生reset信号而PWM定时器不能,S5PV210看门狗 ...

  4. FreeRTOS 独立看门狗监测任务执行状态

    以下转载自安富莱电子: http://forum.armfly.com/forum.php 通过前面的几个章节,我们基本已经完成了 FreeRTOS 所有功能的讲解,本章节为大家介绍一种使用独立看门狗 ...

  5. 第35章 WWDG—窗口看门狗—零死角玩转STM32-F429系列

    第35章     WWDG—窗口看门狗 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...

  6. 第34章 IWDG—独立看门狗—零死角玩转STM32-F429系列

    第34章     IWDG—独立看门狗 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...

  7. tiny4412 裸机程序 三、关闭看门狗和调用C程序【转】

    本文转载自:http://blog.csdn.net/eshing/article/details/37112779 一.原理说明 上是章中大家可能有会觉得奇怪,CPU不是有看门狗嘛?为什么CPU没有 ...

  8. 服务器watchdog看门狗的理解

    1.什么是watchdog?watchdog,中文名称叫做“看门狗”,全称watchdog timer,从字面上我们可以知道其实它属于一种定时器.然而它与我们平常所接触的定时器在作用上又有所不同.普通 ...

  9. STM32之看门狗(独立与窗口)

    广大的互联网网友们,大家早上中午晚上好,我是某某某..对于狗..看过<忠犬八公>的我.无不深深的被狗的义气与灵气所震撼..我也觉得在所有mcu中用看门狗来形容让系统复位的功能是很恰当的.也 ...

随机推荐

  1. c++之五谷杂粮---3

    3.1如果同一作用域内的几个函数名字相同但形参列表不同,我们称之为重载函数. 3.1.1不允许两个函数除了返回类型外所有的要素都相同.(这也是很好解释的) #include<iostream&g ...

  2. 基于jQuery商品分类选择提交表单代码

    分享一款基于jQuery商品分类选择提交表单代码.这是一款基于jQuery实现的商品信息选择列表表单提交代码. 在线预览   源码下载 实现的代码: <div class="yList ...

  3. 初看mysql源代码之mysql.cc

    在mysql的源代码目录中,sql目录是mysql源代码中经常变化的目录之一,也是MySQL服务器内核最为核心和重要的目录. sql目录除了包含mysqld.cc这一MySQL main函数所在文件外 ...

  4. C语言 · 文本加密

    算法提高 9-2 文本加密   时间限制:1.0s   内存限制:256.0MB      问题描述 先编写函数EncryptChar,按照下述规则将给定的字符c转化(加密)为新的字符:"A ...

  5. CentOS5.4安装redmine详细步骤

    >>>>概述<<<< 这里不解释什么是redmine及用来做什么,如果不知道用来做什么,估计也不会把它安装到CentOS5.4上.哈哈…… 以下为详细的 ...

  6. nodejs系列笔记02---模块路径解析

    模块路径解析规则 参考这篇博客 我们已经知道,require函数支持斜杠(/)或盘符(C:)开头的绝对路径,也支持./开头的相对路径.但这两种路径在模块之间建立了强耦合关系,一旦某个模块文件的存放位置 ...

  7. Spring下获取项目根路径--good

    Spring 在 org.springframework.web.util 包中提供了几个特殊用途的 Servlet 监听器,正确地使用它们可以完成一些特定需求的功能.比如某些第三方工具支持通过 ${ ...

  8. Windows上建立、取消共享文件夹

    建立共享文件夹 1.创建一个文件夹test 2.右键属性,点击共享 4.在另外一台机器上访问该共享文件 取消共享文件夹 右键属性,点击高级共享

  9. Java中的内存处理机制和final、static、final static总结

    Java中的内存处理机制和final.static.final static总结   装载自:http://blog.csdn.net/wqthaha/article/details/20923579 ...

  10. js中以键值对的形式当枚举

    js中以键值对的形式当枚举var Penum= { B: "姓名", C: "所属居委", D: "证件号", E: "性别&qu ...