
/* stdperiph_gpio.h */ /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx.h" /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STDPERIPH_GPIO_H #define __STDPERIPH_GPIO_H extern void StdPeriph_GPIO_Config(void); extern void StdPeriph_GPIO_Driver(void); union OutPort { uint8_t all; struct { uint8_t b0:1; // 0 bit0 uint8_t b1:1; // 1 bit1 uint8_t b2:1; // 2 bit2 uint8_t b3:1; // 3 bit3 uint8_t b4:1; // 4 bit4 uint8_t b5:1; // 5 bit5 uint8_t b6:1; // 6 bit6 uint8_t b7:1; // 7 bit7 }bit; }; extern __IO union OutPort Q1; #endif /* stdperiph_gpio.c */ /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_rcc.h" struct BITS { uint16_t GPIO0:1; // 0 GPIO0 uint16_t GPIO1:1; // 1 GPIO1 uint16_t GPIO2:1; // 2 GPIO2 uint16_t GPIO3:1; // 3 GPIO3 uint16_t GPIO4:1; // 4 GPIO4 uint16_t GPIO5:1; // 5 GPIO5 uint16_t GPIO6:1; // 6 GPIO6 uint16_t GPIO7:1; // 7 GPIO7 uint16_t GPIO8:1; // 8 GPIO8 uint16_t GPIO9:1; // 9 GPIO9 uint16_t GPIO10:1; // 10 GPIO10 uint16_t GPIO11:1; // 11 GPIO11 uint16_t GPIO12:1; // 12 GPIO12 uint16_t GPIO13:1; // 13 GPIO13 uint16_t GPIO14:1; // 14 GPIO14 uint16_t GPIO15:1; // 15 GPIO15 }; union BSRL_REG { uint16_t all; struct BITS bit; }; union BSRH_REG { uint16_t all; struct BITS bit; }; __IO union BSRL_REG GPIOE_BSRL_Shadow; __IO union BSRH_REG GPIOE_BSRH_Shadow; union OutPort { uint8_t all; struct { uint8_t b0:1; // 0 bit0 uint8_t b1:1; // 1 bit1 uint8_t b2:1; // 2 bit2 uint8_t b3:1; // 3 bit3 uint8_t b4:1; // 4 bit4 uint8_t b5:1; // 5 bit5 uint8_t b6:1; // 6 bit6 uint8_t b7:1; // 7 bit7 }bit; }; __IO union OutPort Q1; void StdPeriph_GPIO_Driver(void) { /* 1: 打开MOSFET 0: 关闭MOSFET */ GPIOE_BSRL_Shadow.all = 0; GPIOE_BSRH_Shadow.all = 0; if(Q1.bit.b0 == 0){ GPIOE_BSRH_Shadow.bit.GPIO0 = 1; } else { GPIOE_BSRL_Shadow.bit.GPIO0 = 1; } if(Q1.bit.b1 == 0){ GPIOE_BSRH_Shadow.bit.GPIO1 = 1; } else { GPIOE_BSRL_Shadow.bit.GPIO1 = 1; } if(Q1.bit.b2 == 0){ GPIOE_BSRH_Shadow.bit.GPIO2 = 1; } else { GPIOE_BSRL_Shadow.bit.GPIO2 = 1; } if(Q1.bit.b3 == 0){ GPIOE_BSRH_Shadow.bit.GPIO3 = 1; } else { GPIOE_BSRL_Shadow.bit.GPIO3 = 1; } if(Q1.bit.b4 == 0){ GPIOE_BSRH_Shadow.bit.GPIO4 = 1; } else { GPIOE_BSRL_Shadow.bit.GPIO4 = 1; } if(Q1.bit.b5 == 0){ GPIOE_BSRH_Shadow.bit.GPIO5 = 1; } else { GPIOE_BSRL_Shadow.bit.GPIO5 = 1; } if(Q1.bit.b6 == 0){ GPIOE_BSRH_Shadow.bit.GPIO6 = 1; } else { GPIOE_BSRL_Shadow.bit.GPIO6 = 1; } if(Q1.bit.b7 == 0){ GPIOE_BSRH_Shadow.bit.GPIO7 = 1; } else { GPIOE_BSRL_Shadow.bit.GPIO7 = 1; } GPIOE->BSRRL = GPIOE_BSRL_Shadow.all; GPIOE->BSRRH = GPIOE_BSRH_Shadow.all; } |
注意事项:
1. 可以在主程序或定时程序中调用StdPeriph_GPIO_Driver函数,刷新GPIOE.0~GPIOE.7的状态。
2. 在应用程序中,只需访问Q1的位即可。例如下一句
"Q1.bit.b0 = 1;"就可以修改GPIOE.0的状态为高电平;同样地,"Q1.bit.b0 = 0;"可以修改GPIOE.0的状态为低电平。
StdPeriph_GPIO_Driver函数调用的频率,建议在1~10ms,满足要求的即可。
在MDK-ARM V5.15开发环境,键入"Q1."则会出现自动提示,Q1.all 是访问所有的位, Q1.bit.b7是访问最高位。
补充说明:
1. 驱动编程的目的和出发点在于,仅在一个地方调用StdPeriph_GPIO_Driver函数,
用户层只操作Q1输出端口的8个位,8位变量Q1是函数对应用层提供的接口。
2.宏定义的作用
宏定义直接操作GPIO,可以立即刷新GPIO的输出状态。
例如在SPI通信中函数中,代码开头使CS片选脚变低,代码结尾使CS片选变高。
但宏定义不能给用户提供一个统一的中间变量。
假设有二个输出端口Q1、Q2,每个端口均是8路输出,分别安排在任意的GPIOA-GPIOE,
可以设置16个宏定义,将这16路输出端口设置为高,另外再设置16个宏定义,
分别将这16个输出端口设置为低。显然,这种写法将对GPIO的操作复杂化了。
宏定义保证了效率,但对于应用层而言,不利于用户的使用和记忆。