打印
[STM32F1]

STM32F1 GPIO操作宏封装

[复制链接]
457|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

GPIO的操作很常用,使用标准的库函数比较麻烦,尤其在动态指定GPIO引脚时很不方便,正点原子的示例代码中对于GPIO操作宏封装比库函数方便许多。例如对GPIOA的第0个引脚输出和输入的方式如下:

PAout(0) = 1;
if(PAin()){}


使用特权

评论回复
评论
纠结的那些年 2023-8-26 17:56 回复TA
———————————————— 版权声明:本文为CSDN博主「白錵錵」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/bxjie/article/details/101058982 
沙发
纠结的那些年|  楼主 | 2023-8-26 17:55 | 只看该作者
但对于不同的GPIOx的操作还不是很方便,比如在函数参数传递GPIO PIN时需要两个参数,GPIOx和GPIO_Pin_x。

使用特权

评论回复
板凳
纠结的那些年|  楼主 | 2023-8-26 17:55 | 只看该作者
下面分享这段代码帮助解决这个问题,供参考,欢迎留言。

#ifndef _HAL_GPIO_H_
#define _HAL_GPIO_H_

#include <stm32f10x.h>


///
//GPIO MAPPING

typedef enum {
    PIN_INPUT,
    PIN_OUTPUT
} PinDirection_t;

typedef enum
{
        P_A = 0,
        P_B = 1,
        P_C = 2,
        P_D = 3,
        P_E = 4,
        P_F = 5,
        P_G = 6,
} PortSN_t;

typedef enum
{
        P_0 = 0,
        P_1 = 1,
        P_2 = 2,
        P_3 = 3,
        P_4 = 4,
        P_5 = 5,
    P_6 = 6,
        P_7 = 7,
    P_8 = 8,
    P_9 = 9,
    P_10 = 10,
    P_11 = 11,
    P_12 = 12,
    P_13 = 13,
    P_14 = 14,
    P_15 = 15,
} PinSN_t;



typedef enum {
    PA_0  = 0x00,
    PA_1  = 0x01,
    PA_2  = 0x02,
    PA_3  = 0x03,
    PA_4  = 0x04,
    PA_5  = 0x05,
    PA_6  = 0x06,
    PA_7  = 0x07,
    PA_8  = 0x08,
    PA_9  = 0x09,
    PA_10 = 0x0A,
    PA_11 = 0x0B,
    PA_12 = 0x0C,
    PA_13 = 0x0D,
    PA_14 = 0x0E,
    PA_15 = 0x0F,
       
        PB_0  = 0x10,
    PB_1  = 0x11,
    PB_2  = 0x12,
    PB_3  = 0x13,
    PB_4  = 0x14,
    PB_5  = 0x15,
    PB_6  = 0x16,
    PB_7  = 0x17,
    PB_8  = 0x18,
    PB_9  = 0x19,
    PB_10 = 0x1A,
    PB_11 = 0x1B,
    PB_12 = 0x1C,
    PB_13 = 0x1D,
    PB_14 = 0x1E,
    PB_15 = 0x1F,

    PC_0  = 0x20,
    PC_1  = 0x21,
    PC_2  = 0x22,
    PC_3  = 0x23,
    PC_4  = 0x24,
    PC_5  = 0x25,
    PC_6  = 0x26,
    PC_7  = 0x27,
    PC_8  = 0x28,
    PC_9  = 0x29,
    PC_10 = 0x2A,
    PC_11 = 0x2B,
    PC_12 = 0x2C,
    PC_13 = 0x2D,
    PC_14 = 0x2E,
    PC_15 = 0x2F,


    PD_0  = 0x30,
    PD_1  = 0x31,
    PD_2  = 0x32,
    PD_3  = 0x33,
    PD_4  = 0x34,
    PD_5  = 0x35,
    PD_6  = 0x36,
    PD_7  = 0x37,
    PD_8  = 0x38,
    PD_9  = 0x39,
    PD_10 = 0x3A,
    PD_11 = 0x3B,
    PD_12 = 0x3C,
    PD_13 = 0x3D,
    PD_14 = 0x3E,
    PD_15 = 0x3F,
}PinName_t;

typedef struct STPortMapping
{
        PortSN_t portNumber;
        GPIO_TypeDef* portAddr;
}PortMapping_t;

typedef struct STRccMapping
{
        PortSN_t         portSN;
        u32                                  rccAddr;
}RccMapping_t;


typedef struct STExtiIRQMapping
{
        PinSN_t         pinSN;
        u16                         extiIRQ;
}ExtiIRQMapping_t;



static const PortMapping_t PortMapping[]=
{
        {P_A,GPIOA},
        {P_B,GPIOB},
        {P_C,GPIOC},
        {P_D,GPIOD},
        {P_E,GPIOE},
        {P_F,GPIOF},
        {P_G,GPIOG},
};

static const RccMapping_t RccMapping[]=
{
        {P_A,RCC_APB2Periph_GPIOA},
        {P_B,RCC_APB2Periph_GPIOB},
        {P_C,RCC_APB2Periph_GPIOC},
        {P_D,RCC_APB2Periph_GPIOD},
        {P_E,RCC_APB2Periph_GPIOE},
        {P_F,RCC_APB2Periph_GPIOF},
        {P_G,RCC_APB2Periph_GPIOG},
};

static const ExtiIRQMapping_t ExtiIRQMapping[]=
{
    {P_0,EXTI0_IRQn},
    {P_1,EXTI1_IRQn},
    {P_2,EXTI2_IRQn},
    {P_3,EXTI3_IRQn},
    {P_4,EXTI4_IRQn},
    {P_5,EXTI9_5_IRQn},
    {P_6,EXTI9_5_IRQn},
    {P_7,EXTI9_5_IRQn},
    {P_8,EXTI9_5_IRQn},
    {P_9,EXTI9_5_IRQn},
    {P_10,EXTI15_10_IRQn},
    {P_11,EXTI15_10_IRQn},
    {P_12,EXTI15_10_IRQn},
    {P_13,EXTI15_10_IRQn},
    {P_14,EXTI15_10_IRQn},
    {P_15,EXTI15_10_IRQn},
};


// High nibble = port number (0=A, 1=B, 2=C, 3=D, 4=E, 5=F, 6=G, 7=H)
// Low nibble  = pin number
#define PIN_PORT(x) (((uint32_t)(x) >> 4) & 0x0F)
#define PIN_SN(x)  ((uint16_t)(x) & 0x0F)


#define GPIO_MAPPING_PIN(Name)                (u16)(0x01 << PIN_SN(Name))
#define GPIO_MAPPING_RCC(Name)                (u32)(RccMapping[PIN_PORT(Name)].rccAddr)
#define GPIO_MAPPING_PORT(Name)                (GPIO_TypeDef *)(PortMapping[PIN_PORT(Name)].portAddr)

#define GPIO_MAPPING_PORTSN(Name)        (u8)(PIN_PORT(Name))
#define GPIO_MAPPING_PINSN(Name)        (u8)(PIN_SN(Name))

#define GPIO_MAPPING_IRQ(Name)                (u16)(ExtiIRQMapping[PIN_SN(Name)].extiIRQ)
#define GPIO_MAPPING_EXTILINE(Name)        (u16)(0x01 << PIN_SN(Name))

#define GPIO_READ(Name) ((((GPIO_TypeDef *)(GPIO_MAPPING_PORT(Name)))->IDR >> PIN_SN(Name)) & 0x01)
#define GPIO_HI(Name)   (((GPIO_TypeDef *)(GPIO_MAPPING_PORT(Name)))->BSRR = (GPIO_MAPPING_PIN(Name)))
#define GPIO_LOW(Name)  (((GPIO_TypeDef *)(GPIO_MAPPING_PORT(Name)))->BRR = (GPIO_MAPPING_PIN(Name)))                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          

#endif //_HAL_GPIO_H_

使用特权

评论回复
地板
纠结的那些年|  楼主 | 2023-8-26 17:55 | 只看该作者
下面这段为示例程序。
演示程序可以看出,利用PA_0、PB_8这样的方式定义引脚,可以方便的做到复杂的映射关系。
在bool key_IsPressed(PinName_t pin)函数中也可以采用PinName_t类型传递引脚。

使用特权

评论回复
5
纠结的那些年|  楼主 | 2023-8-26 17:55 | 只看该作者
是不是挺方便呢?


#define App_LedOpen(x)      GPIO_LOW(x)
#define App_LedClose(x)     GPIO_HI(x)

#define APP_KEY_ON      0
#define APP_KEY_OFF     1

#define APP_KEYNAME_0       PA_11
#define APP_KEYNAME_1       PA_12
#define APP_KEYNAME_2       PB_8
#define APP_KEYNAME_3       PB_9
#define APP_KEYNAME_4       PC_6
#define APP_KEYNAME_5       PC_7
#define APP_KEYNAME_6       PC_8
#define APP_KEYNAME_7       PC_9


#define APP_LEDNAME_0       PB_12
#define APP_LEDNAME_1       PB_13
#define APP_LEDNAME_2       PB_14
#define APP_LEDNAME_3       PB_15
#define APP_LEDNAME_4       PC_10
#define APP_LEDNAME_5       PC_11
#define APP_LEDNAME_6       PC_12
#define APP_LEDNAME_7       PB_7
                           

typedef struct AppKeyLedMap
{
    PinName_t   keyName;
    PinName_t   LedName;
    bool        flag;
}AppKeyLedMap_t;


static AppKeyLedMap_t gAppKeyLedMap[] =
{
    {APP_KEYNAME_0,APP_LEDNAME_0,0},
    {APP_KEYNAME_1,APP_LEDNAME_1,0},
    {APP_KEYNAME_2,APP_LEDNAME_2,0},
    {APP_KEYNAME_3,APP_LEDNAME_3,0},
    {APP_KEYNAME_4,APP_LEDNAME_4,0},
    {APP_KEYNAME_5,APP_LEDNAME_5,0},
    {APP_KEYNAME_6,APP_LEDNAME_6,0},
    {APP_KEYNAME_7,APP_LEDNAME_7,0}
};


bool key_IsPressed(PinName_t pin)
{
    u8 checkTimes = 2;
    if(GPIO_READ(pin) == APP_KEY_ON)
    {
        DelayMs(20);
        if(GPIO_READ(pin) == APP_KEY_ON)
        {
            while(GPIO_READ(pin) == APP_KEY_ON);
            return  true;
        }
    }
    return false;
}



int main()
{
    u8 v = 0;
    u8 last_v = 0;
    i16 i,j;
     
    CLOCK_Config();   
    GPIO_Config();
    LOG_Config();
   
    for(i = 0;i<8;i++)
    {
        App_LedClose(gAppKeyLedMap[i].LedName);
    }
    DelayMs(500);
    for(i = 0;i<8;i++)
    {
        App_LedOpen(gAppKeyLedMap[i].LedName);
    }
        ..............
}

使用特权

评论回复
6
纠结的那些年|  楼主 | 2023-8-26 17:55 | 只看该作者
演示程序下载:
https://download.csdn.net/download/b_xjie/11790619
做了一排8位按键,对应8个LED。按键控制8个LED对应字节的8位。灯亮代码该位为1,否则该位为0,将此字节及位输出至OLED。
KEIL工程目录及代码结构可以利用。

使用特权

评论回复
7
houcs| | 2023-8-26 23:11 | 只看该作者
可以方便的做到复杂的映射关系

使用特权

评论回复
8
Clyde011| | 2024-9-11 07:32 | 只看该作者

首先是进行按比例和具体的施胶量进行混合操作

使用特权

评论回复
9
公羊子丹| | 2024-9-11 08:25 | 只看该作者

将在原边形成电压尖峰,

使用特权

评论回复
10
万图| | 2024-9-11 09:28 | 只看该作者

使该元器件不超过正常值范围

使用特权

评论回复
11
帛灿灿| | 2024-9-11 12:27 | 只看该作者

ESD静电保护器工作特性与TVS管一致。

使用特权

评论回复
12
Bblythe| | 2024-9-11 13:30 | 只看该作者

环氧树脂、聚胺脂、有机硅灌封胶

使用特权

评论回复
13
周半梅| | 2024-9-11 15:26 | 只看该作者

保护被保护IC或线路

使用特权

评论回复
14
Pulitzer| | 2024-9-11 16:29 | 只看该作者

电源模块的灌封用的胶是可以根据需求而调制的

使用特权

评论回复
15
童雨竹| | 2024-9-11 18:25 | 只看该作者

所以不会通过地损耗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

38

主题

632

帖子

0

粉丝