• 10.12按键中断


    设置按键中断,按键1按下,LED亮,再按一次,灭
    按键2按下,蜂鸣器响。再按一次,不响
    按键3按下,风扇转,再按一次,风扇停
    keyit.h:
    1. #ifndef __KEYIT_H__
    2. #define __KEYIT_H__
    3. #include "stm32mp1xx_rcc.h"
    4. #include "stm32mp1xx_gpio.h"
    5. #include "stm32mp1xx_exti.h"
    6. #include "stm32mp1xx_gic.h"
    7. void key_it_init();
    8. void led_init();
    9. void beep_init();
    10. void fan_init();
    11. #endif
    keyit.c:
    1. #include"keyit.h"
    2. void key_it_init(){
    3. //RCC是能GPIOF时钟
    4. RCC->MP_AHB4ENSETR |= (0x1<<5);
    5. //设置PF9 PF7 PF8的GPIO输入模式
    6. GPIOF->MODER &= (~(0x3f<<14));
    7. //设置PF9 PF7 PF8产生EXTI事件
    8. //设置PF7
    9. EXTI->EXTICR2 &= (~(0xff<<24));
    10. EXTI->EXTICR2 |= (0x05<<24);
    11. //设置PF8,PF9
    12. EXTI->EXTICR3 &= (~(0xff));
    13. EXTI->EXTICR3 |= (0x05);
    14. EXTI->EXTICR3 &= (~(0xff<<8));
    15. EXTI->EXTICR3 |= (0x05<<8);
    16. //设置事件触发方式为下降沿触发
    17. EXTI->FTSR1 |= (0x7<<7);
    18. //设置EXTI事件触发不屏蔽
    19. EXTI->C1IMR1 |= (0x7<<7);
    20. //使能中断能转发到待定的CPU接口层
    21. GICD->ISENABLER[3] |= (0x7<<1);
    22. //设置中断优先级
    23. //设置按键1,PF9的优先级
    24. GICD->IPRIORITYR[24] &= (~(0x1f<<27));
    25. //设置按键2,PF7的优先级
    26. GICD->IPRIORITYR[24] &= (~(0x1f<<11));
    27. //设置按键3,PF8的优先级
    28. GICD->IPRIORITYR[24] &= (~(0x1f<<19));
    29. //设置当前中断被转发到哪一个CPU处理
    30. //设置按键1对应中断处理程序由CPU0处理
    31. GICD->ITARGETSR[24] &= (~(0x3<<24));
    32. GICD->ITARGETSR[24] |= (0x1<<24);
    33. //设置按键2对应中断处理程序由CPU0处理
    34. GICD->ITARGETSR[24] &= (~(0x3<<8));
    35. GICD->ITARGETSR[24] |= (0x1<<8);
    36. //设置按键3对应中断处理程序由CPU0处理
    37. GICD->ITARGETSR[24] &= (~(0x3<<16));
    38. GICD->ITARGETSR[24] |= (0x1<<16);
    39. //使能组0转发中断
    40. GICD->CTRL |= 0x1;
    41. //设置中断优先级掩码
    42. GICC->PMR |= (0xf<<3);
    43. //使能CPU可以处理组0转发的中断
    44. GICC->CTRL |= (0x1);
    45. }
    46. void led_init(){
    47. //将gpioe和GPIOF的时钟使能
    48. RCC->MP_AHB4ENSETR |= (0x3<<4);
    49. //将三盏灯对应的gpio口的模式设置为输出
    50. GPIOE->MODER &= (~(0x3<<20));
    51. GPIOE->MODER |= (0x1<<20);
    52. GPIOF->MODER &= (~(0x3<<20));
    53. GPIOF->MODER |= (0x1<<20);
    54. GPIOE->MODER &= (~(0x3<<16));
    55. GPIOE->MODER |= (0x1<<16);
    56. //将输出模式设置为推挽输出
    57. GPIOE->MODER |= (0x1<<10);
    58. GPIOF->MODER |= (0x1<<10);
    59. GPIOE->MODER |= (0x1<<8);
    60. //将输出设置为低速
    61. GPIOE->OSPEEDR &= (~(0x3<<20));
    62. GPIOF->OSPEEDR &= (~(0x3<<20));
    63. GPIOE->OSPEEDR &= (~(0x3<<16));
    64. //设置无上拉下拉电阻
    65. GPIOE->PUPDR &= (~(0x3<<20));
    66. GPIOF->PUPDR &= (~(0x3<<20));
    67. GPIOE->PUPDR &= (~(0x3<<16));
    68. }
    69. void beep_init(){
    70. //将gpiob的时钟使能
    71. RCC->MP_AHB4ENSETR |= (0x1<<1);
    72. //讲蜂鸣器对应的PB6口的模式设置为输出模式
    73. GPIOB->MODER &= (~(0x3<<12));
    74. GPIOB->MODER |= (0x1<<12);
    75. //将输出模式设置为推挽输出
    76. GPIOB->MODER |= (0x1<<6);
    77. //讲输出设置为低速
    78. GPIOB->OSPEEDR &= (~(0x3<<12));
    79. //设置无上拉下拉电阻
    80. GPIOB->PUPDR &= (~(0x3<<12));
    81. }
    82. void fan_init(){
    83. //将gpiob的时钟使能
    84. RCC->MP_AHB4ENSETR |= (0x1<<4);
    85. //讲风扇对应的PE9口的模式设置为输出模式
    86. GPIOE->MODER &= (~(0x3<<18));
    87. GPIOE->MODER |= (0x1<<18);
    88. //将输出模式设置为推挽输出
    89. GPIOE->MODER |= (0x1<<9);
    90. //讲输出设置为低速
    91. GPIOE->OSPEEDR &= (~(0x3<<18));
    92. //设置无上拉下拉电阻
    93. GPIOE->PUPDR &= (~(0x3<<18));
    94. }
    do_irq.c:
    1. //extern void printf(const char *fmt, ...);
    2. #include "keyit.h"
    3. void delay(int ms){
    4. for(int i=0; i
    5. for(int j=0; j<2000; j++){}
    6. }
    7. }
    8. unsigned int flag_led = 0;
    9. unsigned int flag_beep = 0;
    10. unsigned int flag_fan = 0;
    11. void do_irq(void)
    12. {
    13. int irqno;//保存中断号
    14. irqno = GICC->IAR&0x3FF;
    15. switch(irqno){
    16. case 99://key1
    17. //按键1中断处理
    18. if(flag_led==0){
    19. GPIOE->ODR |= (0x1<<10);
    20. GPIOF->ODR |= (0x1<<10);
    21. GPIOE->ODR |= (0x1<<8);
    22. flag_led = 1;
    23. }else{
    24. GPIOE->ODR &= (~(0x1<<10));
    25. GPIOF->ODR &= (~(0x1<<10));
    26. GPIOE->ODR &= (~(0x1<<8));
    27. flag_led = 0;
    28. }
    29. //清除挂起中断标志位
    30. GICD->ICPENDR[3] |= (0x1<<3);
    31. //清除中断触发标志位
    32. EXTI->FPR1 |= (0x1<<9);
    33. //清除处理完的中断号
    34. GICC->EOIR |= irqno;
    35. break;
    36. case 97://key2
    37. //按键2中断处理
    38. if(flag_beep==0){
    39. GPIOB->ODR |= (0x1<<6);
    40. flag_beep = 1;
    41. }else{
    42. GPIOB->ODR &= (~(0x1<<6));
    43. flag_beep = 0;
    44. }
    45. //清除挂起中断标志位
    46. GICD->ICPENDR[3] |= (0x1<<1);
    47. //清除中断触发标志位
    48. EXTI->FPR1 |= (0x1<<7);
    49. //清除处理完的中断号
    50. GICC->EOIR |= irqno;
    51. break;
    52. case 98://key3
    53. //按键3中断处理
    54. if(flag_fan==0){
    55. GPIOE->ODR |= (0x1<<9);
    56. flag_fan = 1;
    57. }else{
    58. GPIOE->ODR &= (~(0x1<<9));
    59. flag_fan = 0;
    60. }
    61. //清除挂起中断标志位
    62. GICD->ICPENDR[3] |= (0x1<<2);
    63. //清除中断触发标志位
    64. EXTI->FPR1 |= (0x1<<8);
    65. //清除处理完的中断号
    66. GICC->EOIR |= irqno;
    67. break;
    68. }
    69. }
    main.c:
    1. #include"keyit.h"
    2. int main()
    3. {
    4. led_init();
    5. key_it_init();
    6. beep_init();
    7. fan_init();
    8. while(1){
    9. }
    10. return 0;
    11. }
    效果图:

    LED:

    风扇:

    蜂鸣器无可见现象

    按键中断控制led,蜂鸣器和风扇

  • 相关阅读:
    唯众中职人工智能专业解决方案
    使用uniapp写小程序,真机调试的时候不显示log
    Flink学习9:配置idea开发flink-Scala程序环境
    目标检测YOLO实战应用案例100讲-基于改进YOLO的车位导引(续)
    详解设计模式:桥接模式
    AI伦理:科技发展中的人性之声
    Linux下找出吃内存的方法
    UWB芯片与模块市场的崛起与趋势
    【MySQL】DDL因Waiting for table metadata lock卡住
    (48)STM32——图片显示实验
  • 原文地址:https://blog.csdn.net/sy311SB/article/details/133797063