前段时间写了面向对象的推文,算是简单对面向对象进行介绍,现在单独出个系列来深入学习面向对象,例程基于GD32进行编写测试。不知道各位配置GPIO是不是还在用老套路,这篇推文将使用面向对象来配置GPIO,直接就可以对MCU的GPIO进行配置;
eio_pin.h
#ifndef EIO_PIN_H #define EIO_PIN_H /* includes ----------------------------------------------------------------- */ #include#include "gd32f10x.h" #ifdef __cplusplus extern "C" { #endif /* 公共定义 ------------------------------------------------------------------ */ enum pin_mode { /* GPIO mode enum */ PIN_MODE_AIN = 0, PIN_MODE_IN_FLOATING, PIN_MODE_IPD, PIN_MODE_IPU, PIN_MODE_OUT_OD, PIN_MODE_OUT_PP, PIN_MODE_AF_OD, PIN_MODE_AF_PP, PIN_MODE_MAX }; /* 公共类型定义 -------------------------------------------------------------- */ typedef struct eio_pin_data { uint32_t gpio_x; uint32_t pin; } eio_pin_data_t; // 定义类 typedef struct eio_pin { /* 私有的 */ eio_pin_data_t data; enum pin_mode mode; uint8_t status; } eio_pin_t; void eio_pin_init(eio_pin_t * const me, const char *name, enum pin_mode mode); uint8_t eio_pin_get_status(eio_pin_t * const me); void eio_pin_set_status(eio_pin_t * const me, uint8_t status); #ifdef __cplusplus } #endif #endif /* ----------------------------- end of file -------------------------------- */
eio_pin.c
#include "eio_pin.h" /* 私有变量 ------------------------------------------------------------------ */ static const uint32_t gpio_table[] = { GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, }; /* 私有函数 ----------------------------------------------------------------- */ /** * @brief 检查给定的引脚名称是否有效 * @param name 给定的引脚名称 * @retval None. */ static uint8_t _check_pin_name_valid(const char *name) { uint8_t ret = TRUE; uint8_t pin_number; if (!(strlen(name) == 4 && (name[1] == '.'))) { ret = FALSE; goto exit; } if (!((name[0] < 'A' && name[0] > 'G') && (name[2] < '0' && name[2] > '1') && (name[3] < '0' && name[3] > '9'))) { ret = FALSE; goto exit; } pin_number = (name[2] - '0') * 10 + (name[3] - '0'); if (pin_number >= 16) { ret = FALSE; goto exit; } exit: return ret; } /** * @brief 将引脚名称转换为MCU相关引脚数据结构 * @param name 给定的引脚名称 * @param data 引脚数据输出 * @retval None. */ static void _translate_pin_name(const char *name, eio_pin_data_t *data) { /* 检测名称 */ _check_pin_name_valid(name); /* 解析端口 */ data->gpio_x = gpio_table[name[0] - 'A']; /* 解析引脚 */ data->pin = (1 << ((uint8_t)((name[2] - '0') * 10 + (name[3] - '0')))); /* 配置时钟 */ if (name[0] == 'A') { rcu_periph_clock_enable(RCU_GPIOA); } else if (name[0] == 'B') { rcu_periph_clock_enable(RCU_GPIOB); } else if (name[0] == 'C') { rcu_periph_clock_enable(RCU_GPIOC); } else if (name[0] == 'D') { rcu_periph_clock_enable(RCU_GPIOD); } else if (name[0] == 'E') { rcu_periph_clock_enable(RCU_GPIOE); } else if (name[0] == 'F') { rcu_periph_clock_enable(RCU_GPIOF); } else if (name[0] == 'G') { rcu_periph_clock_enable(RCU_GPIOG); } } /** * @brief EIO引脚初始化 * @param me this指针 * @param name 引脚名字, 就像“A.01”或“B.14”等等. * @param mode 引脚模式. * @retval None */ void eio_pin_init(eio_pin_t * const me, const char *name, enum pin_mode mode) { /* 使能外设时钟 */ _translate_pin_name(name, &me->data); /* 模式赋值 */ me->mode = mode; /* 配置GPIO引脚 */ if (mode == PIN_MODE_AIN) { /* 配置GPIO端口:模拟输入 */ gpio_init(me->data.gpio_x, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, me->data.pin); /* 复位GPIO引脚 */ gpio_bit_reset(me->data.gpio_x, me->data.pin); } else if (mode == PIN_MODE_IN_FLOATING) { /* 配置GPIO端口:浮空输入 */ gpio_init(me->data.gpio_x, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, me->data.pin); /* 复位GPIO引脚 */ gpio_bit_reset(me->data.gpio_x, me->data.pin); } else if (mode == PIN_MODE_IPD) { /* 配置GPIO端口:下拉输入 */ gpio_init(me->data.gpio_x, GPIO_MODE_IPD, GPIO_OSPEED_50MHZ, me->data.pin); /* 复位GPIO引脚 */ gpio_bit_reset(me->data.gpio_x, me->data.pin); } else if (mode == PIN_MODE_IPU) { /* 配置GPIO端口:上拉输入 */ gpio_init(me->data.gpio_x, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, me->data.pin); /* 复位GPIO引脚 */ gpio_bit_reset(me->data.gpio_x, me->data.pin); } else if (mode == PIN_MODE_OUT_OD) { /* 配置GPIO端口:开漏输出 */ gpio_init(me->data.gpio_x, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, me->data.pin); /* 复位GPIO引脚 */ gpio_bit_reset(me->data.gpio_x, me->data.pin); /* 拉低GPIO输出 */ gpio_bit_write(me->data.gpio_x, me->data.pin, RESET); } else if (mode == PIN_MODE_OUT_PP) { /* 配置GPIO端口:推挽输出 */ gpio_init(me->data.gpio_x, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, me->data.pin); /* 复位GPIO引脚 */ gpio_bit_reset(me->data.gpio_x, me->data.pin); /* 拉低GPIO输出 */ gpio_bit_write(me->data.gpio_x, me->data.pin, RESET); } else if (mode == PIN_MODE_AF_OD) { /* 配置GPIO端口:AFIO开漏输出 */ gpio_init(me->data.gpio_x, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, me->data.pin); /* 复位GPIO引脚 */ gpio_bit_reset(me->data.gpio_x, me->data.pin); /* 拉低GPIO输出 */ gpio_bit_write(me->data.gpio_x, me->data.pin, RESET); } else if (mode == PIN_MODE_AF_PP) { /* 配置GPIO端口:AFIO推挽输出 */ gpio_init(me->data.gpio_x, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, me->data.pin); /* 复位GPIO引脚 */ gpio_bit_reset(me->data.gpio_x, me->data.pin); /* 拉低GPIO输出 */ gpio_bit_write(me->data.gpio_x, me->data.pin, RESET); } /* 更新引脚状态 */ eio_pin_get_status(me); } /** * @brief EIO引脚状态获取功能 * @param me this指针 * @retval 引脚的状态 */ uint8_t eio_pin_get_status(eio_pin_t * const me) { uint8_t status = gpio_input_bit_get(me->data.gpio_x, me->data.pin); me->status = (status == SET) ? TRUE : FALSE; return me->status; } /** * @brief EIO引脚状态开启功能 * @param me this指针 * @param status 输入引脚状态 * @retval 无 */ void eio_pin_set_status(eio_pin_t * const me, uint8_t status) { if (status != me->status) { gpio_bit_write(me->data.gpio_x, me->data.pin, status ? SET : RESET); /* 更新引脚状态 */ eio_pin_get_status(me); } } main.c
#include "gd32f10x.h" #include "hal_log.h" #include "hal_printf.h" #include "eio_pin.h" // 实例化对象 eio_pin_t pin_led; eio_pin_t pin_key; // 主循环 int main(void) { hal_log_init(); eio_pin_init(&pin_led, "E.02", PIN_MODE_OUT_PP); eio_pin_init(&pin_key, "E.03", PIN_MODE_IN_FLOATING); while (1) { eio_pin_set_status(&pin_led, 0); if( eio_pin_get_status(&pin_key) ) { printfk(USART0,"h "); }else{ printfk(USART0,"l "); } } }通过eio_pin文件就可以对mcu的gpio进行配置,通过实例不同的对象绑定相关信息,即可完成gpio的常规配置,非常方便应用层的调用。
编辑:黄飞
评论
查看更多