1.外部中断实验

1.外部中断概述

1.STM32F103 的19 个外部中断

  1. ** STM32 的每个 IO 都可以作为外部中断的中断输入口** STM32F103 的中断控制器支持 19 个外部 中断/事件请求。<br /> STM32F103 19 个外部中断为:<br /> 线 0~15:对应外部 IO 口的输入中断。<br /> 线 16:连接到 PVD 输出。<br /> 线 17:连接到 RTC 闹钟事件。<br /> 线 18:连接到 USB 唤醒事件。


2. STM32的 IO 口与中断线的对应关系

  1. GPIO 的管教 GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线 0~15。这样每个中断线对应了最多 7 IO 16*7=112 <br /> ![(VPS_[%(HP%5YI3F_S1YBGO.png](https://cdn.nlark.com/yuque/0/2021/png/22507599/1630119523512-1030bf59-36e0-498c-9c62-5941d130c0a7.png#clientId=u440e4b6f-ebb0-4&from=paste&height=447&id=ubc328582&margin=%5Bobject%20Object%5D&name=%28VPS_%5B%25%28HP%255YI3F_S1YBGO.png&originHeight=745&originWidth=916&originalType=binary&ratio=1&size=112867&status=done&style=none&taskId=u2c186abd-ebb5-48f2-8fe7-a92c7de8d6b&width=550)<br /> ** 注意:中断线每次只能连接到 1 个 IO 口上 **<br /> **对于每个中断线,我们可以设置相应的触发方式(上升沿触发,下降沿触发,边沿触发)以及时能。**<br />

3.中断服务函数

  1. IO口外部中断在中断向量表中只分配了7个中断向量<br /> <br /> ![`$TVA8K5WS@3YMEO9G93K`X.png](https://cdn.nlark.com/yuque/0/2021/png/22507599/1630121155125-aef66a2a-2c25-49fe-9f22-6cb0536893d7.png#clientId=u440e4b6f-ebb0-4&from=paste&height=201&id=u3a50901e&margin=%5Bobject%20Object%5D&name=%60%24TVA8K5WS%403YMEO9G93K%60X.png&originHeight=276&originWidth=619&originalType=binary&ratio=1&size=54167&status=done&style=none&taskId=u6e86799e-46d9-418b-b83c-e9c9ef47ddc&width=450)<br /> 中断线 0-4 每个中断线对应一个中断函数, 中断线 5-9 共用中断函数 EXTI9_5_IRQHandler,中<br />断线 10-15 共用中断函数 EXTI15_10_IRQHandler。 <br /> ** 中断函数服务列表**


EXPORT EXTI0_IRQHandler
EXPORT EXTI1_IRQHandler
EXPORT EXTI2_IRQHandler
EXPORT EXTI3_IRQHandler
EXPORT EXTI4_IRQHandler
EXPORT EXTI9_5_IRQHandler
EXPORT EXTI15_10_IRQHandler

2.外部中断常用库函数

  1. ** 配置 GPIO 与中断线的映射关系 **<br /> void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) <br /> ** 中断线上中断的初始化 **<br /> void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)<br /> ** 判断某个中断线上的中断是否发生(标志位是否置位), 这个函数一般使用在中断服务函数的开头判断中断是否发生 **<br /> ITStatus EXTI_GetITStatus(uint32_t EXTI_Line) <br /> ** 清除某个中断线上的中断标志位 这个函数一般应用在中断服务函数结束之前,清除中断标志位** <br /> void EXTI_ClearITPendingBit(uint32_t EXTI_Line) <br /> <br /> ** 使用 IO 口外部中断的一般步骤 **<br /> 1 初始化 IO 口为输入<br /> 2 开启 AFIO 时钟 (一定要使能AFIO时钟)<br /> 3 设置 IO 口与中断线的映射关系<br /> 4 初始化线上中断, 设置触发条件等<br /> 5 配置中断分组(NVIC),并使能中断<br /> 6 编写中断服务函数<br /> 7 清除中断标志位<br /> <br />

3.硬件设计

  1. 和之前的按键输入实验一样,可参考Task4<br />

4.软件设计

  1. 主要介绍新增的exit.c文件,总共包含 5 个函数。一个是外部中断初始化函数 void EXTIX_Init(void),另外 4个都是中断服务函数 <br /> 1.外部中断初始化函数严格按照IO口外部中断的步骤进行<br /> 2.中断服务函数相似,大致内容是先延时 10ms 以消抖,再检测按键是否还是为低电平,如果是,则执行此次操作(翻转 LED0 控制信号),如果不是,则直接跳过,在最后清除已经发生的中断请求。

2.独立看门狗实验

1.看门狗概述

  1. ** 看门狗原理 :**单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环, 看门狗电路就是为了避免这种情况的发生。 看门狗的作用就是在一定时间内(通过定时计数器实现) 没有接收喂狗信号<br />(表示 MCU 已经挂了),便实现处理器的自动复位重启(发送复位信号)。 <br /> <br /> ** 解决的问题:**在启动正常运行的时候,系统不能复位。<br /> 在系统跑飞(程序异常执行)的情况下,系统复位,程序重新执行。<br /> <br /> ** 两种看门狗**<br /> STM32F10xxx内置两个看门狗,提供了更高的安全性、时间的精确性和使用的灵活性。两个看门狗设备(独立看门狗和窗口看门狗)可用来检测和解决由软件错误引起的故障;当计数器达到给定的超时值时,触发一个中断(仅适用于窗口型看门狗)或产生系统复位。<br /> **独立看门狗(IWDG)**由专用的低速时钟(LSI)驱动,即使主时钟发生故障它也仍然有效。<br /> IWDG最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精<br />度要求较低的场合。
  2. **窗口看门狗由**从APB1时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的操作。<br /> WWDG最适合那些要求看门狗在精确计时窗口起作用的应用程序。

2.独立看门狗

1.功能描述

  1. 在键寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值0xFFF递减计数。当计数器计数到末尾0x000时,会产生一个复位信号(IWDG_RESET)。<br /> 无论何时,只要在键寄存器IWDG_KR中写入0xAAAA IWDG_RLR中的值就会被重新加载到计数器,从而避免产生看门狗复位 <br /> ![S~~DXSFK{9]@X57)(CV9NGO.png](https://cdn.nlark.com/yuque/0/2021/png/22507599/1630131151461-710de975-b0fc-4fab-b0d7-c4c085674912.png#clientId=ufaa12722-5d33-4&from=paste&height=193&id=u689b9958&margin=%5Bobject%20Object%5D&name=S~~DXSFK%7B9%5D%40X57%29%28CV9NGO.png&originHeight=385&originWidth=1145&originalType=binary&ratio=1&size=77096&status=done&style=none&taskId=u9eb24829-26ef-42a4-b30e-eaa1233d933&width=572.5)
  2. ** 注意:** IWDG_PRIWDG_RLR IWDG_KR寄存器中写入0x5555。以不同的值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护。重装载操作(即写入0xAAAA)也会启动写保护功能。


2. 四种寄存器

BF1D0C]B34@{)RE8]YDNIJ1.png
![@7X4T18YA~0@PB(R$L9`L8.png
1EMBF8DE6_ODJLE9XAQL)9O.png
![678TN)4KA)XU3~I{ZWXO`O.png

3. 独立看门狗超时时间

  1. ![NYTVJ8]K6H~$}G~GL`HA{]Y.png](https://cdn.nlark.com/yuque/0/2021/png/22507599/1630131606360-743adde3-649a-4b7f-96c6-3ea3ec4c8c72.png#clientId=ufaa12722-5d33-4&from=paste&height=146&id=u41c59d15&margin=%5Bobject%20Object%5D&name=NYTVJ8%5DK6H~%24%7DG~GL%60HA%7B%5DY.png&originHeight=191&originWidth=522&originalType=binary&ratio=1&size=20142&status=done&style=none&taskId=u817ae8ed-d5dc-40b7-a63b-be845e2b1a4&width=400)<br /> 公式:**Tout=(4*2^prer)*rlr / 40 ms**<br />**prer是IWDG_PR寄存器2进制化为十进制的值,rlr就是IWDG_RLR中的值,Tout就是看门狗每次的倒计时。**

4. 启动步骤

  1. 1 取消寄存器写保护(向 IWDG_KR 写入 0X5555 <br /> IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable) <br /> 2 设置独立看门狗的预分频系数和重装载值 <br /> void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); //设置 IWDG 预分频值 <br /> void IWDG_SetReload(uint16_t Reload); //设置 IWDG 重装载值 <br /> 3 重载计数值喂狗(向 IWDG_KR 写入 0XAAAA)<br /> IWDG_ReloadCounter() <br /> 4 启动看门狗(向 IWDG_KR 写入 0XCCCC)<br /> IWDG_Enable(); //使能 IWDG <br /> <br />

5. 软件设计

  1. 引入了 wdg.c ,代码如下<br />
  1. #include "wdg.h"
  2. //初始化独立看门狗
  3. //prer:分频数:0~7(只有低 3 位有效!)
  4. //分频因子=4*2^prer.但最大值只能是 256!
  5. //rlr:重装载寄存器值:低 11 位有效.
  6. //时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
  7. void IWDG_Init(u8 prer,u16 rlr)
  8. {
  9. IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //①使能对寄存器 I 写操作
  10. IWDG_SetPrescaler(prer); //②设置 IWDG 预分频值:设置 IWDG 预分频值
  11. IWDG_SetReload(rlr); //②设置 IWDG 重装载值
  12. IWDG_ReloadCounter(); //③按照 IWDG 重装载寄存器的值重装载 IWDG 计数器
  13. IWDG_Enable(); //④使能 IWDG
  14. }
  15. //喂独立看门狗
  16. void IWDG_Feed(void)
  17. {
  18. IWDG_ReloadCounter();//reload
  19. }
  1. void IWDG_Init(u8 prer u16 rlr)是独立看门狗初始化函数 ,通过这两个参数,就可以大概知道看门狗 复位的时间周期 。<br /> void IWDG_Feed(void)函数,该函数用来喂狗 。<br /> **主函数main的大致运行:**<br /> 先初始化一下系统代码,然后启动按键输入和看门狗,在看门狗开启后马山点亮 LED0DS0),并进入死循环等待按键的输入,一旦 WK_UP 有按键,则喂狗,否则等待 IWDG 复位的到来。