[其他] 【灵动微电子MM32F5330测评】2.LED控制+按键检测

[复制链接]
 楼主| yuyy1989 发表于 2024-6-22 17:12 | 显示全部楼层 |阅读模式
<
之前的帖子使用例程完成了简单的点灯测试,这次自己新建个工程来进行测试,完成基础题目中的这两个
微信截图_20240622170303.png
先新建个文件夹,把固件包里的Device文件夹复制过去,另外再新建2个文件夹用来存放keil工程文件和代码文件
微信截图_20240621224732.png
打开keil,选择新建工程,保存目录选择刚才新建的文件夹(MDK),芯片选择MM32F5333D7PV
微信截图_20240621224933.png
接下来的页面直接点OK就行,按照自己的习惯添加好分组
微信截图_20240621230409.png
将Device中的库文件添加进来
微信截图_20240621230613.png
添加头文件路径
微信截图_20240621230843.png
参考例程添加宏定义
微信截图_20240621231117.png
修改linker
微信截图_20240621231308.png
添加main.c
微信截图_20240621231431.png
先简单写个流水灯测试一下,查看原理图确定LED使用的引脚
微信截图_20240621231707.png
编写代码,LED是低电平点亮,初始化后输出高电平使LED初始状态为熄灭
  1. #include "hal_conf.h"

  2. enum
  3. {
  4.     LED_NO_1 = 0,
  5.     LED_NO_2,
  6.     LED_NO_3,
  7.     LED_NO_4,
  8.     LED_NUM,
  9. };

  10. GPIO_TypeDef *led_ports[] = {GPIOB,GPIOB,GPIOC,GPIOC};
  11. uint16_t led_pins[] = {GPIO_Pin_11,GPIO_Pin_10,GPIO_Pin_7,GPIO_Pin_6};

  12. void led_init(void)
  13. {
  14.     uint8_t i = 0;
  15.     GPIO_InitTypeDef cfg;
  16.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
  17.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
  18.     GPIO_StructInit(&cfg);
  19.     cfg.GPIO_Mode = GPIO_Mode_Out_PP;
  20.     cfg.GPIO_Speed = GPIO_Speed_High;
  21.     while(i < LED_NUM)
  22.     {
  23.         cfg.GPIO_Pin = led_pins[i];
  24.         GPIO_Init(led_ports[i],&cfg);
  25.         GPIO_SetBits(led_ports[i],led_pins[i]);
  26.         i += 1;
  27.     }
  28. }

  29. void led_toggle(uint8_t led)
  30. {
  31.     if(led < LED_NUM)
  32.         GPIO_WriteBit(led_ports[led], led_pins[led], !GPIO_ReadOutputDataBit(led_ports[led], led_pins[led]));
  33. }

  34. void test_delay(void)
  35. {
  36.     uint32_t delay = 0x100000;
  37.     while(delay--);
  38. }

  39. int main(void)
  40. {
  41.     led_init();

  42.     while (1)
  43.     {
  44.         test_delay();
  45.         led_toggle(LED_NO_1);
  46.         test_delay();
  47.         led_toggle(LED_NO_2);
  48.         test_delay();
  49.         led_toggle(LED_NO_3);
  50.         test_delay();
  51.         led_toggle(LED_NO_4);
  52.     }
  53. }

编译并烧录,运行效果
WeChat_20240622170927 00_00_00-00_00_30.gif
接下来实现按键检测,通过点击按键切换LED状态,先来看原理图
微信截图_20240622110841.png
按键1是高电平触发,剩下三个都是低电平触发,并且按键2、3、4没有上拉电阻,在配置时需要开启内部上拉,机械按键按下时会产生抖动,这里对按下状态进行计时,按下状态持续20ms视为触发点击操作,然后切换对应LED的状态,代码如下
  1. GPIO_TypeDef *key_ports[] = {GPIOC,GPIOC,GPIOB,GPIOB};
  2. uint16_t key_pins[] = {GPIO_Pin_4,GPIO_Pin_5,GPIO_Pin_1,GPIO_Pin_2};
  3. const uint8_t key_press_states[] = {Bit_SET,Bit_RESET,Bit_RESET,Bit_RESET};
  4. uint8_t key_press_counts[KEY_NUM];
  5. void keys_init(void)
  6. {
  7.     GPIO_InitTypeDef cfg;
  8.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
  9.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
  10.     GPIO_StructInit(&cfg);
  11.     cfg.GPIO_Mode = GPIO_Mode_IPU;
  12.     cfg.GPIO_Pin = GPIO_Pin_5;
  13.     GPIO_Init(GPIOC,&cfg);
  14.     cfg.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
  15.     GPIO_Init(GPIOB,&cfg);
  16.    
  17.     cfg.GPIO_Mode = GPIO_Mode_FLOATING;
  18.     cfg.GPIO_Pin = GPIO_Pin_4;
  19.     GPIO_Init(GPIOC,&cfg);
  20.     memset(key_press_counts,0,KEY_NUM);
  21. }

  22. void key_state_check(void)
  23. {
  24.     uint8_t i = 0;
  25.     while(i < KEY_NUM)
  26.     {
  27.         if(GPIO_ReadInputDataBit(key_ports[i], key_pins[i]) == key_press_states[i])
  28.         {
  29.             if(key_press_counts[i] < 0xFF)
  30.                 key_press_counts[i] += 1;
  31.         }
  32.         else
  33.             key_press_counts[i] = 0;
  34.         if(key_press_counts[i] == 20)
  35.             led_toggle(i);
  36.         i += 1;
  37.     }
  38. }

  39. int main(void)
  40. {
  41.     led_init();
  42.     keys_init();
  43.     while (1)
  44.     {
  45.         YUYY_DelayMs(1);
  46.         key_state_check();
  47.     }
  48. }

运行效果
WeChat_20240622170933 00_00_00-00_00_30.gif
上面是通过不断查询io电平来实现的按键检测,接下来通过中断来进行按键检测,所有 IO 引脚可以连接到 16 个外部中断线,对应关系如下图
微信截图_20240622165439.png
微信截图_20240622165450.png
配置按键1为上升沿触发,其他3个为下降沿触发,代码如下
  1. void exit_init(void)
  2. {
  3.     EXTI_InitTypeDef exit_cfg;
  4.     NVIC_InitTypeDef nvic_cfg;
  5.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  6.     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource4);
  7.     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource5);
  8.     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource1);
  9.     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource2);
  10.     EXTI_StructInit(&exit_cfg);
  11.    
  12.     exit_cfg.EXTI_Line    = EXTI_Line4;
  13.     exit_cfg.EXTI_Mode    = EXTI_Mode_Interrupt;
  14.     exit_cfg.EXTI_Trigger = EXTI_Trigger_Rising;
  15.     exit_cfg.EXTI_LineCmd = ENABLE;
  16.     EXTI_Init(&exit_cfg);
  17.     nvic_cfg.NVIC_IRQChannel = EXTI4_IRQn;
  18.     nvic_cfg.NVIC_IRQChannelPreemptionPriority = 0;
  19.     nvic_cfg.NVIC_IRQChannelSubPriority = 1;
  20.     nvic_cfg.NVIC_IRQChannelCmd = ENABLE;
  21.     NVIC_Init(&nvic_cfg);
  22.    
  23.     exit_cfg.EXTI_Line    = EXTI_Line5;
  24.     exit_cfg.EXTI_Trigger = EXTI_Trigger_Falling;
  25.     EXTI_Init(&exit_cfg);
  26.     nvic_cfg.NVIC_IRQChannel = EXTI9_5_IRQn;
  27.     NVIC_Init(&nvic_cfg);
  28.    
  29.     exit_cfg.EXTI_Line    = EXTI_Line1;
  30.     exit_cfg.EXTI_Trigger = EXTI_Trigger_Falling;
  31.     EXTI_Init(&exit_cfg);
  32.     nvic_cfg.NVIC_IRQChannel = EXTI1_IRQn;
  33.     NVIC_Init(&nvic_cfg);
  34.    
  35.     exit_cfg.EXTI_Line    = EXTI_Line2;
  36.     exit_cfg.EXTI_Trigger = EXTI_Trigger_Falling;
  37.     EXTI_Init(&exit_cfg);
  38.     nvic_cfg.NVIC_IRQChannel = EXTI2_IRQn;
  39.     NVIC_Init(&nvic_cfg);
  40. }

  41. void EXTI4_IRQHandler(void)
  42. {
  43.     if (SET == EXTI_GetITStatus(EXTI_Line4) && GPIO_ReadInputDataBit(key_ports[KEY_NO_1], key_pins[KEY_NO_1]) == key_press_states[KEY_NO_1])
  44.     {
  45.         led_toggle(LED_NO_1);
  46.         EXTI_ClearITPendingBit(EXTI_Line4);
  47.     }
  48. }
  49. void EXTI9_5_IRQHandler(void)
  50. {
  51.     if (SET == EXTI_GetITStatus(EXTI_Line5) && GPIO_ReadInputDataBit(key_ports[KEY_NO_2], key_pins[KEY_NO_2]) == key_press_states[KEY_NO_2])
  52.     {
  53.         led_toggle(LED_NO_2);
  54.         EXTI_ClearITPendingBit(EXTI_Line5);
  55.     }
  56. }
  57. void EXTI1_IRQHandler(void)
  58. {
  59.     if (SET == EXTI_GetITStatus(EXTI_Line1) && GPIO_ReadInputDataBit(key_ports[KEY_NO_3], key_pins[KEY_NO_3]) == key_press_states[KEY_NO_3])
  60.     {
  61.         led_toggle(LED_NO_3);
  62.         EXTI_ClearITPendingBit(EXTI_Line1);
  63.     }
  64. }
  65. void EXTI2_IRQHandler(void)
  66. {
  67.     if (SET == EXTI_GetITStatus(EXTI_Line2) && GPIO_ReadInputDataBit(key_ports[KEY_NO_4], key_pins[KEY_NO_4]) == key_press_states[KEY_NO_4])
  68.     {
  69.         led_toggle(LED_NO_4);
  70.         EXTI_ClearITPendingBit(EXTI_Line2);
  71.     }
  72. }

  73. int main(void)
  74. {
  75.     led_init();
  76.     keys_init();
  77.     exit_init();
  78.     while (1)
  79.     {
  80.     }
  81. }

运行效果和轮询的类似,这里就不再重复上图了
地瓜patch 发表于 2024-6-28 15:01 | 显示全部楼层
搞个呼吸灯
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

161

主题

815

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部