[STM32F1] STM32F1 GPIO操作宏封装

[复制链接]
887|15
 楼主| 纠结的那些年 发表于 2023-8-26 17:54 | 显示全部楼层 |阅读模式

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

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


评论

———————————————— 版权声明:本文为CSDN博主「白錵錵」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/bxjie/article/details/101058982  发表于 2023-8-26 17:56
 楼主| 纠结的那些年 发表于 2023-8-26 17:55 | 显示全部楼层
但对于不同的GPIOx的操作还不是很方便,比如在函数参数传递GPIO PIN时需要两个参数,GPIOx和GPIO_Pin_x。
 楼主| 纠结的那些年 发表于 2023-8-26 17:55 | 显示全部楼层
下面分享这段代码帮助解决这个问题,供参考,欢迎留言。

  1. #ifndef _HAL_GPIO_H_
  2. #define _HAL_GPIO_H_

  3. #include <stm32f10x.h>


  4. ///
  5. //GPIO MAPPING

  6. typedef enum {
  7.     PIN_INPUT,
  8.     PIN_OUTPUT
  9. } PinDirection_t;

  10. typedef enum
  11. {
  12.         P_A = 0,
  13.         P_B = 1,
  14.         P_C = 2,
  15.         P_D = 3,
  16.         P_E = 4,
  17.         P_F = 5,
  18.         P_G = 6,
  19. } PortSN_t;

  20. typedef enum
  21. {
  22.         P_0 = 0,
  23.         P_1 = 1,
  24.         P_2 = 2,
  25.         P_3 = 3,
  26.         P_4 = 4,
  27.         P_5 = 5,
  28.     P_6 = 6,
  29.         P_7 = 7,
  30.     P_8 = 8,
  31.     P_9 = 9,
  32.     P_10 = 10,
  33.     P_11 = 11,
  34.     P_12 = 12,
  35.     P_13 = 13,
  36.     P_14 = 14,
  37.     P_15 = 15,
  38. } PinSN_t;



  39. typedef enum {
  40.     PA_0  = 0x00,
  41.     PA_1  = 0x01,
  42.     PA_2  = 0x02,
  43.     PA_3  = 0x03,
  44.     PA_4  = 0x04,
  45.     PA_5  = 0x05,
  46.     PA_6  = 0x06,
  47.     PA_7  = 0x07,
  48.     PA_8  = 0x08,
  49.     PA_9  = 0x09,
  50.     PA_10 = 0x0A,
  51.     PA_11 = 0x0B,
  52.     PA_12 = 0x0C,
  53.     PA_13 = 0x0D,
  54.     PA_14 = 0x0E,
  55.     PA_15 = 0x0F,
  56.        
  57.         PB_0  = 0x10,
  58.     PB_1  = 0x11,
  59.     PB_2  = 0x12,
  60.     PB_3  = 0x13,
  61.     PB_4  = 0x14,
  62.     PB_5  = 0x15,
  63.     PB_6  = 0x16,
  64.     PB_7  = 0x17,
  65.     PB_8  = 0x18,
  66.     PB_9  = 0x19,
  67.     PB_10 = 0x1A,
  68.     PB_11 = 0x1B,
  69.     PB_12 = 0x1C,
  70.     PB_13 = 0x1D,
  71.     PB_14 = 0x1E,
  72.     PB_15 = 0x1F,

  73.     PC_0  = 0x20,
  74.     PC_1  = 0x21,
  75.     PC_2  = 0x22,
  76.     PC_3  = 0x23,
  77.     PC_4  = 0x24,
  78.     PC_5  = 0x25,
  79.     PC_6  = 0x26,
  80.     PC_7  = 0x27,
  81.     PC_8  = 0x28,
  82.     PC_9  = 0x29,
  83.     PC_10 = 0x2A,
  84.     PC_11 = 0x2B,
  85.     PC_12 = 0x2C,
  86.     PC_13 = 0x2D,
  87.     PC_14 = 0x2E,
  88.     PC_15 = 0x2F,


  89.     PD_0  = 0x30,
  90.     PD_1  = 0x31,
  91.     PD_2  = 0x32,
  92.     PD_3  = 0x33,
  93.     PD_4  = 0x34,
  94.     PD_5  = 0x35,
  95.     PD_6  = 0x36,
  96.     PD_7  = 0x37,
  97.     PD_8  = 0x38,
  98.     PD_9  = 0x39,
  99.     PD_10 = 0x3A,
  100.     PD_11 = 0x3B,
  101.     PD_12 = 0x3C,
  102.     PD_13 = 0x3D,
  103.     PD_14 = 0x3E,
  104.     PD_15 = 0x3F,
  105. }PinName_t;

  106. typedef struct STPortMapping
  107. {
  108.         PortSN_t portNumber;
  109.         GPIO_TypeDef* portAddr;
  110. }PortMapping_t;

  111. typedef struct STRccMapping
  112. {
  113.         PortSN_t         portSN;
  114.         u32                                  rccAddr;
  115. }RccMapping_t;


  116. typedef struct STExtiIRQMapping
  117. {
  118.         PinSN_t         pinSN;
  119.         u16                         extiIRQ;
  120. }ExtiIRQMapping_t;



  121. static const PortMapping_t PortMapping[]=
  122. {
  123.         {P_A,GPIOA},
  124.         {P_B,GPIOB},
  125.         {P_C,GPIOC},
  126.         {P_D,GPIOD},
  127.         {P_E,GPIOE},
  128.         {P_F,GPIOF},
  129.         {P_G,GPIOG},
  130. };

  131. static const RccMapping_t RccMapping[]=
  132. {
  133.         {P_A,RCC_APB2Periph_GPIOA},
  134.         {P_B,RCC_APB2Periph_GPIOB},
  135.         {P_C,RCC_APB2Periph_GPIOC},
  136.         {P_D,RCC_APB2Periph_GPIOD},
  137.         {P_E,RCC_APB2Periph_GPIOE},
  138.         {P_F,RCC_APB2Periph_GPIOF},
  139.         {P_G,RCC_APB2Periph_GPIOG},
  140. };

  141. static const ExtiIRQMapping_t ExtiIRQMapping[]=
  142. {
  143.     {P_0,EXTI0_IRQn},
  144.     {P_1,EXTI1_IRQn},
  145.     {P_2,EXTI2_IRQn},
  146.     {P_3,EXTI3_IRQn},
  147.     {P_4,EXTI4_IRQn},
  148.     {P_5,EXTI9_5_IRQn},
  149.     {P_6,EXTI9_5_IRQn},
  150.     {P_7,EXTI9_5_IRQn},
  151.     {P_8,EXTI9_5_IRQn},
  152.     {P_9,EXTI9_5_IRQn},
  153.     {P_10,EXTI15_10_IRQn},
  154.     {P_11,EXTI15_10_IRQn},
  155.     {P_12,EXTI15_10_IRQn},
  156.     {P_13,EXTI15_10_IRQn},
  157.     {P_14,EXTI15_10_IRQn},
  158.     {P_15,EXTI15_10_IRQn},
  159. };


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


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

  167. #define GPIO_MAPPING_PORTSN(Name)        (u8)(PIN_PORT(Name))
  168. #define GPIO_MAPPING_PINSN(Name)        (u8)(PIN_SN(Name))

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

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

  174. #endif //_HAL_GPIO_H_

 楼主| 纠结的那些年 发表于 2023-8-26 17:55 | 显示全部楼层
下面这段为示例程序。
演示程序可以看出,利用PA_0、PB_8这样的方式定义引脚,可以方便的做到复杂的映射关系。
在bool key_IsPressed(PinName_t pin)函数中也可以采用PinName_t类型传递引脚。
 楼主| 纠结的那些年 发表于 2023-8-26 17:55 | 显示全部楼层
是不是挺方便呢?


  1. #define App_LedOpen(x)      GPIO_LOW(x)
  2. #define App_LedClose(x)     GPIO_HI(x)

  3. #define APP_KEY_ON      0
  4. #define APP_KEY_OFF     1

  5. #define APP_KEYNAME_0       PA_11
  6. #define APP_KEYNAME_1       PA_12
  7. #define APP_KEYNAME_2       PB_8
  8. #define APP_KEYNAME_3       PB_9
  9. #define APP_KEYNAME_4       PC_6
  10. #define APP_KEYNAME_5       PC_7
  11. #define APP_KEYNAME_6       PC_8
  12. #define APP_KEYNAME_7       PC_9


  13. #define APP_LEDNAME_0       PB_12
  14. #define APP_LEDNAME_1       PB_13
  15. #define APP_LEDNAME_2       PB_14
  16. #define APP_LEDNAME_3       PB_15
  17. #define APP_LEDNAME_4       PC_10
  18. #define APP_LEDNAME_5       PC_11
  19. #define APP_LEDNAME_6       PC_12
  20. #define APP_LEDNAME_7       PB_7
  21.                            

  22. typedef struct AppKeyLedMap
  23. {
  24.     PinName_t   keyName;
  25.     PinName_t   LedName;
  26.     bool        flag;
  27. }AppKeyLedMap_t;


  28. static AppKeyLedMap_t gAppKeyLedMap[] =
  29. {
  30.     {APP_KEYNAME_0,APP_LEDNAME_0,0},
  31.     {APP_KEYNAME_1,APP_LEDNAME_1,0},
  32.     {APP_KEYNAME_2,APP_LEDNAME_2,0},
  33.     {APP_KEYNAME_3,APP_LEDNAME_3,0},
  34.     {APP_KEYNAME_4,APP_LEDNAME_4,0},
  35.     {APP_KEYNAME_5,APP_LEDNAME_5,0},
  36.     {APP_KEYNAME_6,APP_LEDNAME_6,0},
  37.     {APP_KEYNAME_7,APP_LEDNAME_7,0}
  38. };


  39. bool key_IsPressed(PinName_t pin)
  40. {
  41.     u8 checkTimes = 2;
  42.     if(GPIO_READ(pin) == APP_KEY_ON)
  43.     {
  44.         DelayMs(20);
  45.         if(GPIO_READ(pin) == APP_KEY_ON)
  46.         {
  47.             while(GPIO_READ(pin) == APP_KEY_ON);
  48.             return  true;
  49.         }
  50.     }
  51.     return false;
  52. }



  53. int main()
  54. {
  55.     u8 v = 0;
  56.     u8 last_v = 0;
  57.     i16 i,j;
  58.      
  59.     CLOCK_Config();   
  60.     GPIO_Config();
  61.     LOG_Config();
  62.    
  63.     for(i = 0;i<8;i++)
  64.     {
  65.         App_LedClose(gAppKeyLedMap[i].LedName);
  66.     }
  67.     DelayMs(500);
  68.     for(i = 0;i<8;i++)
  69.     {
  70.         App_LedOpen(gAppKeyLedMap[i].LedName);
  71.     }
  72.         ..............
  73. }
 楼主| 纠结的那些年 发表于 2023-8-26 17:55 | 显示全部楼层
演示程序下载:
https://download.csdn.net/download/b_xjie/11790619
做了一排8位按键,对应8个LED。按键控制8个LED对应字节的8位。灯亮代码该位为1,否则该位为0,将此字节及位输出至OLED。
KEIL工程目录及代码结构可以利用。
houcs 发表于 2023-8-26 23:11 | 显示全部楼层
可以方便的做到复杂的映射关系
Clyde011 发表于 2024-9-11 07:32 | 显示全部楼层

首先是进行按比例和具体的施胶量进行混合操作
公羊子丹 发表于 2024-9-11 08:25 | 显示全部楼层

将在原边形成电压尖峰,
万图 发表于 2024-9-11 09:28 | 显示全部楼层

使该元器件不超过正常值范围
帛灿灿 发表于 2024-9-11 12:27 | 显示全部楼层

ESD静电保护器工作特性与TVS管一致。
Bblythe 发表于 2024-9-11 13:30 | 显示全部楼层

环氧树脂、聚胺脂、有机硅灌封胶
周半梅 发表于 2024-9-11 15:26 | 显示全部楼层

保护被保护IC或线路
Pulitzer 发表于 2024-9-11 16:29 | 显示全部楼层

电源模块的灌封用的胶是可以根据需求而调制的
童雨竹 发表于 2024-9-11 18:25 | 显示全部楼层

所以不会通过地损耗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

56

主题

751

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部