关闭

STM32F10X便利的GPIO驱动设计(C++,基于基础库)

标签: stm32
241人阅读 评论(0) 收藏 举报
分类:

目的

该驱动的目的是使用户更加简单的配置GPIO,并且封装成为类后,相较于基础库,管脚信息获取与设置更加清晰简单,层次结构更好

使用效果

#include "GPIO.h"
#include "Delay.h"

GPIO RedLed(GPIOA,1,GPIO_Mode_Out_PP,GPIO_Speed_50MHz);

int main()
{
        bool Level = false;
        RedLed.SetLevel(1);//设置管脚电平为高
        while(1)
        {
            RedLed.Toggle(); //翻转电平
            Level=RedLed.GetLevel();//获取当前管脚电平
            Delay::Ms(100);

        }
}

还可以将定于的管脚作为参数传入到其他C++驱动类中去。

基础知识

GPIO模式

  1. 输入浮空
  2. 输入上拉
  3. 输入下拉
  4. 模拟输入
  5. 开漏输出
  6. 推挽式输出
  7. 推挽式复用功能
  8. 开漏复用功能
    这里写图片描述

GPIO速率

这里写图片描述

外设的GPIO配置

引用至官方手册

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

代码中使用的库函数

1、函数GPIO_Init
这里写图片描述

2、函数GPIO_SetBits
这里写图片描述

3、函数GPIO_ResetBits
这里写图片描述

4、函数GPIO_ReadInputDataBit
这里写图片描述

代码设计

因为这个驱动相对简单,就没有进行文件设计,而直接从代码讲起。

首先第一步就是对GPOI进行初始化话了,而进行初始化需要知道GPIOx和Pin_y,管脚模式和速率。我们决定在定义类的对象的时候就进行相关配置,于是这些未知量就成为了构造函数的参数了

GPIO(GPIO_TypeDef *port,uint16_t pin,
                        GPIOMode_TypeDef mode,
                        GPIOSpeed_TypeDef speed);

构造函数的第二个参数,未使用库函数的GPIO_Pin_X这种表示方式,主要是觉得输入麻烦,要使用2号管脚直接输入2就好了。而在系统封装库中,数字和管脚不是对应的,因为要操作寄存器嘛

#define GPIO_Pin_0                 ((uint16_t)0x0001)  /*!< Pin 0 selected */
#define GPIO_Pin_1                 ((uint16_t)0x0002)  /*!< Pin 1 selected */
#define GPIO_Pin_2                 ((uint16_t)0x0004)  /*!< Pin 2 selected */
#define GPIO_Pin_3                 ((uint16_t)0x0008)  /*!< Pin 3 selected */
#define GPIO_Pin_4                 ((uint16_t)0x0010)  /*!< Pin 4 selected */
#define GPIO_Pin_5                 ((uint16_t)0x0020)  /*!< Pin 5 selected */
#define GPIO_Pin_6                 ((uint16_t)0x0040)  /*!< Pin 6 selected */
#define GPIO_Pin_7                 ((uint16_t)0x0080)  /*!< Pin 7 selected */
#define GPIO_Pin_8                 ((uint16_t)0x0100)  /*!< Pin 8 selected */
#define GPIO_Pin_9                 ((uint16_t)0x0200)  /*!< Pin 9 selected */
#define GPIO_Pin_10                ((uint16_t)0x0400)  /*!< Pin 10 selected */
#define GPIO_Pin_11                ((uint16_t)0x0800)  /*!< Pin 11 selected */
#define GPIO_Pin_12                ((uint16_t)0x1000)  /*!< Pin 12 selected */
#define GPIO_Pin_13                ((uint16_t)0x2000)  /*!< Pin 13 selected */
#define GPIO_Pin_14                ((uint16_t)0x4000)  /*!< Pin 14 selected */
#define GPIO_Pin_15                ((uint16_t)0x8000)  /*!< Pin 15 selected */
#define GPIO_Pin_All               ((uint16_t)0xFFFF)  /*!< All pins selected */

于是我们就定义了一个转化数组

static const  uint16_t      mPin[16];

定义如下

const  uint16_t  GPIO::mPin[16]={GPIO_Pin_0,GPIO_Pin_1,GPIO_Pin_2,GPIO_Pin_3,GPIO_Pin_4,GPIO_Pin_5,GPIO_Pin_6,GPIO_Pin_7,                   GPIO_Pin_8,GPIO_Pin_9,GPIO_Pin_10,GPIO_Pin_11,GPIO_Pin_12,GPIO_Pin_13,GPIO_Pin_14,GPIO_Pin_15};

由于每一类GPIO开启的时钟不同,在构造函数获取到GPIOx后,以此判断开启对应的时钟。

void GPIO::RCC_Configuration()
{
    if(mPort==GPIOA)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    }
    else if(mPort==GPIOB)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    }
    else if(mPort==GPIOC)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
    }
    else if(mPort==GPIOD)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
    }
    else if(mPort==GPIOE)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
    }
    else if(mPort==GPIOF)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE);
    }
    else if(mPort==GPIOG)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);
    }
}

接下来构造函数就简单多了,执行上面函数后进行GPIO配置即可

GPIO::GPIO(GPIO_TypeDef *port,uint16_t pin,GPIOMode_TypeDef mode,GPIOSpeed_TypeDefspeed)
:mMode(mode),mSpeed(speed),mPort(port),mSelectPin(pin)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_Configuration();
    GPIO_InitStructure.GPIO_Pin=mPin[pin];
    GPIO_InitStructure.GPIO_Speed=speed;
    GPIO_InitStructure.GPIO_Mode=mode;
    GPIO_Init(mPort,&GPIO_InitStructure);   
}

之后就是封装使用的各个接口了,这里只编了读取管脚电平,设置管脚电平,翻转电平函数,其他函数就你们自己去写啦~

void GPIO::SetLevel(u8 level)
{
    if(level>0)
        GPIO_SetBits(mPort,mPin[mSelectPin]);
    else
        GPIO_ResetBits(mPort,mPin[mSelectPin]);
}

bool GPIO::GetLevel()
{
    if(!GPIO_ReadInputDataBit(mPort,mPin[mSelectPin]))
        return false;
    else
        return true;
}

void GPIO::Toggle()
{
    if(GPIO_ReadInputDataBit(mPort,mPin[mSelectPin]))
        GPIO_ResetBits(mPort,mPin[mSelectPin]);
    else
        GPIO_SetBits(mPort,mPin[mSelectPin]);
}

附言

和之前写的定时器一样。没有在一个封装里面加入其他东西,如输入捕获、外部中断什么的,主要原因是要经量分割各个驱动,方便维护和修改,也让结构层次清晰一些。

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

STM32F10X便利的定时器C++驱动设计(基于基础库)

目的该驱动的目的是使用户远离繁琐的定时器配置,而更关心代码逻辑,加快项目开发。使用效果1.用户只需要在主函数中定义一个定时器Timer tim(TIM2,1,2,3);//使用定时器2 计时 :1s ...
  • lissettecarlr
  • lissettecarlr
  • 2016-08-26 11:42
  • 596

Android 驱动 (一) GPIO

前面的博文对Lichee做了系列分析,其实就是对在《七年之痒》中所说的,Android BSP具备的一项基本素质-SHELL脚本,所以我们Lichee系列的文章着重分析了SHELL脚本和Lichee的...
  • blood_defences
  • blood_defences
  • 2014-06-06 17:05
  • 2542

LINUX之GPIO驱动及接口使用

打算跟着友善之臂的《mini2440 Linux移植开发指南》 见 http://www.linuxidc.com/Linux/2011-06/37904.htm 来做个LED驱动,虽然LED的原...
  • s762888517
  • s762888517
  • 2013-06-21 10:59
  • 5492

STM32F1x系列——GPIO操作

GPIO 即通用输入输出口。凡事都要熟悉,熟能生巧。一定要掌握MDK软件的工程操作方法。 对于GPIO的操作。 Project里面要有以下几个文件夹(开发之前需要包含相应的库文件,这里默认已经包含...
  • perfectguyipeng
  • perfectguyipeng
  • 2017-05-28 21:33
  • 667

linux驱动开发(一)—GPIO驱动框架

前言          GPIO驱动是Linux驱动开发中最基础、但却是很常用、很重要的驱动。比如你要点亮一个LED灯、键盘扫描、输出高低电平等等。而Linux内核的强大之处在于对最底层的GPIO硬...
  • zengxianyang
  • zengxianyang
  • 2016-01-26 20:18
  • 5135

linux 标准GPIO 驱动模型—version1

学习培训中
  • xuefeng_apple
  • xuefeng_apple
  • 2015-09-05 22:28
  • 1517

BBB GPIO驱动分析

一、 说明 IO驱动是驱动开发最基础也是很有代表性的,因为IO驱动基本包含了驱动框架中的所有常用函数,例如加载函数、卸载函数、打开函数、关闭函数、IO配置函数,此外还包括设备结构体、存储结构体。具体...
  • AA0210AA
  • AA0210AA
  • 2015-04-27 14:32
  • 797

教大家如何在dragonboard410c 上直接操作GPIO操作设备

前言
  • weijory
  • weijory
  • 2017-02-23 12:05
  • 635

字符型设备驱动程序--gpio 驱动实例

概述: 字符设备驱动程序: 是按照字符设备要求完成的由操作系统调用的代码。 重点理解以下内容:  1. 驱动是写给操作系统的代码,它不是直接给用户层程序调用的,而是给系统调用的  2. 所以驱动要向系...
  • hejinjing_tom_com
  • hejinjing_tom_com
  • 2014-05-09 18:03
  • 4817

GPIO按键驱动分析(包括矩阵按键)

一 Gpio_keys.c分析   1.      input device的注册是怎么样的,调用了哪些公用的函数   首先使用了late_initcall宏定义对驱动模型进行加载,在gpio...
  • feng85016578
  • feng85016578
  • 2016-09-27 10:25
  • 1492
    个人资料
    • 访问:15471次
    • 积分:428
    • 等级:
    • 排名:千里之外
    • 原创:27篇
    • 转载:0篇
    • 译文:1篇
    • 评论:10条
    文章分类
    最新评论