编程语言及工具
前段时间写了面向对象的推文,算是简单对面向对象进行介绍,现在单独出个系列来深入学习面向对象,例程基于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的常规配置,非常方便应用层的调用。
编辑:黄飞
全部0条评论
快来发表一下你的评论吧 !