最近突然想研究研究STM32,看到几乎所有的教程上都是用C编单片机程序的,让一直研究C艹的我编写起来很不适应,今天研究了一中午,成功地将一个 单个LED的驱动封装成了一个Arduino风格的类库,使用起来非常方便,方法如下。
在开始之前,建议按照STM32模板建立方法此文中描述的方法将工程需要的基本库放到一个文件夹中,这样在添加.c和.h文件的时候会更加容易。
1. 为了将驱动封装到一个类中,首先定义驱动代码的头文件 led.h。
#ifndef LED_H
#define LED_H
#include "stm32f10x_gpio.h"
class Led
{
enum State{HIGH, LOW};
public:
Led(GPIO_TypeDef* GPIOX, uint16_t GPIO_Pin_x, State s = HIGH);
virtual ~Led();
void Open();
void Close();
inline bool IsOpen() const {return isOpen;}
private:
GPIO_TypeDef* GPIOX;
uint16_t GPIO_Pin_x;
bool isOpen;
};
#endif
类名起做Led,构造函数的三个参数依次是该小灯泡所在的IO口线,小灯泡的IO口号和IO口的初始状态(小灯泡一端已经接高电平,IO口默认为高)。添加公有的点亮LED和关闭LED的方法声明,以及一个内联函数返回当前小灯泡的状态。
2. 接下来定义这个类的实现,新建一个.cpp文件,注意不能是.c否则无法通过编译。
#include "led.h"
Led::Led(GPIO_TypeDef* GPIOX, uint16_t GPIO_Pin_x, State s)
{
isOpen =false;
this->GPIOX = GPIOX;
this->GPIO_Pin_x = GPIO_Pin_x;
// 设置端口时钟
if (GPIOX == GPIOA)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
}
else if (GPIOX == GPIOB)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
}
else if (GPIOX == GPIOC)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
}
else if (GPIOX == GPIOD)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
}
else if (GPIOX == GPIOE)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
}
else if (GPIOX == GPIOF)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
}
else if (GPIOX == GPIOG)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);
}
GPIO_InitTypeDef init;
// 配置IO口
init.GPIO_Pin = GPIO_Pin_x;
init.GPIO_Mode = GPIO_Mode_Out_PP;
init.GPIO_Speed = GPIO_Speed_50MHz;
// 初始化IO口
GPIO_Init(GPIOX, &init);
if (s == HIGH)
{
GPIO_SetBits(GPIOX, GPIO_Pin_x);
}
else
{
GPIO_ResetBits(GPIOX, GPIO_Pin_x);
}
}
Led::~Led()
{
}
void Led::Open()
{
GPIO_ResetBits(GPIOX, GPIO_Pin_x);
isOpen = true;
}
void Led::Close()
{
GPIO_SetBits(GPIOX, GPIO_Pin_x);
isOpen = false;
}
首先根据函数参数设定对应的端口时钟,然后常规地配置IO口即可。最后将ResetBits()和SetBits()函数分别写在打开和关闭函数中。这样就实现了驱动的简单封装。
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
int main()
{
Delayer mydelay;
Led myLed(GPIOA, GPIO_Pin_2);
while (1)
{
myLed.Open();
myDelay.Delay(500);
myLed.Close();
myDelay.Delay(500);
}
return 0;
}
使用时,直接把类实例化,调用合适的公共方法即可。
如果想实现控制多个GPIO口,可以实例化多个对象,或者重载类的构造函数。