单片机外部中断实验

单片机:STM32F407

开发板:DMF407电机开发板

平台:keil V5.31

HSE 为8MHZ

HSI为16MHZ

利用按键,按下按键触发下降沿的外部中断,松开按键触发上升沿的外部中断,计算按键按下时长,不同的时长,显示不同的LED。

主函数:

复制代码
uint32_t g_ntime=0;
int main(void)
{
    HAL_Init();                             /* 初始化HAL库 */
    sys_stm32_clock_init(336, 8, 2, 7);     /* 设置时钟,168Mhz */
    delay_init(168);                        /* 延时初始化 */
    led_init();                             /* 初始化LED */
    extix_init();                           /* 初始化外部中断输入 */
    LED0(0);                                /* 点亮LED0 */
    while(1)
    {
        delay_ms(1);
			g_ntime++;
    }
}

按键配置:

复制代码
void key_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;                          /* GPIO配置参数存储变量 */
    KEY0_GPIO_CLK_ENABLE();                                     /* KEY0时钟使能 */
    KEY1_GPIO_CLK_ENABLE();                                     /* KEY1时钟使能 */
    KEY2_GPIO_CLK_ENABLE();                                     /* KEY2时钟使能 */

    gpio_init_struct.Pin = KEY0_GPIO_PIN;                       /* KEY0引脚 */
    gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */
    gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
    HAL_GPIO_Init(KEY0_GPIO_PORT, &gpio_init_struct);           /* KEY0引脚模式设置,上拉输入 */

    gpio_init_struct.Pin = KEY1_GPIO_PIN;                       /* KEY1引脚 */
    gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */
    gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
    HAL_GPIO_Init(KEY1_GPIO_PORT, &gpio_init_struct);           /* KEY1引脚模式设置,上拉输入 */

    gpio_init_struct.Pin = KEY2_GPIO_PIN;                       /* KEY2引脚 */
    gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */
    gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
    HAL_GPIO_Init(KEY2_GPIO_PORT, &gpio_init_struct);           /* KEY2引脚模式设置,上拉输入 */
}

外部中断配置

复制代码
void extix_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    
    key_init();
    gpio_init_struct.Pin = KEY0_INT_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_IT_RISING_FALLING;//GPIO_MODE_IT_FALLING;            /* 下降沿触发 */
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY0_INT_GPIO_PORT, &gpio_init_struct);    /* KEY0配置为下降沿触发中断 */

    gpio_init_struct.Pin = KEY1_INT_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下降沿触发 */
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY1_INT_GPIO_PORT, &gpio_init_struct);    /* KEY1配置为下降沿触发中断 */
    
    gpio_init_struct.Pin = KEY2_INT_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下降沿触发 */
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY2_INT_GPIO_PORT, &gpio_init_struct);    /* KEY2配置为下降沿触发中断 */
    

    HAL_NVIC_SetPriority(KEY0_INT_IRQn, 0, 2);               /* 抢占0,子优先级2 */
    HAL_NVIC_EnableIRQ(KEY0_INT_IRQn);                       /* 使能中断线1 */

    HAL_NVIC_SetPriority(KEY1_INT_IRQn, 1, 2);               /* 抢占1,子优先级2 */
    HAL_NVIC_EnableIRQ(KEY1_INT_IRQn);                       /* 使能中断线15 */
    
    HAL_NVIC_SetPriority(KEY2_INT_IRQn, 2, 2);               /* 抢占2,子优先级2 */
    HAL_NVIC_EnableIRQ(KEY2_INT_IRQn);                       /* 使能中断线15 */

}

外部中断处理:

复制代码
void KEY0_INT_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(KEY0_INT_GPIO_PIN);         /* 调用中断处理公用函数 清除KEY0所在中断线 的中断标志位 */
    __HAL_GPIO_EXTI_CLEAR_IT(KEY0_INT_GPIO_PIN);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}

void KEY1_INT_IRQHandler(void)
{ 
    HAL_GPIO_EXTI_IRQHandler(KEY1_INT_GPIO_PIN);         /* 调用中断处理公用函数 清除KEY1所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
    __HAL_GPIO_EXTI_CLEAR_IT(KEY1_INT_GPIO_PIN);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}

void KEY2_INT_IRQHandler(void)
{ 
    HAL_GPIO_EXTI_IRQHandler(KEY2_INT_GPIO_PIN);        /* 调用中断处理公用函数 清除KEY2所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
    __HAL_GPIO_EXTI_CLEAR_IT(KEY2_INT_GPIO_PIN);        /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}

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);
  }
}

extern uint32_t g_ntime;
uint32_t g_npresstime=0;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    delay_ms(10);      /* 消抖 */
    switch(GPIO_Pin)
    {
        case KEY0_INT_GPIO_PIN:
            if (KEY0 == 0)
            {
//                LED0_TOGGLE();  /* LED0 状态取反 */ 
							g_ntime=0;
            }
						else
						{
							g_npresstime=g_ntime;
							if(g_npresstime<500)
								LED0_TOGGLE();
							else if(g_npresstime<1000)
								LED1_TOGGLE();
							else
							{
								LED0_TOGGLE();
								LED1_TOGGLE();
							}
						}
            break;

        case KEY1_INT_GPIO_PIN:
//            if (KEY1 == 0)
            {
                LED1_TOGGLE();  /* LED1 状态取反 */ 
            }
            break;

        case KEY2_INT_GPIO_PIN:
            if (KEY2 == 0)
            {
                LED0_TOGGLE();  /* LED0 状态取反 */ 
                LED1_TOGGLE();  /* LED1 状态取反 */
            }
            break;

        default : break;
    }
}
相关推荐
硅基手札6 小时前
【Linux 内核专栏 19】20 · 嵌入式子系统 — GPIO·pinctrl·clock·regulator
linux·运维·单片机·linux内核·嵌入式开发·调试定位
何粥学8 小时前
Vivado 2024.2 开发记录(AC820 Zynq-7020)——软件使用,点亮led灯
单片机·嵌入式硬件·zynq
Sakura_j_h_9 小时前
51 单片机驱动四位数码管:动态扫描、限流电阻与消影的取舍
单片机·嵌入式硬件·51单片机·嵌入式·数码管·动态扫描·限流电阻
HANDY0920010 小时前
从“不照人”到“剂量达标”:扇叶遮挡式UV-C空气消毒的工程边界与可验证评估框架
开发语言·人工智能·嵌入式硬件·智能家居
飞凌嵌入式13 小时前
千次静电放电试炼,守住飞凌嵌入式硬件可靠底线
嵌入式硬件
蹊黎21 小时前
Linux 下用 C 语言实现进度条
linux·c语言·单片机
无敌贵点大王1 天前
从寄存器层面重学STM32(6)——串口USART实战部分
stm32·单片机·嵌入式硬件
庙堂龙吟奈我何1 天前
二进制和十六进制
stm32·单片机
国科安芯1 天前
长期在轨的计算底座:商业空间站与在轨服务飞行器健康管理中的抗辐射MCU—— 面向可维护空间平台的分层容错与安全通信综述
人工智能·单片机·嵌入式硬件·安全·低轨卫星·抗辐射
不昀1 天前
RMII切到10Mbps,50MHz参考时钟也要降到5MHz吗?
单片机·嵌入式硬件·硬件设计·以太网接口