学习内容:
第二十八讲:外部中断实验-EXTI
1.stm32中有16个IO口中断,每个IO口中断对应这一个数。例如GPIOx.1对应这EXIT1(x为A到G)映射表如下:
注意:在EXTI中断中,一个EXTI只能对应一个GPIO口,例如,不能将PA1和PB1设置为外部中断,只能选择其中之一。
2.stm32中断向量表的5-9和10-15各只有一个中断服务函数,因此如果同时打开其中的两个或多个,都会进入一个中断服务函数执行。
3.外部中断一般配置步骤
注意:①必须开启复用时钟,否则无法正常运行。
②必须手动清除中断标志位,保证下一次中断的正常进行。
4.代码实现
main()函数
#include "stm32f10x.h"
#include "bsp_exti.h"
#include "bsp_led.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
LED_GPIO_Config();
EXTI_Key_Config();
while(1)
{
}
}
LED 头文件
#ifndef __BSP_LED_H
#define __BSP_LED_H
#include "stm32f10x.h"
#define LED_G_GPIO_PIN GPIO_Pin_0
#define LED_G_GPIO_PORT GPIOB
#define LED_G_GPIO_CLK RCC_APB2Periph_GPIOB
#define ON 1
#define OFF 0
#define LED_G_TOGGLE {LED_G_GPIO_PORT->ODR ^=GPIO_Pin_0;}
#define LED(a) if(a) GPIO_ResetBits(LED_G_GPIO_PORT,LED_G_GPIO_PIN); else GPIO_SetBits(LED_G_GPIO_PORT,LED_G_GPIO_PIN);
void LED_GPIO_Config(void);
#endif
LED C文件
#include "bsp_led.h"
void LED_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(LED_G_GPIO_CLK, ENABLE);
GPIO_InitStruct.GPIO_Pin=LED_G_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(LED_G_GPIO_PORT, &GPIO_InitStruct);
}
外部中断头文件
#ifndef __BSP_EXTI_H
#define __BSP_EXTI_H
#include "stm32f10x.h"
#define KEY2_INT_GPIO_PIN GPIO_Pin_13
#define KEY2_INT_GPIO_PORT GPIOC
#define KEY2_INT_GPIO_CLK RCC_APB2Periph_GPIOC
void EXTI_Key_Config(void);
#endif
外部中断C文件
#include "bsp_exti.h"
static void EXIT_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_Initstruct;
NVIC_Initstruct.NVIC_IRQChannel=EXTI15_10_IRQn;
NVIC_Initstruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority=1;
NVIC_Initstruct.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_Initstruct);
}
void EXTI_Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
EXIT_NVIC_Config();
RCC_APB2PeriphClockCmd(KEY2_INT_GPIO_CLK, ENABLE);
GPIO_InitStruct.GPIO_Pin=KEY2_INT_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStruct);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);
EXTI_InitStruct.EXTI_Line = EXTI_Line13;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStruct);
}
注意:此处的时钟开启必须使用AFIO时钟,若不开启,则会导致外部中断无法执行。
中断服务函数
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line13)!=RESET)
{
LED_G_TOGGLE;
}
EXTI_ClearITPendingBit(EXTI_Line13);
}
第二十九讲:独立看门狗实验-IWDG
1.看门狗是在单片机受到外界电磁场干扰而导致程序跑飞进入死循环的情况下,用于检测单片机程序运行状态的模块或者芯片。
2.看门狗的工作原理是在系统程序异常执行的情况下,将系统复位,让程序正常执行。
3.stm32有两种看门狗,分别为独立看门狗和窗口看门狗。
独立看门狗:由专用低速时钟驱动,即使在主时钟故障也能工作。适合用于在主程序之外完全独立工作且对精度要求较低的场合。
窗口看门狗:由APB1时钟分频得来,通过可配置时间窗口来检测应用程序非正常的过迟或过早操作。适合用于对精度要求较高的场合。
4.看门狗功能描述
注意:第一次开启看门狗时,会从0xFFF开始递减,而不是自己设定的计数值,需要喂狗之后才能从自己设定的计数值开始递减。
5.溢出时间计算公式
公式理解:一个最短周期为时钟频率LSI分频后的频率的倒数,则自己想设定的周期是在最短周期的基础上乘以设定的倍数(即RLR的值)。
6.操作步骤
7.代码分析
main()函数
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_key.h"
#include "iwdg.h"
#include "bsp_systick.h"
int main(void)
{
uint8_t key;
LED_GPIO_Config();
KEY_GPIO_Config();
systick_Delay_ms(500);
LED(ON);
IWDG_Config();
while(1)
{
key=Key_Scan(0);
if(key==LED1)
IWDG_ReloadCounter();
}
}
看门狗头文件
#ifndef __IWDG_H
#define __IWDG_H
#include "stm32f10x.h"
#define RELOADNUM 625
void IWDG_Config(void);
#endif
看门狗C文件
#include "iwdg.h"
void IWDG_Config(void)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_64);
IWDG_SetReload(RELOADNUM);
IWDG_ReloadCounter();
IWDG_Enable();
}
注意:若希望第一次就使用自己设置的初值,必须用IWDG_ReloadCounter()来重装载寄存器,配置装载值为1s。