最近要使用极海的芯片开发项目,又要求不能用HAL库只能使用官方标准库,但是官方标准库面向他们的开发板多一点,后面开发很不方便,就对他们库做点封装,后面开发舒服点。任何32的第一个项目当然是点灯,我们先看官方库怎么初始化一个灯:
` GPIO_Config_T configStruct;
/* Enable the GPIO_LED Clock */
RCM_EnableAHB1PeriphClock(GPIO_CLK[Led]);
/* Configure the GPIO_LED pin */
GPIO_ConfigStructInit(&configStruct);
configStruct.pin = GPIO_PIN[Led];
configStruct.mode = GPIO_MODE_OUT;
configStruct.speed = GPIO_SPEED_50MHz;
GPIO_Config(GPIO_PORT[Led], &configStruct);
GPIO_PORT[Led]->BSCL = GPIO_PIN[Led];`
刚开始声明了一个实例configStruct,再使能了这个gpio的时钟,后面又先初始化了实例configStruct,再给configStruct成员变量赋值。````
GPIO_Config(GPIO_PORT[Led],&configStruct);` 用来初始化这个led的gpio,再赋值led的初始状态。我们来寻找下LED的定义:
typedef enum
{
LED2 = 0,
LED3 = 1
} BOARD_LED_T;
#define LEDn 2
#define LED2_PIN GPIO_PIN_15
#define LED2_GPIO_PORT GPIOC
#define LED2_GPIO_CLK RCM_AHB1_PERIPH_GPIOC
#define LED3_PIN GPIO_PIN_0
#define LED3_GPIO_PORT GPIOE
#define LED3_GPIO_CLK RCM_AHB1_PERIPH_GPIOE
如果只是控制两个gpio还好,控制多个在这后面加#define又或者变成输入模式用另一种写法,这样开发实在有点麻烦。提取一下上面led的成员变量,生成一个结构体去初始化的时候配置,类似于cubemx把一个gpio的所有配置在一个地方初始化会方便很多。
typedef struct gpio_t{
uint32_t *port;
rcc_t *gpio_rcc;
uint16_t pin;
uint8_t mode;
uint8_t speed;
uint8_t otype;
uint8_t pupd;
}gpio_t;
因为每个gpio的时钟不一定一样,为了初始化的时候也可以改变一下再写一个rcc_t,包括后面usart,外部中断等也需要时钟可以用这个做变量:
typedef struct rcc_t{
uint32_t dev_clk;
void (*RCM_DisableAHBXPeriphClock)(uint32_t AHBXPeriph);
void (*RCM_EnableAHBXPeriphClock)(uint32_t AHBXPeriph);
}rcc_t;
后面看官方的init,write,read怎么写的套用一下:
static int gpio_param_check(gpio_t *gpio)
{
if (gpio == 0)
return -1;
if (gpio->port == 0)
return -1;
return 0;
}
int apm32_gpio_init(gpio_t *gpio)
{
GPIO_Config_T gpio_cfg;
GPIO_T *port;
if (gpio_param_check(gpio) != 0)
return -1;
port = (GPIO_T *)gpio->port;
gpio->gpio_rcc->RCM_EnableAHBXPeriphClock(gpio->gpio_rcc->dev_clk);
GPIO_ConfigStructInit(&gpio_cfg);
gpio_cfg.pin = gpio->pin;
gpio_cfg.mode = gpio->mode;
gpio_cfg.speed = gpio->speed;
gpio_cfg.otype = gpio->otype;
gpio_cfg.pupd = gpio->pupd;
GPIO_Config(port, &gpio_cfg);
if(gpio->mode==GPIO_MODE_OUT)port->BSCL=gpio_cfg.pin;
return 0;
}
int apm32_gpio_write(gpio_t *gpio, uint8_t state)
{
GPIO_T *port;
if (gpio == 0 || gpio->port == 0)
return -1;
port = (GPIO_T *)gpio->port;
if (state)
port->BSCL = gpio->pin; // 置位
else
port->BSCH = gpio->pin; // 清零
return 0;
}
int apm32_gpio_read(gpio_t *gpio)
{
GPIO_T *port;
if (gpio_param_check(gpio) != 0)
return -1;
port = (GPIO_T *)gpio->port;
return (port->IDATA & gpio->pin) ? 1 : 0;
}
int apm32_gpio_toggle(gpio_t *gpio)
{
GPIO_T *port;
if (gpio == 0 || gpio->port == 0)
return -1;
port = (GPIO_T *)gpio->port;
if (port->ODATA & gpio->pin)
{
port->BSCH = gpio->pin; // 清零
}
else
{
port->BSCL = gpio->pin; // 置位
}
return 0;
}
main函数里这样写:
static rcc_t gpio_rcc={
.dev_clk=RCM_AHB1_PERIPH_GPIOC,
.RCM_EnableAHBXPeriphClock=RCM_EnableAHB1PeriphClock,
.RCM_DisableAHBXPeriphClock=RCM_EnableAHB1PeriphClock,
};
static gpio_t led1 = {
.port = (uint32_t *)GPIOC,
.gpio_rcc=&gpio_rcc,
.pin = GPIO_PIN_15,
.mode = GPIO_MODE_OUT,
.speed = GPIO_SPEED_50MHz,
.otype = GPIO_OTYPE_PP,
.pupd = GPIO_PUPD_NOPULL,
};
apm32_DelayConfig();
apm32_gpio_init(&led1);
while (1)
{
apm32_gpio_write(&led1,0);
apm32_DelayMs(500);
apm32_gpio_write(&led1,1);
apm32_DelayMs(500);
}`
apm32_DelayMs,apm32_DelayConfig只是对原来SDK里的BOARD_DelayMs,BOARD_DelayConfig改了个名字,没有改动内容。
这样就可以初始化的时候直接用一个变量去初始化,初始化简单一点。