Bootstrap

华大HC32F460 GPIO口代码解读

一、GPIO口基础知识

HC32F460系列提供了PAy-PHy,y=0-16的IO口。主要是特性:

  1. 每组Port配有16个I/O Pin,根据实际配置可能不足16个

  1. 支持上拉、推挽,开漏输出模式

  1. 支持外部中断的输入

  1. 支持I/O Pin周边功能服用,一个I/O Pin最多可具有64个可选择的复用功能。

  1. 各个I/O Pin可独立编程

  1. 各个I/O Pin可以选择2个功能同时有效(不支持2个输出功能同时有效)

二、代码实现

首先 先看GPIO初始化的结构体

typedef struct {
    uint16_t u16PinState;       /*!< 设置使能引脚 >  */
    uint16_t u16PinDir;         /*!< 设置引脚模式  */
    uint16_t u16PinOutputType;  /*!< 设置输出类型:推挽、开漏   */
    uint16_t u16PinDrv;         /*!< 设置引脚驱动能力:高、中、低型驱动模式  */
    uint16_t u16Latch;          /*!< 设置引脚锁存   */
    uint16_t u16PullUp;         /*!< 设置上拉电阻是否使能     */
    uint16_t u16Invert;         /*!< 设置输入/输出翻转模式       */
    uint16_t u16ExtInt;         /*!< 设置外部中断引脚  */
    uint16_t u16PinAttr;        /*!< 设置引脚口是 数字 还是 模拟。 */
} stc_gpio_init_t;

在文件hc32f4xx_conf.h中开启宏

#define LL_GPIO_ENABLE                              (DDL_ON)

三、以点亮LED为例

定义LED相关IO口的宏

/* LED_R Port/Pin definition */
#define LED_R_PORT          (GPIO_PORT_D)
#define LED_R_PIN           (GPIO_PIN_03)
/* LED_G Port/Pin definition */
#define LED_G_PORT          (GPIO_PORT_D)
#define LED_G_PIN           (GPIO_PIN_04)
/* LED_Y Port/Pin definition */
#define LED_Y_PORT          (GPIO_PORT_D)
#define LED_Y_PIN           (GPIO_PIN_05)
/* LED_B Port/Pin definition */
#define LED_B_PORT          (GPIO_PORT_D)
#define LED_B_PIN           (GPIO_PIN_06)

使用华大官方提供的输入输出翻转功能

#define LED_R_TOGGLE()      (GPIO_TogglePins(LED_R_PORT, LED_R_PIN))
#define LED_G_TOGGLE()      (GPIO_TogglePins(LED_G_PORT, LED_G_PIN))
#define LED_Y_TOGGLE()      (GPIO_TogglePins(LED_Y_PORT, LED_Y_PIN))
#define LED_B_TOGGLE()      (GPIO_TogglePins(LED_B_PORT, LED_B_PIN))

详细看看GPIO_TogglePins()函数。

void GPIO_TogglePins(uint8_t u8Port, uint16_t u16Pin)
{
    __IO GPIO_REG_TYPE *POTRx;

    /* Parameter validity checking */
    DDL_ASSERT(IS_GPIO_PORT(u8Port));
    DDL_ASSERT(IS_GPIO_PIN(u16Pin));

    POTRx = &POTR_REG(u8Port); //PORT_REG对应是通用输出翻转寄存器(POTRx),具体看用户手册。
    SET_REG_BIT(*POTRx, (GPIO_REG_TYPE)u16Pin);//置1 对应引脚翻转,置0 无变化
}

实现延时

void DDL_DelayMS(uint32_t u32Count)
{
    __IO uint32_t i;
    const uint32_t u32Cyc = (HCLK_VALUE + 10000UL - 1UL) / 10000UL;

    while (u32Count-- > 0UL) {
        i = u32Cyc;
        while (i-- > 0UL) {
        }
    }
}

主函数:

#define DLY_MS              (100UL)
int32_t main(void)
{
    /* Register write enable for some required peripherals. */
    LL_PERIPH_WE(LL_PERIPH_GPIO);//使用寄存器前需要将相关的寄存器写保护关闭
    /* LED initialize */
    LED_Init();
    /* Register write protected for some required peripherals. */
    LL_PERIPH_WP(LL_PERIPH_GPIO);//使用完寄存器后 需要将相关的寄存器 写保护重新开启。
    for (;;) {
        LED_R_TOGGLE();
        DDL_DelayMS(DLY_MS);
        LED_G_TOGGLE();
        DDL_DelayMS(DLY_MS);
        LED_Y_TOGGLE();
        DDL_DelayMS(DLY_MS);
        LED_B_TOGGLE();
        DDL_DelayMS(DLY_MS);
        /* De-init port if necessary */
        // GPIO_DeInit();
    }
}

鉴于很多小白和我一样,不知道UL是什么,这里特别声明UL表示 unsigned long 类型。

;