GD32实战3__点亮LED灯

知识点

1. GPIO控制

2. LED灯驱动原理

3. 按键检查原理

硬件部分

GD32实战3__点亮LED灯_第1张图片

如上图,LED灯负极接地,正极通过470欧电阻后,接到了MCU的引脚上。可以看出,当MCU的GPIO口输出

高电平时LED亮,

低电平时LED灭。

GD32实战3__点亮LED灯_第2张图片

如上图,

​ 当按键弹起时,GPIO接在3.3V上,为高电平

​ 当按键按下时,GPIO接到地上,为低电平

GD32实战3__点亮LED灯_第3张图片

注意:

  1. 原理图中的K1,K2,K3分别对应板子上的K2,K3,K4,本文都是按原理图描述
  2. 0.1uF电容作用去抖动

功能设计

​ 设计一个小功能,KEY3按下 4个LED灯亮,弹起时4个LED灭。子功能设计包括,

1. 功能状态设计

GD32实战3__点亮LED灯_第4张图片

​ 如上图,该功能一共要经历上面几个状态,从而也就明白我们需要提供哪些功能函数,细节读下面的代码。

static VOID LED_Init(VOID)
{
    DRV_LED_Init();
    DRV_KEY_Init();
}

static VOID LED_SetLedStatus(IN U8 status)
{
    if (DRV_KEY_DOWN == status)
    {
        DRV_LED_On(DRV_LED1);
        DRV_LED_On(DRV_LED2);
        DRV_LED_On(DRV_LED3);
        DRV_LED_On(DRV_LED4);
    }
    else if (DRV_KEY_UP == status)
    {
        DRV_LED_Off(DRV_LED1);
        DRV_LED_Off(DRV_LED2);
        DRV_LED_Off(DRV_LED3);
        DRV_LED_Off(DRV_LED4);
    }
    else
    {
        ;
    }
}

static VOID LED_CheckKeyStatus(VOID)
{
    U8 keyStatus = 0;
    
    keyStatus = DRV_KEY_GetStatus(DRV_KEY3);
    if (DRV_KEY_DOWN == keyStatus)
    {
        APP_Delay(50); /* 50ms去抖动 */
        keyStatus = DRV_KEY_GetStatus(DRV_KEY3);
        if (DRV_KEY_DOWN == keyStatus)
        {
            LED_SetLedStatus(DRV_KEY_DOWN);
        }
    }
    else
    {
        LED_SetLedStatus(DRV_KEY_UP);
    }
}

VOID APP_LED_Test(VOID)
{
    LED_Init();
    LED_SetLedStatus(DRV_KEY_UP);
    
    while (1)
    {
        LED_CheckKeyStatus();
    }
}

2. 定时器设计

1. 采用systick作为功能定时器,初始配置成1ms一次中断
2. 提供delay延时函数
static U32 gDrvSystickDelayCount = 0;

S32 DRV_SYSTICK_Init(VOID)
{
    /* 1000Hz,1ms中断一次 */
    if (SysTick_Config(SystemCoreClock / 1000))
    {
        return OS_ERROR;
    }
    
    NVIC_SetPriority(SysTick_IRQn, 0x00);

    return OS_OK;
}

/* 1ms中断一次 */
VOID SysTick_Handler(VOID)
{
    if (gDrvSystickDelayCount > 0)
    {
        gDrvSystickDelayCount--;
    }
}

VOID DRV_SYSTICK_Delay(IN U32 ms)
{
    gDrvSystickDelayCount = ms;
    while (1)
    {
        if (gDrvSystickDelayCount <= 0)
        {
            break;
        }
    }

    return;
}

3. LED驱动

  1. 提供初始化函数接口
  2. 提供LED on/off接口
#define DRV_LED1 GPIOC,GPIO_PIN_0
#define DRV_LED2 GPIOC,GPIO_PIN_2
#define DRV_LED3 GPIOE,GPIO_PIN_0
#define DRV_LED4 GPIOE,GPIO_PIN_1
#define DRV_LED_On(led) GPIO_SetBits(led);
#define DRV_LED_Off(led) GPIO_ResetBits(led);

extern void DRV_LED_Init(void);

4. 按键驱动

  1. 提供初始化接口
  2. 提供获取按键状态接口
#define DRV_KEY3 GPIOB, GPIO_PIN_14
#define DRV_KEY_GetStatus(key) GPIO_ReadInputBit(key)
#define DRV_KEY_DOWN 0
#define DRV_KEY_UP 1

extern VOID DRV_KEY_Init(VOID);

总结

IO配置总结(配置时钟(必配)–>选择复用(选配)–>选择模式(必配)–>配置速率(必配)):

  1. 判断是GPIO(通用IO)和AFIO(复用IO),可以从datasheet的PIN definition章节查到,如图GD32实战3__点亮LED灯_第5张图片default是作为普通GPIO口配置,remap(复用)可以作为TM1_BKIN

  2. IO作为普通GPIO口使用,配置流程如下:

    1. 配置GPIO时钟,由下图可以看出,GPIO挂在APB2上,所以,配置代码如下RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_GPIOC |RCC_APB2PERIPH_GPIOE,ENABLE);GD32实战3__点亮LED灯_第6张图片

    2. 配置GPIO方向、模式和速率GD32实战3__点亮LED灯_第7张图片在这里插入图片描述如上图几种方式,配置代码如下,注意,输入时速率硬件已经配置好了,软件不需要配置

      GPIO_InitPara GPIO_InitStructure;
      
      /* 上拉输出,50MHz */
      GPIO_InitStructure.GPIO_Pin = GPIO_PIN_0 | GPIO_PIN_2;
      GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ;
      GPIO_Init(GPIOC,&GPIO_InitStructure);
      
      /* 浮空输入 */
      GPIO_InitStructure.GPIO_Pin = GPIO_PIN_14;
      GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IN_FLOATING;
      GPIO_Init(GPIOB,&GPIO_InitStructure);
      
    3. 配置GPIO口中断,参考中断章节

  3. AFIO remap流程,先使能AF时钟,再调用pinRemap函数重新映射即可

    RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_AF, ENABLE);
    GPIO_PinRemapConfig(GPIO_REMAP_SWJ_DISABLE, ENABLE);
    

参考资料

《GD32F10xCH_V1.1.pdf》

《GD32103C-EVAL-V1.1.pdf》

《GD32F103xxDatasheetRev2.2.pdf》

代码路径

https://github.com/YaFood/GD32F103/tree/master/TestLED

你可能感兴趣的:(ARM)