STM32片上驱动 - GPIO驱动

一、GPIO端口

STM32芯片根据芯片不通具有多组GPIO端口,分别为:A、B、C、D、E、F、G,每一组有16个GPIO端口(编号为0~15);

使用“GPIOx(x:组别名称).端口编号”或者使用“Px(x:组别名称).端口编号”格式来表示具体使用的GPIO端口,每个GPIO端口都具有多功能模式,GPIO端口默认功能为输入功能;

例:使用GPIO A组编号15的端口,则使用PA.15(PA15)或GPIOA.15来表示;

二、GPIO功能

浮空输入

GPIO端口电平状态不确定,完全由外部输入决定,一般用于处理信号;

上拉输入

在没有外接输入的情况下,能够让GPIO端口有一个确定的高电平信号,用于对输入电平信号进行检测(用于检测外部低电平);

下拉输入

在没有外接输入的情况下,能够让GPIO端口有一个确定的低电平信号,用于对输入电平信号进行检测(用于检测外部高电平);

模拟功能

芯片内部ADC或DAC模块专用功能(analog-digital);

具有上拉或下拉功能的开漏输出

开漏输出也称为断开输出,可以正常输出低电平(0),没有输出高电平(1)的能力;

如果需要输出高电平(1),则需要配置成上拉功能的开漏输出(芯片内部上拉属于弱上拉,驱动能力很小,如果需要获得较强的驱动能力,需要在芯片外部外接上拉电阻);

具有上拉或下拉功能的推挽输出

推挽输出可以输出高电平(1),也可以输出低电平(0);

具有上拉或下拉功能的复用功能推挽

复用功能是指GPIO端口的第二功能(除了默认功能以外的功能),也就是对片内外设进行通信时功能管脚的专用功能,复用功能推挽是指当GPIO端口作为第二功能时配置为推挽输出模式;

具有上拉或下拉功能的复用功能开漏

复用功能推挽是指当GPIO端口作为第二功能时配置为开漏输出模式;

三、GPIO复用

1、外设功能管脚复用概念

STM32芯片所有的片内外设模块的功能引脚(除了GPIO端口以外)都是使用GPIO端口的复用功能,并且每个GPIO端口都会对应有多个复用模块的功能。

2、外设功能管脚复用

注:每个GPIO端口可用复用功能在出厂时已经固定,选择端口复用功能必须满足管脚是否可以实现为前提。

四、GPIO操作

1、使用PIN驱动程序

2、GPIO输出

rt_pin_mode() 设置引脚模式

rt_pin_write() 设置引脚电平

#include <rtthread.h>

#include <rtdevice.h>

#include <drv_common.h>

#define pinTest GET_PIN(F, 9)

rt_pin_mode(pinTest, PIN_MODE_OUTPUT);

rt_pin_write(pinTest, PIN_LOW);

3、GPIO输入

rt_pin_mode() 设置引脚模式

rt_pin_read() 读取引脚电平

输入模式:

#define PIN_MODE_INPUT          0x01

#define PIN_MODE_INPUT_PULLUP   0x02

#define PIN_MODE_INPUT_PULLDOWN 0x03

#include <rtthread.h>

#include <rtdevice.h>

#include <drv_common.h>

#define pinTest GET_PIN(F, 9)

rt_pin_mode(pinTest, PIN_MODE_INPUT_PULLUP);

rt_base_t pinInstance = pinTest;

uint8_t status = rt_pin_read(pinInstance);

4、GPIO外部中断

外部中断(EXTI)是指直接能作用于GPIO端口,直接引用芯片外部的信号作为中断源

外部中断框图:

rt_pin_attach_irq() 绑定引脚中断回调函数

rt_pin_irq_enable() 使能引脚中断

rt_pin_detach_irq() 脱离引脚中断回调函数

触发边沿:

#define PIN_IRQ_MODE_RISING             0x00

#define PIN_IRQ_MODE_FALLING            0x01

#define PIN_IRQ_MODE_RISING_FALLING     0x02

#include <rtthread.h>

#include <rtdevice.h>

#include <drv_common.h>

void gpioCallback(void *args)

{

    rt_kprintf("gpioCallback!\n");

}

#define pinTest GET_PIN(E, 4)

rt_pin_mode(pinTest, PIN_MODE_INPUT_PULLUP);

rt_pin_attach_irq(pinTest, PIN_IRQ_MODE_FALLING, gpioCallback, RT_NULL);

rt_pin_irq_enable(pinTest, PIN_IRQ_ENABLE);

注意:先绑定回调函数再使能中断,引脚脱离了中断回调函数以后,中断并没有关闭,还可以调用绑定中断回调函数再次绑定其他回调函数。

电平检测示例(中断+定时器回调[延时消抖]):

typedef enum {

    XXX_STATUS_RELEASE = 0, // 释放

    XXX_STATUS_PRESS        // 按下

} xxxStatus_e;

typedef void (*m_xxxCallbackPtr)(uint8_t status);

m_xxxCallbackPtr m_xxxCallback = NULL;

static rt_base_t xxxPin;

static rt_timer_t xxxTimer;

static void xxxEdge(void *args)

{

    rt_timer_start(xxxTimer);

}

static void xxxTimeout(void *parameter)

{

    if (rt_pin_read(xxxPin) == PIN_HIGH) {

        if(m_xxxCallback != NULL) m_xxxCallback(XXX_STATUS_PRESS);

    } else {

        if(m_xxxCallback != NULL) m_xxxCallback(XXX_STATUS_RELEASE);

    }

}

bool xxxInit(rt_base_t pin, uint16_t delayms, void (*callback)(uint8_t status))

{

    xxxPin = pin;

    m_xxxCallback = callback;

    rt_pin_mode(pin, PIN_MODE_INPUT_PULLDOWN);

    rt_pin_attach_irq(pin, PIN_IRQ_MODE_RISING_FALLING, xxxEdge, RT_NULL);

    rt_pin_irq_enable(pin, PIN_IRQ_ENABLE);

    // 创建消抖定时器

    xxxTimer = rt_timer_create("xxxTimer", xxxTimeout, RT_NULL, delayms, RT_TIMER_FLAG_ONE_SHOT);

    if (xxxTimer == RT_NULL) {

        rt_kprintf("xxxTimer creation failed!\n");

        return false;

    }

    return true;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值