@/"
1> 为什么需要中断这个功能?
随着延时时间的加长,按键为啥会失灵?
/**---------------- 按键控制灯程序 ------------**/
int main ()
{
led_init();
key_init();
while (1) {
uint8_t val = key_read_bit(KEY_1);
if (val == 1)
led_on();
else
led_off();
delay(0xFFFFFFF);
}
}
1.1> 分析问题
结论:典型轮询结构(Polling)
1.2> 目标结构
如果按键控制灯程序,可以在任何时刻打断主循环并执行,就解决问题了
理想流程:
按下按键,触发中断,
CPU能很快检测到;
执行控制灯的函数;
这种结构称为:前后台结构 ;
主程序称为后台(background) 无限大循环;
中断程序称为 前台(Foreground) 打断主程序;
2> F407硬件组成
请你设计个带中断功能CPU?
先参考下ARM公司的… 通过阅读手册,查看结构体,硬件框图,操作函数等从而了解他
就像了解充电器,我们可以拆开他,或阅读说明,或看别人使用;
回顾下,51单片机的中断结构:
2.1> EXTI
外部中断控制器,EXTI: External interrupt / event controller
2.1.1 > 结构体描述
typedef struct
{
__IO uint32_t IMR; /*!< EXTI Interrupt mask register, Address offset: 0x00 */
__IO uint32_t EMR; /*!< EXTI Event mask register, Address offset: 0x04 */
__IO uint32_t RTSR; /*!< EXTI Rising trigger selection register, Address offset: 0x08 */
__IO uint32_t FTSR; /*!< EXTI Falling trigger selection register, Address offset: 0x0C */
__IO uint32_t SWIER; /*!< EXTI Software interrupt event register, Address offset: 0x10 */
__IO uint32_t PR; /*!< EXTI Pending register, Address offset: 0x14 */
} EXTI_TypeDef;
2.1.2 > 框图描述
可以看出PA0,PB0… PI0,是共用一个中断口,硬件设计就要注意。
2.2> NVIC
嵌套向量中断控制器,NVIC : Nested Vecrored Interrupt Controller;
2.2.1 > 结构体描述
typedef struct
{
uint32_t ISER[8]; /*(R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[24];
uint32_t ICER[8]; /*(R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[24];
uint32_t ISPR[8]; /*(R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[24];
uint32_t ICPR[8]; /*(R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[24];
uint32_t IABR[8]; /*(R/W) Interrupt Active bit Register */
uint32_t RESERVED4[56];
uint8_t IP[240]; /*(R/W) Interrupt Priority Register */
uint32_t RESERVED5[644];
uint32_t STIR; /* ( /W) Software Trigger Interrupt Register */
} NVIC_Type;
2.2.2 > 框图描述
2.2.3 > 操作函数
2.3> SCB
系统控制块,SCB:System Control Block;
2.3.1 > 结构体描述
typedef struct
{
uint32_t CPUID; /*(R/ ) CPUID Base Register */
uint32_t ICSR; "(R/W) Interrupt Control and State Register"
uint32_t VTOR; /*(R/W) Vector Table Offset Register */
uint32_t AIRCR; "(R/W) Application Interrupt and Reset Control Register"
uint32_t SCR; /*(R/W) System Control Register */
"..."
"..."
"..."
} SCB_Type;
2.3.2 > 操作函数(core_cm4.h)
void NVIC_SetPriorityGrouping(uint32_t PriorityGroup);
uint32_t NVIC_GetPriorityGrouping(void);
总结:
STM32F407ZGT6的中断相关硬件,有SYSCFG,EXTI, NVIC,SCB,外设中的寄存器;
大概看到,中断使能,中断挂起,中断优先级…一些相关的操作;
Coretex-M4支持8位, STM32F407只用了高8位:
3> 外部中断实验
step1> CubeMx生成初始化代码,copy到工程;
…
step2> 实现中断服务函数
HAL库干的活:
// stm32f4xx_it.c
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
/*************************************************/
// stm32f4xx_hal_gpio.c
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
有道翻译这句话;
*/
}
/*************************************************/
咱要干的活:只需要实现回调函数:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* KEY1_PIN */
if (GPIO_Pin == KEY1_PIN) {
led_on();
}
/* KEY2_PIN */
if (GPIO_Pin == KEY2_PIN) {
led_off();
}
/* KEY3_PIN */
if (GPIO_Pin == KEY3_PIN) {
led_off();
}
/* KEY4_PIN */
if (GPIO_Pin == KEY4_PIN) {
beep_on();
}
/* KEY5_PIN */
if (GPIO_Pin == KEY5_PIN) {
beep_off();
}
}
step3> main.c
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
led_init();
beep_init();
key_init_it();
while (1) {
/* nothing */
}
}