打印
[其他]

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

[复制链接]
765|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
之前的帖子使用例程完成了简单的点灯测试,这次自己新建个工程来进行测试,完成基础题目中的这两个

先新建个文件夹,把固件包里的Device文件夹复制过去,另外再新建2个文件夹用来存放keil工程文件和代码文件

打开keil,选择新建工程,保存目录选择刚才新建的文件夹(MDK),芯片选择MM32F5333D7PV

接下来的页面直接点OK就行,按照自己的习惯添加好分组

将Device中的库文件添加进来

添加头文件路径

参考例程添加宏定义

修改linker

添加main.c

先简单写个流水灯测试一下,查看原理图确定LED使用的引脚

编写代码,LED是低电平点亮,初始化后输出高电平使LED初始状态为熄灭
#include "hal_conf.h"

enum
{
    LED_NO_1 = 0,
    LED_NO_2,
    LED_NO_3,
    LED_NO_4,
    LED_NUM,
};

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

void led_init(void)
{
    uint8_t i = 0;
    GPIO_InitTypeDef cfg;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
    GPIO_StructInit(&cfg);
    cfg.GPIO_Mode = GPIO_Mode_Out_PP;
    cfg.GPIO_Speed = GPIO_Speed_High;
    while(i < LED_NUM)
    {
        cfg.GPIO_Pin = led_pins[i];
        GPIO_Init(led_ports[i],&cfg);
        GPIO_SetBits(led_ports[i],led_pins[i]);
        i += 1;
    }
}

void led_toggle(uint8_t led)
{
    if(led < LED_NUM)
        GPIO_WriteBit(led_ports[led], led_pins[led], !GPIO_ReadOutputDataBit(led_ports[led], led_pins[led]));
}

void test_delay(void)
{
    uint32_t delay = 0x100000;
    while(delay--);
}

int main(void)
{
    led_init();

    while (1)
    {
        test_delay();
        led_toggle(LED_NO_1);
        test_delay();
        led_toggle(LED_NO_2);
        test_delay();
        led_toggle(LED_NO_3);
        test_delay();
        led_toggle(LED_NO_4);
    }
}

编译并烧录,运行效果

接下来实现按键检测,通过点击按键切换LED状态,先来看原理图

按键1是高电平触发,剩下三个都是低电平触发,并且按键2、3、4没有上拉电阻,在配置时需要开启内部上拉,机械按键按下时会产生抖动,这里对按下状态进行计时,按下状态持续20ms视为触发点击操作,然后切换对应LED的状态,代码如下
GPIO_TypeDef *key_ports[] = {GPIOC,GPIOC,GPIOB,GPIOB};
uint16_t key_pins[] = {GPIO_Pin_4,GPIO_Pin_5,GPIO_Pin_1,GPIO_Pin_2};
const uint8_t key_press_states[] = {Bit_SET,Bit_RESET,Bit_RESET,Bit_RESET};
uint8_t key_press_counts[KEY_NUM];
void keys_init(void)
{
    GPIO_InitTypeDef cfg;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
    GPIO_StructInit(&cfg);
    cfg.GPIO_Mode = GPIO_Mode_IPU;
    cfg.GPIO_Pin = GPIO_Pin_5;
    GPIO_Init(GPIOC,&cfg);
    cfg.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
    GPIO_Init(GPIOB,&cfg);
   
    cfg.GPIO_Mode = GPIO_Mode_FLOATING;
    cfg.GPIO_Pin = GPIO_Pin_4;
    GPIO_Init(GPIOC,&cfg);
    memset(key_press_counts,0,KEY_NUM);
}

void key_state_check(void)
{
    uint8_t i = 0;
    while(i < KEY_NUM)
    {
        if(GPIO_ReadInputDataBit(key_ports[i], key_pins[i]) == key_press_states[i])
        {
            if(key_press_counts[i] < 0xFF)
                key_press_counts[i] += 1;
        }
        else
            key_press_counts[i] = 0;
        if(key_press_counts[i] == 20)
            led_toggle(i);
        i += 1;
    }
}

int main(void)
{
    led_init();
    keys_init();
    while (1)
    {
        YUYY_DelayMs(1);
        key_state_check();
    }
}

运行效果

上面是通过不断查询io电平来实现的按键检测,接下来通过中断来进行按键检测,所有 IO 引脚可以连接到 16 个外部中断线,对应关系如下图


配置按键1为上升沿触发,其他3个为下降沿触发,代码如下
void exit_init(void)
{
    EXTI_InitTypeDef exit_cfg;
    NVIC_InitTypeDef nvic_cfg;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource4);
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource5);
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource1);
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource2);
    EXTI_StructInit(&exit_cfg);
   
    exit_cfg.EXTI_Line    = EXTI_Line4;
    exit_cfg.EXTI_Mode    = EXTI_Mode_Interrupt;
    exit_cfg.EXTI_Trigger = EXTI_Trigger_Rising;
    exit_cfg.EXTI_LineCmd = ENABLE;
    EXTI_Init(&exit_cfg);
    nvic_cfg.NVIC_IRQChannel = EXTI4_IRQn;
    nvic_cfg.NVIC_IRQChannelPreemptionPriority = 0;
    nvic_cfg.NVIC_IRQChannelSubPriority = 1;
    nvic_cfg.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&nvic_cfg);
   
    exit_cfg.EXTI_Line    = EXTI_Line5;
    exit_cfg.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_Init(&exit_cfg);
    nvic_cfg.NVIC_IRQChannel = EXTI9_5_IRQn;
    NVIC_Init(&nvic_cfg);
   
    exit_cfg.EXTI_Line    = EXTI_Line1;
    exit_cfg.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_Init(&exit_cfg);
    nvic_cfg.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_Init(&nvic_cfg);
   
    exit_cfg.EXTI_Line    = EXTI_Line2;
    exit_cfg.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_Init(&exit_cfg);
    nvic_cfg.NVIC_IRQChannel = EXTI2_IRQn;
    NVIC_Init(&nvic_cfg);
}

void EXTI4_IRQHandler(void)
{
    if (SET == EXTI_GetITStatus(EXTI_Line4) && GPIO_ReadInputDataBit(key_ports[KEY_NO_1], key_pins[KEY_NO_1]) == key_press_states[KEY_NO_1])
    {
        led_toggle(LED_NO_1);
        EXTI_ClearITPendingBit(EXTI_Line4);
    }
}
void EXTI9_5_IRQHandler(void)
{
    if (SET == EXTI_GetITStatus(EXTI_Line5) && GPIO_ReadInputDataBit(key_ports[KEY_NO_2], key_pins[KEY_NO_2]) == key_press_states[KEY_NO_2])
    {
        led_toggle(LED_NO_2);
        EXTI_ClearITPendingBit(EXTI_Line5);
    }
}
void EXTI1_IRQHandler(void)
{
    if (SET == EXTI_GetITStatus(EXTI_Line1) && GPIO_ReadInputDataBit(key_ports[KEY_NO_3], key_pins[KEY_NO_3]) == key_press_states[KEY_NO_3])
    {
        led_toggle(LED_NO_3);
        EXTI_ClearITPendingBit(EXTI_Line1);
    }
}
void EXTI2_IRQHandler(void)
{
    if (SET == EXTI_GetITStatus(EXTI_Line2) && GPIO_ReadInputDataBit(key_ports[KEY_NO_4], key_pins[KEY_NO_4]) == key_press_states[KEY_NO_4])
    {
        led_toggle(LED_NO_4);
        EXTI_ClearITPendingBit(EXTI_Line2);
    }
}

int main(void)
{
    led_init();
    keys_init();
    exit_init();
    while (1)
    {
    }
}

运行效果和轮询的类似,这里就不再重复上图了

使用特权

评论回复
沙发
地瓜patch| | 2024-6-28 15:01 | 只看该作者
搞个呼吸灯

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

146

主题

698

帖子

6

粉丝