
/* stdperiph_gpio.h */' B" h0 S9 }; M0 p- D; x /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx.h" /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STDPERIPH_GPIO_H* E# v. g1 a6 D #define __STDPERIPH_GPIO_H 6 {- W& n0 l1 @; t; [ extern void StdPeriph_GPIO_Config(void); extern void StdPeriph_GPIO_Driver(void); ( ]$ `. G6 N1 x. } union OutPort { uint8_t all; struct { uint8_t b0:1; // 0 bit0 uint8_t b1:1; // 1 bit10 \; u2 [: U2 m4 l4 G0 l2 d 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 / ` n o4 B7 Z) Z3 R& e" } }bit;# F. M# m- V" C9 E0 q4 H8 } };- {+ s* S I% W' |2 n0 h - D& o& q' w! j& G, | extern __IO union OutPort Q1;6 T' x0 ]8 h* g5 b+ [( Q5 D 8 G$ Y1 Z* R8 @5 k- J #endif ( ~( t) D5 j' w) E /* stdperiph_gpio.c */ /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx.h"5 H, @4 e- [6 o' Q( h% w/ u #include "stm32f4xx_gpio.h" #include "stm32f4xx_rcc.h"+ h! q4 M' }) h7 P- O) e, x struct BITS { uint16_t GPIO0:1; // 0 GPIO07 t, L& B5 E, B' e: u# [+ U uint16_t GPIO1:1; // 1 GPIO1 uint16_t GPIO2:1; // 2 GPIO21 a+ Y% P5 I' ~ uint16_t GPIO3:1; // 3 GPIO3$ X' _% Q+ B; y* g" m* a uint16_t GPIO4:1; // 4 GPIO4/ j6 ^9 `; E8 D+ R4 m3 M! g* q% @ uint16_t GPIO5:1; // 5 GPIO51 E6 T1 i3 f4 R+ M% J uint16_t GPIO6:1; // 6 GPIO6 uint16_t GPIO7:1; // 7 GPIO7 uint16_t GPIO8:1; // 8 GPIO8: c4 `: ]( E6 L" }* }8 D uint16_t GPIO9:1; // 9 GPIO9! s$ i- U' q9 m& ~1 N: T uint16_t GPIO10:1; // 10 GPIO10 uint16_t GPIO11:1; // 11 GPIO11 uint16_t GPIO12:1; // 12 GPIO12# J6 @2 L: G6 ?4 ^( T uint16_t GPIO13:1; // 13 GPIO13% T6 ^! F u! c* T! O6 d uint16_t GPIO14:1; // 14 GPIO14* }, g0 m7 D& S4 h7 D6 P2 d" h uint16_t GPIO15:1; // 15 GPIO15 }; ' S6 x! J( o$ K- R4 w union BSRL_REG {3 m6 q- T$ J7 ]- t3 S uint16_t all; struct BITS bit; };# W" h2 N/ H0 y* Q8 ?0 \ " ]. M3 S9 g% V union BSRH_REG {1 Z6 H3 p$ e. u x' P) Y uint16_t all;8 d# G% b h/ K# m* @ struct BITS bit;- i) q8 o+ `! d. l }; 2 @0 f+ w$ E1 ]( I: I* C( N __IO union BSRL_REG GPIOE_BSRL_Shadow;7 i; N" r/ t9 o6 E) l6 i4 P __IO union BSRH_REG GPIOE_BSRH_Shadow; 8 ^. U8 s& N( L) y: Z) f4 Z) d+ H/ o union OutPort {4 ^6 m( d2 @$ D. M7 k: d2 f4 \! F' Y uint8_t all; struct { uint8_t b0:1; // 0 bit0 uint8_t b1:1; // 1 bit1- n. |- T) n# c; w uint8_t b2:1; // 2 bit2( f4 `* G# Z* t' V8 O" u- o uint8_t b3:1; // 3 bit3 uint8_t b4:1; // 4 bit41 o( u6 O) G0 K. d6 V1 H, ] uint8_t b5:1; // 5 bit5 uint8_t b6:1; // 6 bit6 uint8_t b7:1; // 7 bit7 3 u4 C" Q; N+ Q! n }bit;' k$ y% O7 _' G' f$ m }; / r9 ]5 W* ]- s7 V% G __IO union OutPort Q1; void StdPeriph_GPIO_Driver(void). B2 O! J' A' e5 d" s' U* G; R { /* 1: 打开MOSFET 0: 关闭MOSFET */ GPIOE_BSRL_Shadow.all = 0;) u( L" T7 }0 Z) l; K GPIOE_BSRH_Shadow.all = 0;6 j) }6 M& i+ n! c if(Q1.bit.b0 == 0){ GPIOE_BSRH_Shadow.bit.GPIO0 = 1; } else { GPIOE_BSRL_Shadow.bit.GPIO0 = 1; }2 H( s- k# i( c1 j if(Q1.bit.b1 == 0){ GPIOE_BSRH_Shadow.bit.GPIO1 = 1; } else {) a4 D6 ^5 V: v& T GPIOE_BSRL_Shadow.bit.GPIO1 = 1;) Y1 I4 l, H7 Y; r( A* o% M }! Y# N/ {( M8 g0 Q, x, N4 U if(Q1.bit.b2 == 0){ GPIOE_BSRH_Shadow.bit.GPIO2 = 1;& h" p0 H# W5 I/ U } else { GPIOE_BSRL_Shadow.bit.GPIO2 = 1;8 f" e- c: V, r1 T6 ] }8 T+ m+ n7 i0 A; o2 e if(Q1.bit.b3 == 0){ GPIOE_BSRH_Shadow.bit.GPIO3 = 1;2 d5 U. H- H& V } else { GPIOE_BSRL_Shadow.bit.GPIO3 = 1; } if(Q1.bit.b4 == 0){ GPIOE_BSRH_Shadow.bit.GPIO4 = 1; } else {- N+ j; D$ R$ W7 ] GPIOE_BSRL_Shadow.bit.GPIO4 = 1;0 `; _4 X* \9 C4 @2 C+ M4 Q$ f } if(Q1.bit.b5 == 0){: x, h! L+ C9 M# F GPIOE_BSRH_Shadow.bit.GPIO5 = 1; } else { GPIOE_BSRL_Shadow.bit.GPIO5 = 1;6 p( D" M& P% L) M% C }9 y7 c% n* G+ G0 X if(Q1.bit.b6 == 0){+ Y- d: ? U5 d GPIOE_BSRH_Shadow.bit.GPIO6 = 1;" w5 a* y% g5 J9 x } else { GPIOE_BSRL_Shadow.bit.GPIO6 = 1;) V5 \: R2 B6 B D$ `" p0 p) } }+ {5 M2 N- O; R, H Z if(Q1.bit.b7 == 0){ h; d& q4 t; e& z. X ~) n9 f GPIOE_BSRH_Shadow.bit.GPIO7 = 1; } else {1 U" @ N' w- R GPIOE_BSRL_Shadow.bit.GPIO7 = 1;/ q( e( S, y+ G. w } GPIOE->BSRRL = GPIOE_BSRL_Shadow.all;' Q7 G6 y; H9 N7 b; M- \ GPIOE->BSRRH = GPIOE_BSRH_Shadow.all;7 } u" X1 r- P0 q, G } + w" b3 H! r8 M ! B: M* Q3 v0 y$ a( D |
注意事项:
1. 可以在主程序或定时程序中调用StdPeriph_GPIO_Driver函数,刷新GPIOE.0~GPIOE.7的状态。
2. 在应用程序中,只需访问Q1的位即可。例如下一句! L4 b: T# I" I, h( |
"Q1.bit.b0 = 1;"就可以修改GPIOE.0的状态为高电平;同样地,"Q1.bit.b0 = 0;"可以修改GPIOE.0的状态为低电平。; V7 C% ~/ w& E7 C
StdPeriph_GPIO_Driver函数调用的频率,建议在1~10ms,满足要求的即可。/ }0 O0 ]$ J7 o: \0 W
在MDK-ARM V5.15开发环境,键入"Q1."则会出现自动提示,Q1.all 是访问所有的位, Q1.bit.b7是访问最高位。 k! P2 O5 l' Q$ t. u) i( R( `4 ]
- H. O* u9 |- U0 H/ H
. r1 ?1 ]: J- O- I3 F
补充说明:
1. 驱动编程的目的和出发点在于,仅在一个地方调用StdPeriph_GPIO_Driver函数,! N. Q& t/ x: R+ @! I8 q
用户层只操作Q1输出端口的8个位,8位变量Q1是函数对应用层提供的接口。
2.宏定义的作用/ l9 D4 Z ^2 |
宏定义直接操作GPIO,可以立即刷新GPIO的输出状态。6 e F$ b1 E! t B% v
例如在SPI通信中函数中,代码开头使CS片选脚变低,代码结尾使CS片选变高。0 X. ?& X0 j6 S8 F6 Q U" I, i6 |
但宏定义不能给用户提供一个统一的中间变量。
假设有二个输出端口Q1、Q2,每个端口均是8路输出,分别安排在任意的GPIOA-GPIOE,: L% k, M3 d: i
可以设置16个宏定义,将这16路输出端口设置为高,另外再设置16个宏定义,
分别将这16个输出端口设置为低。显然,这种写法将对GPIO的操作复杂化了。7 U5 q! o9 K3 A: w3 k! k6 ~# Y% h
宏定义保证了效率,但对于应用层而言,不利于用户的使用和记忆。9 I" |! N. v6 n
# O) d) @( H1 u+ \7 Y