前段時間寫了面向對象的推文,算是簡單對面向對象進行介紹,現在單獨出個系列來深入學習面向對象,例程基于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的常規配置,非常方便應用層的調用。
編輯:黃飛
?
電子發燒友App



















評論