[AT32M412] 【AT-START-M412测评】+ 按钮学习,多路IO中断

[复制链接]
 楼主| 发表于 2025-6-14 22:48 | 显示全部楼层 |阅读模式
IO的单路学习分享参考下面的帖子
https://bbs.21ic.com/icview-3461522-1-1.html
本贴在此基础上进行拓展,实现4个IO的中断操作

IO的初始化配置如下
  1. void at32_button_init(void)
  2. {
  3.   gpio_init_type gpio_init_struct;

  4.   /* enable the button clock */
  5.   crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

  6.   /* set default parameter */
  7.   gpio_default_para_init(&gpio_init_struct);

  8.   /* configure button pin as input with pull-up/pull-down */
  9.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  10.   gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_OPEN_DRAIN;
  11.   gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
  12.   gpio_init_struct.gpio_pins = GPIO_PINS_4 | GPIO_PINS_5 | GPIO_PINS_7 | GPIO_PINS_10;
  13.   gpio_init_struct.gpio_pull = GPIO_PULL_UP;
  14.   gpio_init(GPIOB, &gpio_init_struct);
  15. }
我使用了四个IO,GPIOB上的4/5/7/10
设置为输入模式,内部上拉电阻
20625684d8a4e7c620.png
这样按下的时候就是下降沿,松开时候就是上升沿。
接下来配置IO中断的初始化配置
  1. void button_exint_init(void)
  2. {
  3.   exint_init_type exint_init_struct;

  4.   crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);
  5.   scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOB, SCFG_PINS_SOURCE4);
  6.   scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOB, SCFG_PINS_SOURCE5);  
  7.   scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOB, SCFG_PINS_SOURCE7);
  8.   scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOB, SCFG_PINS_SOURCE10);
  9.   
  10.   exint_default_para_init(&exint_init_struct);
  11.   exint_init_struct.line_enable = TRUE;
  12.   exint_init_struct.line_mode = EXINT_LINE_INTERRUPT;
  13.   exint_init_struct.line_select = EXINT_LINE_4 | EXINT_LINE_5 | EXINT_LINE_7 | EXINT_LINE_10;
  14.   exint_init_struct.line_polarity = EXINT_TRIGGER_FALLING_EDGE;
  15.   exint_init(&exint_init_struct);
  16.   nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  17.   nvic_irq_enable(EXINT4_IRQn, 0, 0);
  18.   nvic_irq_enable(EXINT9_5_IRQn, 0, 0);
  19.   nvic_irq_enable(EXINT15_10_IRQn, 0, 0);
  20. }
设置为了下降沿中断。
4个IO的中断函数处理
  1. void button_B4_isr(void)
  2. {
  3.   /* delay 5ms */
  4.   delay_ms(5);

  5.   /* clear interrupt pending bit */
  6.   exint_flag_clear(EXINT_LINE_4);

  7.   /* check input pin state */
  8.   if(RESET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_4))
  9.   {
  10.     if(g_speed == SLOW)
  11.       g_speed = FAST;
  12.     else
  13.       g_speed = SLOW;
  14.   }
  15. }

  16. void button_B5_isr(void)
  17. {
  18.   /* delay 5ms */
  19.   delay_ms(5);

  20.   /* clear interrupt pending bit */
  21.   exint_flag_clear(EXINT_LINE_5);

  22.   /* check input pin state */
  23.   if(RESET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_5))
  24.   {
  25.     if(g_speed == SLOW)
  26.       g_speed = FAST;
  27.     else
  28.       g_speed = SLOW;
  29.   }
  30. }

  31. void button_B7_isr(void)
  32. {
  33.   /* delay 5ms */
  34.   delay_ms(5);

  35.   /* clear interrupt pending bit */
  36.   exint_flag_clear(EXINT_LINE_7);

  37.   /* check input pin state */
  38.   if(RESET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_7))
  39.   {
  40.     if(g_speed == SLOW)
  41.       g_speed = FAST;
  42.     else
  43.       g_speed = SLOW;
  44.   }
  45. }

  46. void button_B10_isr(void)
  47. {
  48.   /* delay 5ms */
  49.   delay_ms(5);

  50.   /* clear interrupt pending bit */
  51.   exint_flag_clear(EXINT_LINE_10);

  52.   /* check input pin state */
  53.   if(RESET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_10))
  54.   {
  55.     if(g_speed == SLOW)
  56.       g_speed = FAST;
  57.     else
  58.       g_speed = SLOW;
  59.   }
  60. }
将中断处理函数加入到启动文件里的中断向量函数里
  1. void EXINT4_IRQHandler(void)
  2. {
  3.   button_B4_isr();
  4. }
  5. void EXINT9_5_IRQHandler(void)
  6. {
  7.   button_B5_isr();
  8.   button_B7_isr();
  9. }
  10. void EXINT15_10_IRQHandler(void)
  11. {
  12.   button_B10_isr();
  13. }
我们可以看到5到9的IO端口共用一个入口,10到15的共用一个入口。
相关的定义在.s启动文件里startup_at32m412_416.s
36917684d8b616ef82.png
编译下载
可以看到这四个按钮按下都可以切换流水灯的速度了。
说明实现了相关目的。


 楼主| 发表于 2025-6-14 22:49 | 显示全部楼层
该测试可以为后续的总体功能实现提供 4个基于中断的按钮。
 楼主| 发表于 2025-6-14 23:18 | 显示全部楼层
增加按下后打印消息
  1. void button_B4_isr(void)
  2. {
  3.   /* delay 5ms */
  4.   delay_ms(5);

  5.   /* clear interrupt pending bit */
  6.   exint_flag_clear(EXINT_LINE_4);

  7.   /* check input pin state */
  8.   if(RESET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_4))
  9.   {
  10.     if(g_speed == SLOW)
  11.       g_speed = FAST;
  12.     else
  13.       g_speed = SLOW;
  14.   }
  15.   printf("GPIOB_04 is pressed.\r\n");
  16. }

  17. void button_B5_isr(void)
  18. {
  19.   /* delay 5ms */
  20.   delay_ms(5);

  21.   /* clear interrupt pending bit */
  22.   exint_flag_clear(EXINT_LINE_5);

  23.   /* check input pin state */
  24.   if(RESET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_5))
  25.   {
  26.     if(g_speed == SLOW)
  27.       g_speed = FAST;
  28.     else
  29.       g_speed = SLOW;
  30.    
  31.     printf("GPIOB_05 is pressed.\r\n");
  32.   }

  33. }

  34. void button_B7_isr(void)
  35. {
  36.   /* delay 5ms */
  37.   delay_ms(5);

  38.   /* clear interrupt pending bit */
  39.   exint_flag_clear(EXINT_LINE_7);

  40.   /* check input pin state */
  41.   if(RESET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_7))
  42.   {
  43.     if(g_speed == SLOW)
  44.       g_speed = FAST;
  45.     else
  46.       g_speed = SLOW;
  47.    
  48.     printf("GPIOB_07 is pressed.\r\n");
  49.   }
  50.   
  51. }

  52. void button_B10_isr(void)
  53. {
  54.   /* delay 5ms */
  55.   delay_ms(5);

  56.   /* clear interrupt pending bit */
  57.   exint_flag_clear(EXINT_LINE_10);

  58.   /* check input pin state */
  59.   if(RESET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_10))
  60.   {
  61.     if(g_speed == SLOW)
  62.       g_speed = FAST;
  63.     else
  64.       g_speed = SLOW;
  65.    
  66.     printf("GPIOB_10 is pressed.\r\n");
  67.   }

  68. }
6891684d92af49a0f.png
发表于 2025-6-18 13:04 | 显示全部楼层
6啊,多路按键中断是在一个中断里面判断按个按键按下吗?
 楼主| 发表于 2025-6-19 16:47 | 显示全部楼层
顶点追寻者 发表于 2025-6-18 13:04
6啊,多路按键中断是在一个中断里面判断按个按键按下吗?

是多个中断入口,这个其中两个共用了一个入口的。四个按钮使用了三个中断入口
发表于 2025-6-29 13:14 | 显示全部楼层
纯库函数编程,听说有图形化工具,怎么不用用。看看好用不
 楼主| 发表于 2025-7-7 09:56 | 显示全部楼层
zhuomuniao110 发表于 2025-6-29 13:14
纯库函数编程,听说有图形化工具,怎么不用用。看看好用不

因为我更 熟悉库函数方式。回头 试试图形化工具。
发表于 2025-7-7 10:50 | 显示全部楼层
非常详细的帖子,通过你的分享,我对AT-START-M412的IO中断操作有了更深的理解。谢谢你的代码示例和解释!
发表于 2025-7-7 17:04 | 显示全部楼层
非常详细的测评和代码分享,学习了!这种多路IO中断的实现对于嵌入式开发来说非常实用。
发表于 2025-7-11 19:35 | 显示全部楼层
gaoyang9992006 发表于 2025-6-19 16:47
是多个中断入口,这个其中两个共用了一个入口的。四个按钮使用了三个中断入口 ...

这个是不是太浪费啊,如果长按怎么算。
 楼主| 发表于 2025-7-12 11:12 | 显示全部楼层
HarmonySage 发表于 2025-7-11 19:35
这个是不是太浪费啊,如果长按怎么算。

这是中断,长按想做作为输入状态的话,可以在中断函数里启用计数器或者计时器,测量按下的时长作为判断依据。
发表于 2025-7-14 13:52 | 显示全部楼层
非常详细的测评,学习了!你的代码和解释都很清晰,对于理解AT-START-M412的IO中断操作非常有帮助。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:如果你觉得我的分享或者答复还可以,请给我点赞,谢谢。

2045

主题

16347

帖子

222

粉丝
快速回复 返回顶部 返回列表