
/* stdperiph_gpio.h *// @" }" l5 y' d0 w& w 1 y0 a; C+ o' h5 k" ]9 |; Z# }- e /* Includes ------------------------------------------------------------------*/' V4 }0 `2 M+ T2 u2 B/ _; d% v #include "stm32f4xx.h"/ `# G; B! A3 Q/ g6 ]5 } /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STDPERIPH_GPIO_H M% E) ]) q g8 _ U5 C #define __STDPERIPH_GPIO_H extern void StdPeriph_GPIO_Config(void);% Y, Y' B2 K* S# J& i T. O extern void StdPeriph_GPIO_Driver(void);% w1 T; u8 Q) m; ?8 Y/ i% n* v' C; S union OutPort {0 m2 l$ B, R# N2 N7 p. V uint8_t all; struct { uint8_t b0:1; // 0 bit0 uint8_t b1:1; // 1 bit1 uint8_t b2:1; // 2 bit2, m- e9 T- ]2 I9 } uint8_t b3:1; // 3 bit3 uint8_t b4:1; // 4 bit42 E9 K n% u9 ~; ~/ `; P$ E4 S uint8_t b5:1; // 5 bit5' X5 @. d: t. [6 l+ f9 \$ x9 Z( Q uint8_t b6:1; // 6 bit6 uint8_t b7:1; // 7 bit7 & I4 w! | `# Z; _5 \/ ~0 L }bit; }; extern __IO union OutPort Q1;- T0 @( U2 @4 y, D" A% c ?" e& U ) c/ z8 i$ y( ^% D- {* ^; m, g) H" B #endif " g+ I6 K( m* \. _+ T2 N8 `: N /* stdperiph_gpio.c */* U* S& \# z8 a) F, z; N' p /* Includes ------------------------------------------------------------------*/! ]" Q( K6 Z, G& ?, \8 P) \ #include "stm32f4xx.h" #include "stm32f4xx_gpio.h") r. C# K! S2 G* ^( P #include "stm32f4xx_rcc.h" struct BITS { uint16_t GPIO0:1; // 0 GPIO0 uint16_t GPIO1:1; // 1 GPIO16 @8 L; d: Q1 U1 X+ ` uint16_t GPIO2:1; // 2 GPIO2) e6 M( m0 Q( I2 {9 L uint16_t GPIO3:1; // 3 GPIO3 uint16_t GPIO4:1; // 4 GPIO4 uint16_t GPIO5:1; // 5 GPIO5. L# T# z( s6 v0 @ uint16_t GPIO6:1; // 6 GPIO6; M1 c: h# Y' i; g9 C! J 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) f8 W) g- E5 t5 e( z uint16_t GPIO12:1; // 12 GPIO120 N3 `" i9 ~8 o2 p( E' ]' O uint16_t GPIO13:1; // 13 GPIO136 n+ P! s- T+ N8 \3 R uint16_t GPIO14:1; // 14 GPIO14 uint16_t GPIO15:1; // 15 GPIO15 }; 8 M) J& m8 W: ~; r5 e0 t( B5 ` union BSRL_REG { uint16_t all; struct BITS bit; }; union BSRH_REG { uint16_t all; struct BITS bit;7 U. V) O2 \, e$ D+ n6 M) b }; __IO union BSRL_REG GPIOE_BSRL_Shadow;+ T- i5 J Q: b3 C/ C4 I4 D __IO union BSRH_REG GPIOE_BSRH_Shadow;$ ?4 U5 P( [2 U) |# c$ b * K. O& @ d& s ) ~5 u+ l: K0 K3 L+ m% f8 u union OutPort {6 G1 f z" x7 b6 R i uint8_t all;4 K# S2 ]) R9 n struct { uint8_t b0:1; // 0 bit0 uint8_t b1:1; // 1 bit1 uint8_t b2:1; // 2 bit27 G- `. J( [8 v" v- X0 S uint8_t b3:1; // 3 bit3 uint8_t b4:1; // 4 bit4# {' q# h- j5 J8 F: @! F uint8_t b5:1; // 5 bit5- m1 X! y7 v" o# q6 J" }# ]( B uint8_t b6:1; // 6 bit68 E3 o- q& u8 e7 o7 p" r uint8_t b7:1; // 7 bit7 }bit; };' @. z4 ^# m6 ]2 Q) ?) D " ~! T! J, X9 E' D" E& A6 D __IO union OutPort Q1;6 f6 C# \; w+ J" e/ L void StdPeriph_GPIO_Driver(void) {6 G6 n) K0 |+ N& B/ n /* 1: 打开MOSFET 0: 关闭MOSFET */, V. G x4 u8 f# Y# Y$ o# ~( B GPIOE_BSRL_Shadow.all = 0; GPIOE_BSRH_Shadow.all = 0; if(Q1.bit.b0 == 0){ GPIOE_BSRH_Shadow.bit.GPIO0 = 1; } else {3 F' H4 F8 o4 x& A; T- H' c GPIOE_BSRL_Shadow.bit.GPIO0 = 1; }" d* |* C, p& z" B/ ^ if(Q1.bit.b1 == 0){ GPIOE_BSRH_Shadow.bit.GPIO1 = 1; } else { GPIOE_BSRL_Shadow.bit.GPIO1 = 1;1 i3 c; A Z. ?, _/ c } if(Q1.bit.b2 == 0){" |; ^4 d5 V/ p H/ l GPIOE_BSRH_Shadow.bit.GPIO2 = 1;: y( Y+ Y4 Y% r6 h } else {/ E; p4 g, |& @- O GPIOE_BSRL_Shadow.bit.GPIO2 = 1; }5 M) ?, ?* r$ Z' B/ H& Q& ^ if(Q1.bit.b3 == 0){ GPIOE_BSRH_Shadow.bit.GPIO3 = 1; } else {8 }4 G+ s3 ?/ s Z- L3 e GPIOE_BSRL_Shadow.bit.GPIO3 = 1;% y: v9 u. D$ g }: x: u* [9 Q% u6 G if(Q1.bit.b4 == 0){9 C. b9 m8 r' R2 e, t. t( c1 D GPIOE_BSRH_Shadow.bit.GPIO4 = 1; } else {. a2 w! ]6 z. z3 \. H, R GPIOE_BSRL_Shadow.bit.GPIO4 = 1;& u+ A' ~ q# ^ ?% n M. p }. ^: w. Z, @3 d if(Q1.bit.b5 == 0){ GPIOE_BSRH_Shadow.bit.GPIO5 = 1; } else { GPIOE_BSRL_Shadow.bit.GPIO5 = 1;$ I R# o* C: C; x* b5 `& w }2 a7 [/ s* j0 m% ^: H! ? if(Q1.bit.b6 == 0){8 R. S) _5 k& j; E9 d7 M% b GPIOE_BSRH_Shadow.bit.GPIO6 = 1;) A+ x( u/ q2 V( p7 f' e% k, z } else {+ A* _2 M, J" p( q( P$ r* K GPIOE_BSRL_Shadow.bit.GPIO6 = 1; }. X% x* d3 G- c1 m3 B8 f2 T if(Q1.bit.b7 == 0){ GPIOE_BSRH_Shadow.bit.GPIO7 = 1;3 u0 s- K, t; m$ V7 z4 C } else {4 I4 D0 z0 a7 `; u0 d5 B GPIOE_BSRL_Shadow.bit.GPIO7 = 1; } GPIOE->BSRRL = GPIOE_BSRL_Shadow.all;+ u: i5 u5 c5 c, i GPIOE->BSRRH = GPIOE_BSRH_Shadow.all; } p3 D& P: t" L& g& c- }( d & i+ p" p8 z& [8 k. h + \$ f: m% a& h6 }( Y6 o' G. }& M- S |
注意事项:6 p `7 A! ]/ ]
1. 可以在主程序或定时程序中调用StdPeriph_GPIO_Driver函数,刷新GPIOE.0~GPIOE.7的状态。
2. 在应用程序中,只需访问Q1的位即可。例如下一句
"Q1.bit.b0 = 1;"就可以修改GPIOE.0的状态为高电平;同样地,"Q1.bit.b0 = 0;"可以修改GPIOE.0的状态为低电平。4 d: S ]7 S3 w2 A8 b5 U
StdPeriph_GPIO_Driver函数调用的频率,建议在1~10ms,满足要求的即可。) q' @! D1 k* ^% e; V* I$ y
在MDK-ARM V5.15开发环境,键入"Q1."则会出现自动提示,Q1.all 是访问所有的位, Q1.bit.b7是访问最高位。
补充说明:
1. 驱动编程的目的和出发点在于,仅在一个地方调用StdPeriph_GPIO_Driver函数,
用户层只操作Q1输出端口的8个位,8位变量Q1是函数对应用层提供的接口。
9 d+ f7 q5 `' I2 Q4 ^
2.宏定义的作用
宏定义直接操作GPIO,可以立即刷新GPIO的输出状态。
例如在SPI通信中函数中,代码开头使CS片选脚变低,代码结尾使CS片选变高。
: t8 F- f& u, g1 N, W3 o! C
但宏定义不能给用户提供一个统一的中间变量。; @8 K* O% Q+ a; V
假设有二个输出端口Q1、Q2,每个端口均是8路输出,分别安排在任意的GPIOA-GPIOE,6 x6 x9 q, S" g3 m
可以设置16个宏定义,将这16路输出端口设置为高,另外再设置16个宏定义,
分别将这16个输出端口设置为低。显然,这种写法将对GPIO的操作复杂化了。
宏定义保证了效率,但对于应用层而言,不利于用户的使用和记忆。
* ]7 y( `$ r5 m: a' p
! ~( T+ k! G! E e, h) ?
" j& x% V' s+ O$ y: \0 g