GD32F4xx系列入门实践——01_GPIO_Running_LED

GD32F4xx系列入门——01_GPIO_Running_LED



前言

本文章将给大家解析官方库函数所给的第一章节——点亮LED灯,本质上就是GPIO的控制。


一、什么是GPIO

  • GD32F4xx芯片最多可支持 140 个通用 I/O 引脚(GPIO),分别为 PA0 ~ PA15,PB0 ~ PB15,PC0 ~ PC15,
    PD0 ~ PD15,PE0 ~ PE15,PF0 ~ PF15,PG0 ~ PG15,PH0 ~ PH15 和 PI0 ~ PI11,各片
    上设备用其来实现逻辑输入/输出功能。每个 GPIO 端口有相关的控制和配置寄存器以满足特
    定应用的需求。GPIO 引脚上的外部中断在中断/事件控制器(EXTI)中有相关的控制和配置寄
    存器。
  • GPIO 端口和其他的备用功能(AFs)共用引脚,在特定的封装下获得最大的灵活性。GPIO 引
    脚通过配置相关的寄存器可以用作备用功能引脚,备用功能输入/输出都可以。
    每个 GPIO 引脚可以由软件配置为输出(推挽或开漏)、输入、外设备用功能或者模拟模式。
    每个 GPIO 引脚都可以配置为上拉、下拉或无上拉/下拉。除模拟模式外,所有的 GPIO 引脚都
    具备大电流驱动能力。

二、GPIO模式

  • GPIO 引脚可以配置为输入模式、输出模式和复用模式(AF)。
  • 当 GPIO 引脚配置为输入引脚时:所有的 GPIO 引脚内部都有一个可选择的弱上拉和弱下拉电阻。外部引脚上的数据在每个 AHB 时钟周期时都会装载到数据输入寄存器(GPIOx_ISTAT)。
  • 当 GPIO 引脚配置为输出引脚时:用户可以配置端口的输出速度和选择输出驱动模式:推挽或开漏模式。输出寄存器(GPIOx_OCTL)的值将会从相应 I/O 引脚上输出。
  • 当端口配置为 AFIO(设置 GPIOx_CTL 寄存器中的 CTLy 值为“0b10”)时,该端口用作外设备用功能。通过配置 GPIO 备用功能选择寄存器(GPIOx_AFSELz(z=0,1)),每个端口可以配置 16 个备用功能。端口备用功能分配的详细介绍见芯片数据手册(后续使用时为你们介绍)。

三、此项目环境

  • 软件:keil5;
  • 版本:5.39;
  • 电路板:官方GD32470I_EVAL_Demo_Suites
  • 芯片:GD32F470xx(xx:依据不同的芯片去不同的芯片型号即可,我由于目前没有布置环境,见谅),见下图;
  • 使用的库:官方库(可在官方库下载),你们依据官方库看此文章好哟;
  • 目的:首先点亮一个LED灯,让你们体验一下单片机的魅力。在这里插入图片描述

四、需要了解的库知识点

代码如下(示例):

//以下是需要了解的引脚工作模式
/* output mode definitions */
#define CTL_CLTR(regval)           (BITS(0,1) & ((uint32_t)(regval) << 0))
#define GPIO_MODE_INPUT            CTL_CLTR(0)               /*输入模式*/
#define GPIO_MODE_OUTPUT           CTL_CLTR(1)               /*输出模式*/
#define GPIO_MODE_AF               CTL_CLTR(2)               /*复用模式*/
#define GPIO_MODE_ANALOG           CTL_CLTR(3)               /*模拟模式*/


//以下是引脚状态
/* pull-up/ pull-down definitions */
#define PUD_PUPD(regval)           (BITS(0,1) & ((uint32_t)(regval) << 0))
#define GPIO_PUPD_NONE             PUD_PUPD(0)             /*浮空模式*/
#define GPIO_PUPD_PULLUP           PUD_PUPD(1)             /*上拉模式*/
#define GPIO_PUPD_PULLDOWN         PUD_PUPD(2)             /*下拉模式*/


//引脚输出类型
/* GPIO output type */
#define GPIO_OTYPE_PP              ((uint8_t)(0x00U))        /*推挽模式*/
#define GPIO_OTYPE_OD              ((uint8_t)(0x01U))        /*开漏模式*/


//引脚的驱动能力
/* GPIO output max speed value */
#define GPIO_OSPEED_2MHZ           GPIO_OSPEED_LEVEL0        /*!< output max speed 2MHz */
#define GPIO_OSPEED_25MHZ          GPIO_OSPEED_LEVEL1        /*!< output max speed 25MHz */
#define GPIO_OSPEED_50MHZ          GPIO_OSPEED_LEVEL2        /*!< output max speed 50MHz */
#define GPIO_OSPEED_MAX            GPIO_OSPEED_LEVEL3        /*!< GPIO very high output speed, max speed more than 50MHz */


/*!
    \brief      set GPIO mode
    \param[in]  gpio_periph: GPIO port
                only one parameter can be selected which is shown as below:
      \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
    \param[in]  mode: GPIO pin mode
      \arg        GPIO_MODE_INPUT: input mode
      \arg        GPIO_MODE_OUTPUT: output mode
      \arg        GPIO_MODE_AF: alternate function mode
      \arg        GPIO_MODE_ANALOG: analog mode
    \param[in]  pull_up_down: GPIO pin with pull-up or pull-down resistor
      \arg        GPIO_PUPD_NONE: floating mode, no pull-up and pull-down resistors
      \arg        GPIO_PUPD_PULLUP: with pull-up resistor
      \arg        GPIO_PUPD_PULLDOWN:with pull-down resistor
    \param[in]  pin: GPIO pin
                one or more parameters can be selected which are shown as below:
      \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
    \param[out] none
    \retval     none
*/
void gpio_mode_set(uint32_t gpio_periph, uint32_t mode, uint32_t pull_up_down, uint32_t pin)
{
    uint16_t i;
    uint32_t ctl, pupd;

    ctl = GPIO_CTL(gpio_periph);
    pupd = GPIO_PUD(gpio_periph);

    for(i = 0U; i < 16U; i++) {
        if((1U << i) & pin) {
            /* clear the specified pin mode bits */
            ctl &= ~GPIO_MODE_MASK(i);
            /* set the specified pin mode bits */
            ctl |= GPIO_MODE_SET(i, mode);

            /* clear the specified pin pupd bits */
            pupd &= ~GPIO_PUPD_MASK(i);
            /* set the specified pin pupd bits */
            pupd |= GPIO_PUPD_SET(i, pull_up_down);
        }
    }

    GPIO_CTL(gpio_periph) = ctl;
    GPIO_PUD(gpio_periph) = pupd;
}


/*!
    \brief      set GPIO output type and speed
    \param[in]  gpio_periph: GPIO port
                only one parameter can be selected which is shown as below:
      \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
    \param[in]  otype: GPIO pin output mode
      \arg        GPIO_OTYPE_PP: push pull mode
      \arg        GPIO_OTYPE_OD: open drain mode
    \param[in]  speed: GPIO pin output max speed
      \arg        GPIO_OSPEED_2MHZ: output max speed 2MHz
      \arg        GPIO_OSPEED_25MHZ: output max speed 25MHz
      \arg        GPIO_OSPEED_50MHZ: output max speed 50MHz
      \arg        GPIO_OSPEED_MAX: output max speed more than 50MHz
    \param[in]  pin: GPIO pin
                one or more parameters can be selected which are shown as below:
      \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
    \param[out] none
    \retval     none
*/
void gpio_output_options_set(uint32_t gpio_periph, uint8_t otype, uint32_t speed, uint32_t pin)
{
    uint16_t i;
    uint32_t ospeedr;

    if(GPIO_OTYPE_OD == otype) {
        GPIO_OMODE(gpio_periph) |= (uint32_t)pin;
    } else {
        GPIO_OMODE(gpio_periph) &= (uint32_t)(~pin);
    }

    /* get the specified pin output speed bits value */
    ospeedr = GPIO_OSPD(gpio_periph);

    for(i = 0U; i < 16U; i++) {
        if((1U << i) & pin) {
            /* clear the specified pin output speed bits */
            ospeedr &= ~GPIO_OSPEED_MASK(i);
            /* set the specified pin output speed bits */
            ospeedr |= GPIO_OSPEED_SET(i, speed);
        }
    }
    GPIO_OSPD(gpio_periph) = ospeedr;
}


/*!
    \brief      reset GPIO pin bit
    \param[in]  gpio_periph: GPIO port
                only one parameter can be selected which is shown as below:
      \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
    \param[in]  pin: GPIO pin
                one or more parameters can be selected which are shown as below:
      \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
    \param[out] none
    \retval     none
*/
void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin)
{
    GPIO_BC(gpio_periph) = (uint32_t)pin;
}


/*!
    \brief    set GPIO pin bit
    \param[in]  gpio_periph: GPIO port
                only one parameter can be selected which is shown as below:
      \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
    \param[in]  pin: GPIO pin
                one or more parameters can be selected which are shown as below:
      \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
    \param[out] none
    \retval     none
*/
void gpio_bit_set(uint32_t gpio_periph, uint32_t pin)
{
    GPIO_BOP(gpio_periph) = (uint32_t)pin;
}

五、上正文(main函数)

代码如下(示例):


//一句话概括:使用代码控制GPIO引脚来拉高和拉低电频来实现灯的亮和暗

int main(void)
{
    //首先使能时钟,所用的外设能使用,是依据芯片内部有一个时钟来工作,后续会详解
    systick_config();		

    //使能引脚时钟,你查看的电路图,使用的LED接通到哪一个引脚上,你就使能哪一个时钟,
    //此官方板上有三个LED灯,分别在PE2、PE3和PF10上所以使能这两个引脚时钟即可。
    //只用使能一次即可。
    rcu_periph_clock_enable(RCU_GPIOE);	
    rcu_periph_clock_enable(RCU_GPIOF);		


    //初始化引脚,使用输出模式,初始化时将引脚配置为浮空模式即可,依据引脚输入正确的PIN脚即可
    gpio_mode_set(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_2);
    //设置输出模式为推挽输出,驱动能力就默认即可,这个参数不重要
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
    //将引脚复位(此时LED灯不会亮)
    gpio_bit_reset(GPIOE, GPIO_PIN_2);

    /* enable the LED2 GPIO clock */
    /* configure LED2 GPIO port */
    gpio_mode_set(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_3);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
    /* reset LED2 GPIO pin */
    gpio_bit_reset(GPIOE, GPIO_PIN_3);

    /* enable the LED3 GPIO clock */
    /* configure LED3 GPIO port */
    gpio_mode_set(GPIOF, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_10);
    gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
    /* reset LED3 GPIO pin */
    gpio_bit_reset(GPIOF, GPIO_PIN_10);

    while(1) {
        gpio_bit_set(GPIOF, GPIO_PIN_10);	//上拉PF10引脚电频,LED3会点亮
        gpio_bit_set(GPIOE, GPIO_PIN_2);	//上拉PE2引脚电频,LED1会点亮
        gpio_bit_reset(GPIOF, GPIO_PIN_10);	//下拉PE3引脚点评,LED2会点暗
        delay_1ms(1000);					//延时函数,单位是毫秒,后续会讲解其工作原理,此处参数写1000,就是延时1S

        gpio_bit_set(GPIOE, GPIO_PIN_3);	//上拉PE3引脚电频,LED2会点亮
        gpio_bit_reset(GPIOE, GPIO_PIN_2);	//下拉PE2引脚电频,LED1会点暗
        delay_1ms(1000);

        gpio_bit_set(GPIOF, GPIO_PIN_10);	//上拉PF10引脚电频,LED3会点亮
        gpio_bit_reset(GPIOE, GPIO_PIN_3);	//下拉PE3引脚电频,LED2会点暗
        delay_1ms(1000);
    }
}

六、说点题外话

  • 可以学会了,制作好看的灯带,原理就是我上面写的内容,很简单。
  • 可能会有人会问,外面使用的灯会慢慢的变量和变暗,那就是呼吸灯罢了,其实原理是一样的,只不过使用了更多的外设(TIMER外设),控制了变量和变暗的时间,来迷惑了我们的眼睛。后续我会讲解。
  • 有什么问题可以私信,不玻璃心。

总结

以上就是今天要讲的内容,本文仅仅简单介绍了LED的使用。但是可以控制千变万化的不同颜色和不同数量的灯。

  • 21
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值