1.窗口看门狗

1.窗口看门狗概述

  1. 窗口看门狗就是因为其喂狗时间是一个有上下限的范围内,可以通过设定相关寄存器,设定其上限时间(下限固定),喂狗的时间不能过早也不能过晚。<br /> ** 窗口看门狗优势**<br /> 对于一般的看门狗,程序可以在它产生复位前的任意时刻刷新看门狗,但是这样有一个隐患,有可能程序跑乱了又跑回正常的地方,或者跑乱的程序正好执行了刷新看门狗操作,这样的情况下一按的看门狗就检测不出来故障了;但是如果使用窗口看门狗,程序员可以根据程序正常执行的时间设置刷新看门狗的一个时间窗口,保证不会提前刷新看门狗,也不会滞后刷新看门狗,这样可以检测出程序没有按照正常的路径运行,非正常地跳过了某些程序段的情况。<br /> ** 窗口看门狗工作示意图**<br /> ![3S63MVE[K_B8OFS_BG{4SPE.png](https://cdn.nlark.com/yuque/0/2021/png/22507599/1630206270942-82f29b6a-c475-43ef-9efc-d2fccca2eb64.png#clientId=u23289f5b-2610-4&from=paste&height=266&id=u3acad8fe&margin=%5Bobject%20Object%5D&name=3S63MVE%5BK_B8OFS_BG%7B4SPE.png&originHeight=475&originWidth=715&originalType=binary&ratio=1&size=37952&status=done&style=none&taskId=u7156e1ac-5e84-4446-888c-59d0c636b80&width=400)<br /> 喂狗范围:W【6:0】到3Fh<br /> 当窗口看门狗的计数器在上窗口值之外被刷新,或者低于下窗口值都会产生复位。 <br /> <br /> ** 窗口看门狗框图**<br /> ![JB1T%~MOO$W8[ES)6SK(`58.png](https://cdn.nlark.com/yuque/0/2021/png/22507599/1630206417835-ee8f499d-ff15-4847-9bb8-26177498e497.png#clientId=u23289f5b-2610-4&from=paste&height=215&id=uccb38294&margin=%5Bobject%20Object%5D&name=JB1T%25~MOO%24W8%5BES%296SK%28%6058.png&originHeight=302&originWidth=563&originalType=binary&ratio=1&size=29979&status=done&style=none&taskId=u5e8afef2-8850-4460-9d23-541539f7d7b&width=400)
  2. ** 窗口看门狗工作过程总结**<br /> STM32F的窗口看门狗中有一个7位的递减计数器T[6:0],它会在出现下述2种情况之一时产生看门狗复位:<br />①当喂狗的时候如果计数器的值大于某一设定数值W[6:0]时,此设定数值在WWDG_ CFR寄存器定义。<br />②当计数器的数值从0x40减到0x3F时[T6位跳变到0 ]。<br /> 如果启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI),它可以用于喂狗以避免WWDG复位。
  1. ** 窗口看门狗的超时公式如下:**<br /> Twwdg=(4096× 2^WDGTB× (T[5:0]+1)) /Fpclk1;<br /> 其中:<br /> Twwdg WWDG 超时时间(单位为 ms)<br /> Fpclk1 APB1 的时钟频率(单位为 Khz)<br /> WDGTB WWDG 的预分频系数<br /> T[5:0]:窗口看门狗的计数器低 6
  1. <br />**注意事项:**1.一定要确保上窗口值W[6:0]必须大于窗口值 0X40,否则窗口就不存在了。 <br /> 2.窗口看门狗时钟来源PCLK1(APB1总线时钟)分频后。

2.常用寄存器和库函数

1.寄存器

  1. ![5U4_@EN0BN0J95V5XE6GPZW.png](https://cdn.nlark.com/yuque/0/2021/png/22507599/1630208395501-49010e62-8ba5-4b17-a5f5-32866300076a.png#clientId=u23289f5b-2610-4&from=paste&height=250&id=uac3a96fa&margin=%5Bobject%20Object%5D&name=5U4_%40EN0BN0J95V5XE6GPZW.png&originHeight=321&originWidth=643&originalType=binary&ratio=1&size=53386&status=done&style=none&taskId=u7b18c26a-3915-4a18-af99-aee1fcc54c0&width=500)<br /> 警告:当写入 WWDG_CR 寄存器时,始终置 T6 位为’1’以避免立即产生一个复位。
  2. ![}5X$PE6I82]]_S]9_VH_@_T.png](https://cdn.nlark.com/yuque/0/2021/png/22507599/1630208456744-355454db-cbf0-4d6c-a186-a31727197fa1.png#clientId=u23289f5b-2610-4&from=paste&height=313&id=u54616eb2&margin=%5Bobject%20Object%5D&name=%7D5X%24PE6I82%5D%5D_S%5D9_VH_%40_T.png&originHeight=403&originWidth=643&originalType=binary&ratio=1&size=69554&status=done&style=none&taskId=u91f3a018-f223-4148-9ec1-4cfbf7ec1f1&width=500)<br /> 该位中的 EWI 是提前唤醒中断, 一般用该位来设置中断,当窗口看门狗的计数器值减到 0X40 的时候,如果该位设置,并开启了中断,则会产生中断,我们可以在中断里面向 WWDG_CR 重新写入计数器的值,来达到喂狗的目的。 <br /> <br /> ![28T]FLBA3N_S8X%$I)Y)ZWD.png](https://cdn.nlark.com/yuque/0/2021/png/22507599/1630208483298-440abd41-afb4-419b-b7bd-b8456e4c9c31.png#clientId=u23289f5b-2610-4&from=paste&height=205&id=ua6784b9b&margin=%5Bobject%20Object%5D&name=28T%5DFLBA3N_S8X%25%24I%29Y%29ZWD.png&originHeight=264&originWidth=644&originalType=binary&ratio=1&size=39731&status=done&style=none&taskId=u071f98fd-20d7-47e2-ba65-237337f9ca3&width=500)

2.库函数

  1. 1 使能 WWDG 时钟 <br /> RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); <br /> 2 设置窗口值和分频数 <br /> void WWDG_SetWindowValue(uint8_t WindowValue); 用来设置看门狗的上窗口值 <br /> void WWDG_SetPrescaler(uint32_t WWDG_Prescaler); <br /> 3 开启 WWDG 中断并分组 <br /> WWDG_EnableIT(); <br /> 4 设置计数器初始值并使能看门狗 <br /> void WWDG_Enable(uint8_t Counter) <br /> 5 编写中断服务函数 <br />

3.软件设计

  1. //保存 WWDG 计数器的设置值,默认为最大
  2. u8 WWDG_CNT=0x7f;
  3. //初始化窗口看门狗
  4. //tr :T[6:0],计数器值
  5. //wr :W[6:0],窗口值
  6. //fprer:分频系数(WDGTB) ,仅最低 2 位有效
  7. //Fwwdg=PCLK1/(4096*2^fprer).
  8. void WWDG_Init(u8 tr,u8 wr,u32 fprer)
  9. {
  10. RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG 时钟使能
  11. WWDG_CNT=tr&WWDG_CNT; //初始化 WWDG_CNT.
  12. WWDG_SetPrescaler(fprer); //设置 IWDG 预分频值
  13. WWDG_SetWindowValue(wr); //设置窗口值
  14. WWDG_Enable(WWDG_CNT); //使能看门狗,设置 counter
  15. WWDG_ClearFlag(); //清除提前唤醒中断标志位
  16. WWDG_NVIC_Init(); //初始化窗口看门狗 NVIC
  17. WWDG_EnableIT(); //开启窗口看门狗中断
  18. }
  19. //重设置 WWDG 计数器的值
  20. void WWDG_Set_Counter(u8 cnt)
  21. {
  22. WWDG_Enable(cnt); //使能看门狗,设置 counter .
  23. }
  24. //窗口看门狗中断服务程序
  25. void WWDG_NVIC_Init()
  26. {
  27. NVIC_InitTypeDef NVIC_InitStructure;
  28. NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; //WWDG 中断
  29. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占 2 子优先级 3 组 2
  30. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //抢占 2,子优先级 3,组 2
  31. NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  32. NVIC_Init(&NVIC_InitStructure); //NVIC 初始化
  33. }
  34. void WWDG_IRQHandler(void)
  35. {
  36. WWDG_SetCounter(WWDG_CNT); //当禁掉此句后,窗口看门狗将产生复位
  37. WWDG_ClearFlag(); //清除提前唤醒中断标志位
  38. LED1=!LED1; //LED 状态翻转
  39. }
  1. 函数 void WWDG_Init(u8 tr u8 wr u8 fprer)用来设置 WWDG 的初始化值。包括看门狗计数器的值和看门狗比较值等。 <br /> 中断服务函数里面, 先重设窗口看门狗的计数器值,然后清除提前唤醒中断标志。最后对 LED1DS1)取反,来监测中断服务函数的执行了状况
  2. main函数主要是 通过 LED0(DS0)来指示是否正在初始化。而 LED1(DS1)用来指示是否发生了中断。我们先让 LED0 300ms,然后关闭以用于判断是否有复位发生了。在初始化 WWDG 之后,我们回到死循环,关闭 LED1,并等待看门狗中断的触发/复位。 <br />

2.通用定时器基本原理

1.通用定时器概述

1.三种定时器

  1. ![MY9SQF7JZBGM~U04`C$M657.png](https://cdn.nlark.com/yuque/0/2021/png/22507599/1630209667459-8a6fe2bd-cebe-4bb6-b67a-7641827c0fa5.png#clientId=u23289f5b-2610-4&from=paste&height=217&id=u72cc7a4e&margin=%5Bobject%20Object%5D&name=MY9SQF7JZBGM~U04%60C%24M657.png&originHeight=406&originWidth=1215&originalType=binary&ratio=1&size=459721&status=done&style=none&taskId=uf79ffea2-06c5-47d0-9789-1922f9a5da7&width=650)

2.通用定时器特点

  1. STM3F1 的通用 TIMx (TIM2 TIM3 TIM4 TIM5)定时器功能包括:<br /> 1)16 位向上、向下、向上/向下自动装载计数器(TIMx_CNT)。<br /> 2)16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 165535 之间的任意数值。<br /> 3 4 个独立通道(TIMx_CH1~4),这些通道可以用来作为:<br /> A.输入捕获<br /> B.输出比较<br /> C PWM 生成(边缘或中间对齐模式)<br /> D.单脉冲模式输出<br /> 4)可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。 <br /> 5)如下事件发生时产生中断/DMA:<br /> 1.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)<br /> 2.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)<br /> 3.输入捕获<br /> 4.输出比较<br /> 5.支持针对定位的增量(正交)编码器和霍尔传感器电路<br /> 6.触发输入作为外部时钟或者按周期的电流管理 <br /> 前面4种比较常用<br /> STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。 使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。 <br />

3. 计数器模式

  1. 通用定时器可以向上计数、向下计数、双向计数模式。<br /> ①向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。<br /> ②向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。<br /> ③中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。<br /> ![%D~`8NOGWO%KRJO(3UJSILP.png](https://cdn.nlark.com/yuque/0/2021/png/22507599/1630210251902-bc85f579-2d3a-49d2-aa6a-612ddae9bc35.png#clientId=u23289f5b-2610-4&from=paste&height=84&id=u139fa45e&margin=%5Bobject%20Object%5D&name=%25D~%608NOGWO%25KRJO%283UJSILP.png&originHeight=121&originWidth=578&originalType=binary&ratio=1&size=6858&status=done&style=none&taskId=u7630f36a-9f53-48bd-86c1-5a0f8dcc71c&width=400)

2.通用定时器工作过程

  1. ** 通用定时器框图**
  2. ![Z$CU_BA{[%3CL0H)_AR@QNU.png](https://cdn.nlark.com/yuque/0/2021/png/22507599/1630210893662-2ad90222-686f-48a0-a43c-f343f044adae.png#clientId=u23289f5b-2610-4&from=paste&height=385&id=u1ab95d91&margin=%5Bobject%20Object%5D&name=Z%24CU_BA%7B%5B%253CL0H%29_AR%40QNU.png&originHeight=654&originWidth=849&originalType=binary&ratio=1&size=189581&status=done&style=none&taskId=u2da38359-32b9-4d93-bbbd-c9179bb9cd5&width=500)

1.定时器的时钟来源

  1. 定时器的时钟来源有 4 个:<br /> 1 内部时钟(CK_INT)<br /> 2 外部时钟模式 1:外部输入脚(TIx)<br /> 3 外部时钟模式 2:外部触发输入(ETR)<br /> 4 内部触发输入(ITRx):使用 A 定时器作为 B 定时器的预分频器(A B 提供时钟)。 <br />

2.时基单元

  1. 时基单元包含:<br /> 计数器寄存器(TIMx_CNT)<br /> 预分频器寄存器 (TIMx_PSC)<br /> 自动装载寄存器 (TIMx_ARR) <br />

3.输入捕获

  1. 当检测到ICx信号上相应的边沿后,计数器的当前值被锁存到捕获/比较寄存器(TIMx_CCRx)中。当捕获事件发生时,相应的CCxIF标志(TIMx_SR寄存器)被置’1’,如果使能了中断或者DMA操作,则将产生中断或者DMA操作。如果捕获事件发生时CCxIF标志已经为高,那么重复捕获标志CCxOF(TIMx_SR寄存器)被置’1’。写CCxIF=0可清除CCxIF,或读取存储在TIMx_CCRx寄存器中的捕获数据也可清除CCxIF。写CCxOF=0可清除CCxOF <br />

4.输出比较

  1. 比如在比较寄存器中预先设定一个值,计数器从初始值到装载值之间计数时,当正好等于比较寄存器中的预设值时,控制TIMx_CH1——TIMx_CH4通道输出低电平或者高电平,这样随着计数器不断的计数,就可以获得一个脉冲,通过调整预设值,就可以调整脉冲宽度,调整初始值和装载值就可以调整周期。
  2. ** 注意输入捕获和输出比较不可以同时进行**
  3. 之后会通过实验详细讲解4个部分