【GD32】01-GPIO通用输入输出

GD32

闲话说在前头

这里又开一个系列啦。

原因就是之前买了立创开发板的9.9的GD32E230C8T6的板子,买都买了就跟着立创开发板学习一下(属于是一次性支持了两个国产品牌了,立创和兆易创新)。并且我还买了GD32F407VET6的板子,后续也会使用GD32F407VET6这块板子来做一些别的。

GD32可以说是STM32的国产平替版,听说部分型号可以直接替换掉STM32(我没试过)。

反正以后有啥项目我的首选MCU肯定不会是STM32了(虽然我是用的STM32入门的32位单片机),因为上有更好用ESP32,下有供货稳定(21年的时候STM32断货,STM32F103C8T6的价格曾被炒到六十多一片)的GD32。

刚刚去某宝逛了逛,目前为止(2024.4.23),我在同一家店铺里发现GD32F103C8T6的芯片会比STM32F103C8T6的芯片稍贵三毛钱(不过GD32的主频更高,其他外设和性能什么的没去翻手册对比不太清楚)。并且在某宝上卖STM32开发板的商家明显比GD32开发板的多。现在一个STM32F103C8T6的最小系统板我找到的便宜的可能也就十块钱出头,但是GD32F103C8T6的核心板要二十多块,而且选择还很少。我想这大概是市场上的差异,因为有了需求才会有供给,大家都去买STM32那么STM32自然就能投入更多到研发和生产上,导致了强者愈强的局面。随着国内技术的不断发展和市场的逐步成熟,GD32等国产MCU正在逐渐缩小与国际品牌的差距。

本人怀着强烈的爱国之心,呼吁各位小伙伴支持国产。你不支持,我不支持,那国产品牌哪来的研发资金给咱整什么国货崛起。

总之一句话,支持国产就完事了。

命名规则

GD32和STM32可以说是非常相似的,连命名规则都差不多。

外设资源

上面红框框出来的是GD32E230的外设资源。相比较STM32F103C8T6来说,相对少一些。不过E230在GD32系列芯片里属于入门级,拿来学习是绰绰有余的。

GPIO

接下来我们直接看如何驱动GPIO,点个灯先。

国产的还有一个好处就是手册对中文的支持比较好,省的跑去找翻译了。

可以看得出GD32的固件库功能还是挺多的,比如最后一个翻转GPIO的引脚状态,这个在STM32的固件库里是没有的(HAL库有)。虽然不用人家提供,我们另外也有办法可以实现翻转的操作,但是直接就有的话还是很舒服的。

在STM32中,我们配置GPIO口是需要一个结构体变量的,通过给这个结构体的成员赋值来配置GPIO口。

在GD32中,我们可以看到配置GPIO口是通过两个函数来配置的,分别是设置GPIO模式和GPIO输出模式和速度。

gpio_mode_set

可以选什么参数,在上面的表格写的非常清楚。

这边就简单说一下一些参数的具体含义。

首先是mode,输入输出这个没什么好说的,模拟模式就是我们使用ADC的时候用的。备用功能模式也就是复用引脚,比如我现在要用串口,那么就需要给串口的TX和RX这俩引脚配上这个备用功能模式。

pull_up_down是配置电阻的,和STM32不同的是GD32把这个配置拆开了,STM32中是直接配置为上拉输入,下拉输入等,而在GD32中是配置输入模式,再加上上拉电阻或者是下拉电阻。

gpio_mode_set(GPIOA,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO_PIN_0);

上面示例代码的意思就是我们配置GPIOA的0号引脚为输出模式,没有加电阻。

gpio_output_options_set

配置输出的模式和速率。

一般来说咱就陪推挽输出是够用的,不过具体还得看咱要驱动的模块的手册来判断。

输出速度,如果是通过高低电平来传输数据,那么速度是建议在通信速率的5~10倍的。

gpio_output_options_set(GPIOA,GPIO_OTYPE_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_0);

上面配置了GPIOA的0号引脚为2MHz的推挽输出模式。 

如果是输入模式则不需要使用这个函数。

gpio_bit_write

设置输出电平的函数有很多个,除了这个还有gpio_bit_set gpio_bit_resetgpio_port_write不过我这边就讲gpio_bit_write,因为这个是最常用的,并且剩下三个能实现的功能,用这个函数都可以实现。

参数就是指定端口和引脚,以及高电平(SET)或是低电平(RESET)。

gpio_input_bit_get

gpio_output_bit_get

上面的两个函数都可以读取指定端口和引脚的电平。

跟STM32不一样的是GD32细分了读取电平,分为了读取输出模式下的引脚和读取输入模式下的引脚。

gpio_af_set

设置复用哪一个外设。

这个具体看我们要使用哪一个外设,对照着表格去配置就好了。后续我们会用到。

点亮LED

剩下还有一点就是GD32和STM32一样,默认都是关闭外设时钟的,因此我们还需要打开外设时钟。

rcu_periph_clock_enable  

参照着表格填写我们需要打开的外设时钟即可。 

#include "gd32e23x.h"

void Z_Init_GPIO(void){
    rcu_periph_clock_enable(RCU_GPIOA);
    gpio_mode_set(GPIOA,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO_PIN_0);
    gpio_output_options_set(GPIOA,GPIO_OTYPE_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_0);
}

int main(void){
    Z_Init_GPIO();
    gpio_bit_write(GPIOA,GPIO_PIN_0,0);

    while(1){
        
    }
}

闪烁LED

点亮LED之后我们再让LED闪烁。

我们需要延时函数,这个时候就直接把立创开发板写的拿过来用就好了。

systick.c

 /******************************************************************************
   * 测试硬件:立创开发板·GD32E230C8T6    使用主频72Mhz    晶振8Mhz
   * 版 本 号: V1.0
   * 修改作者: www.lckfb.com
   * 修改日期: 2023年11月02日
   * 功能介绍:      
   *****************************************************************************
   * 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源  
   * 开发板官网:www.lckfb.com   
   * 技术支持常驻论坛,任何技术问题欢迎随时交流学习  
   * 立创论坛:club.szlcsc.com   
   * 其余模块移植手册:【立创·GD32E230C8T6开发板】模块移植手册
   * 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
   * 不靠卖板赚钱,以培养中国工程师为己任
  ******************************************************************************/
/*!
    \file  systick.c
    \brief the systick configuration file
    
    \version 2019-02-19, V1.0.0, firmware for GD32E23x
*/

/*
    Copyright (c) 2019, GigaDevice Semiconductor Inc.

    All rights reserved.

    Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this 
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice, 
       this list of conditions and the following disclaimer in the documentation 
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors 
       may be used to endorse or promote products derived from this software without 
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
*/

#include "gd32e23x.h"
#include "systick.h"

volatile static float count_1us = 0;
volatile static float count_1ms = 0;

/*!
    \brief      configure systick
    \param[in]  none
    \param[out] none
    \retval     none
*/
void systick_config(void)
{
    /* systick clock source is from HCLK/8 */
    systick_clksource_set(SYSTICK_CLKSOURCE_HCLK_DIV8);
    count_1us = (float)SystemCoreClock/8000000;
    count_1ms = (float)count_1us * 1000;
}

/*!
    \brief      delay a time in microseconds in polling mode
    \param[in]  count: count in microseconds
    \param[out] none
    \retval     none
*/
void delay_1us(uint32_t count)
{
    uint32_t ctl;
    
    /* reload the count value */
    SysTick->LOAD = (uint32_t)(count * count_1us);
    /* clear the current count value */
    SysTick->VAL = 0x0000U;
    /* enable the systick timer */
    SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
    /* wait for the COUNTFLAG flag set */
    do{
        ctl = SysTick->CTRL;
    }while((ctl&SysTick_CTRL_ENABLE_Msk)&&!(ctl & SysTick_CTRL_COUNTFLAG_Msk));
    /* disable the systick timer */
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    /* clear the current count value */
    SysTick->VAL = 0x0000U;
}


void delay_us(uint32_t count)
{
    uint32_t ctl;
    
    /* reload the count value */
    SysTick->LOAD = (uint32_t)(count * count_1us);
    /* clear the current count value */
    SysTick->VAL = 0x0000U;
    /* enable the systick timer */
    SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
    /* wait for the COUNTFLAG flag set */
    do{
        ctl = SysTick->CTRL;
    }while((ctl&SysTick_CTRL_ENABLE_Msk)&&!(ctl & SysTick_CTRL_COUNTFLAG_Msk));
    /* disable the systick timer */
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    /* clear the current count value */
    SysTick->VAL = 0x0000U;
}


/*!
    \brief      delay a time in milliseconds in polling mode
    \param[in]  count: count in milliseconds
    \param[out] none
    \retval     none
*/
void delay_1ms(uint32_t count)
{
    uint32_t ctl;
    
    /* reload the count value */
    SysTick->LOAD = (uint32_t)(count * count_1ms);
    /* clear the current count value */
    SysTick->VAL = 0x0000U;
    /* enable the systick timer */
    SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
    /* wait for the COUNTFLAG flag set */
    do{
        ctl = SysTick->CTRL;
    }while((ctl&SysTick_CTRL_ENABLE_Msk)&&!(ctl & SysTick_CTRL_COUNTFLAG_Msk));
    /* disable the systick timer */
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    /* clear the current count value */
    SysTick->VAL = 0x0000U;
}

void delay_ms(uint32_t count)
{
    uint32_t ctl;
    
    /* reload the count value */
    SysTick->LOAD = (uint32_t)(count * count_1ms);
    /* clear the current count value */
    SysTick->VAL = 0x0000U;
    /* enable the systick timer */
    SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
    /* wait for the COUNTFLAG flag set */
    do{
        ctl = SysTick->CTRL;
    }while((ctl&SysTick_CTRL_ENABLE_Msk)&&!(ctl & SysTick_CTRL_COUNTFLAG_Msk));
    /* disable the systick timer */
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    /* clear the current count value */
    SysTick->VAL = 0x0000U;
}

systick.h

/*!
    \file  systick.h
    \brief the header file of systick
    
    \version 2019-02-19, V1.0.0, firmware for GD32E23x
*/

/*
    Copyright (c) 2019, GigaDevice Semiconductor Inc.

    All rights reserved.

    Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this 
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice, 
       this list of conditions and the following disclaimer in the documentation 
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors 
       may be used to endorse or promote products derived from this software without 
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
*/

#ifndef SYS_TICK_H
#define SYS_TICK_H

#include <stdint.h>

/* function declarations */
/* configure systick */
void systick_config(void);
/* delay a time in milliseconds */
void delay_1ms(uint32_t count);

/* delay a time in milliseconds */
void delay_ms(uint32_t count);

/* delay a time in microseconds */
void delay_1us(uint32_t count);

/* delay a time in microseconds */
void delay_us(uint32_t count);

#endif /* SYS_TICK_H */

闪烁LED代码 

#include "gd32e23x.h"
#include "systick.h"

void Z_Init_GPIO(void){
    rcu_periph_clock_enable(RCU_GPIOA);
    gpio_mode_set(GPIOA,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO_PIN_0);
    gpio_output_options_set(GPIOA,GPIO_OTYPE_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_0);
}

int main(void){
    systick_config();
    
    Z_Init_GPIO();
    gpio_bit_write(GPIOA,GPIO_PIN_0,0);

    while(1){
        //gpio_bit_write(GPIOA,GPIO_PIN_0,!gpio_output_bit_get(GPIOA,GPIO_PIN_0));
        gpio_bit_toggle(GPIOA,GPIO_PIN_0);
        delay_ms(500);
    }
}

  • 28
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值