STM32F0xx的IO口定义方式与STM32F10x类似,一组GPIO包含16个IO。每组GPIO同样用GPIO_TypeDef的结构指向对应的寄存器空间。
: x$ u' Y& w# @/ E
9 y9 q1 X7 {) q: W- <blockquote>#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
复制代码 % }1 O B/ v2 w7 D3 f( j" e1 c
但是寄存器空间与STM32F10x的不同。8 h/ \2 v- E* D& Z
- <blockquote>typedef struct
复制代码
8 ]- }( f! o" j! S. U0 s' G1. 使能GPIO的RCC' g( F% d/ N: l! @! v3 } U
RCC->AHBENR |= RCC_AHBPeriph_GPIOn V4 C9 D, \- d1 ~2 f" x7 [+ O
7 l3 Q. E8 O3 @ V5 |8 ]# ^2 y其中n的范围为A-F。
# c% a9 l: L$ ]/ y3 ?0 Y& c
' m: E+ Q8 b' w% N) f. L8 I; p如果涉及到复用,与STM32F10x不同,这里用寄存器AFR[2]来设定复用。每个IO用4bit来选择复用功能,最多有8种复用。, J ]" W$ F! I( Z
( |8 k. c6 s/ s( u
9 e/ }/ l' V2 s( {: W例如GPIOA9,GPIOA10的AFR设定:2 b, H+ W2 p' [3 n d3 \
$ c7 V8 x! H- l6 e4 H! k' R
- *((uint32_t *)GPIOA->AFR + ((9 / 8))) &= ~(0x0000000F << ((9 % 8) * 4)); O' K0 e2 s- H5 b
- *((uint32_t *)GPIOA->AFR + ((9 / 8))) |= (0x00000001 << ((9 % 8) * 4));
; r' d3 i4 F3 b2 V2 |( x- W' c C% |2 K - *((uint32_t *)GPIOA->AFR + ((10 / 8))) &= ~(0x0000000F << ((10 % 8) * 4));# A) f8 P1 J9 M! C# A. t2 H% v
- *((uint32_t *)GPIOA->AFR + ((10 / 8))) |= (0x00000001 << ((10 % 8) * 4));
复制代码
9 ^9 A9 j% \/ f/ ^( n& T6 U% a! e! V2. 配置GPIO
, ?) ^6 R7 H1 ]3 k6 ?5 k2.1 设置输出频率(OSPEEDR)
$ ?. S3 X3 I- r. l
; s" |% m, ~! m& M: d( I( k- P' q0 j, a) h# j
5 S5 @; M1 ^6 m每2个位配置一个Pin。默认是2MHz。& a9 H3 |, O+ U, U [, K6 Y! N' S
7 a* m* B( _% i
0b00, 0b10: 2MHz
4 k$ [: N* [' I% {
/ Q3 A" I( Y# j0b10: 10MHz$ v1 A% [( A1 C' S3 S
+ h j9 x- b9 F5 i$ t6 Q
0b11: 50MHz
& \+ g, K# {% e! v" h3 t o! i! t# Z/ S) `4 @* B
- typedef enum* g) C- s" B) |) P. ^+ C% G5 n
- {6 ^! j( m6 H5 C2 e; [" n, b
- GPIO_Speed_Level_1 = 0x00, /*!< I/O output speed: Low 2 MHz */5 E5 R4 e/ a3 y+ R$ m: R9 b
- GPIO_Speed_Level_2 = 0x01, /*!< I/O output speed: Medium 10 MHz */' a4 S; H) R; P9 S$ F
- GPIO_Speed_Level_3 = 0x03 /*!< I/O output speed: High 50 MHz */. j! Y# Q4 k# }/ X2 c
- }GPIOSpeed_TypeDef;3 v+ L* i8 G' v% m3 r# q
" x( l$ _ l) @7 v: x% |' ?. n. D- #define GPIO_Speed_2MHz GPIO_Speed_Level_1 /*!< I/O output speed: Low 2 MHz */
9 p1 y8 q6 X* X, ?: T6 h8 B - #define GPIO_Speed_10MHz GPIO_Speed_Level_2 /*!< I/O output speed: Medium 10 MHz */
! t* D- l: _" V/ v' |) h+ M - #define GPIO_Speed_50MHz GPIO_Speed_Level_3 /*!< I/O output speed: High 50 MHz */
复制代码 . j8 ~2 U3 h% C v7 l+ U. I
例如A9、A10都为50MHz: c. l. g3 x% h9 J5 o% N1 R& l' _
9 U+ o; x2 Q G0 i4 Q/ [- GPIOA->OSPEEDR |= (0x0000000F << (9 * 2));
复制代码
8 _0 F* }/ a" o# {' H2.2 配置输入输出(MODER)
+ _- c3 H8 A+ h( T5 G$ g/ F& h# f( H* c
+ ^& f* m# F) s4 u& Q
$ E% s( Z; t8 A1 @每2个位配置一个Pin。 默认Input(除了SWD的A13,A14)
1 h. O# f" s' w; q8 W8 _" r3 ~$ X4 H" R C5 E
0b00: Input# }2 K% a, ~/ r
) {" z. k: b1 d
0b01: Output
: _5 n' I) O/ t+ H% Y
! U& n2 v/ z0 r$ Q" m& ^0b10: AF
' T& L/ f+ B$ T2 g) W3 k
! u& T9 n. e. N, E; @0 u0b11: Analog In/Out, M5 Q" @5 `7 B' u0 Q) b# p
0 r/ C7 B# b+ M! T1 `
- typedef enum
, _* h% K( ^5 K - {) J9 H7 A% E8 u' W' k, x
- GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */
+ \3 d* u4 Q2 |1 x - GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */
0 R; a- M9 G, o - GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */
& Q4 Q8 \ _, X! E6 ~ - GPIO_Mode_AN = 0x03 /*!< GPIO Analog In/Out Mode */$ k6 |3 Z+ C6 M' i3 W+ o
- }GPIOMode_TypeDef;
复制代码
( q# U. u5 l/ v例如GPIOA9,GPIOA10为AF:" y8 p* k0 g2 d# G% ]
- GPIOA->MODER |= ((uint32_t)GPIO_Mode_AF << (9 * 2)) | ((uint32_t)GPIO_Mode_AF << (10 * 2));
复制代码 % ]2 n1 N8 ~+ Y2 P7 E, h
2.3 配置输出模式(OTYPER)2 ^5 U3 p9 }0 Z8 h4 _) C8 R; |: B
; n) V6 ]. g/ d0 s5 X
6 a+ M+ r7 ~) o6 F) n& F9 V5 R8 |" }$ M/ ^0 T7 A
每个bit表示输出模式," @3 g4 v r% D0 O+ p8 L( l
( l/ u+ V% P0 K2 b
0b0: PP模式;
' Z# T8 n% [) ~+ n$ ~
& c5 k: `8 ?8 E' i0b1: OD模式。 2 y6 y, _" V% b+ n
0 i; b$ [+ n) O7 P7 {
- typedef enum
3 y/ I$ v) p: w. m+ T - {
, f1 R# \( m7 ]3 J. r5 ^ - GPIO_OType_PP = 0x00,/ }- _, }0 n- ]1 t
- GPIO_OType_OD = 0x019 P5 U) C; S8 O
- }GPIOOType_TypeDef;
复制代码 % A+ [, ~( [' i" I( K/ ^8 P
例如:
! |; t9 j3 M* L) B5 l- GPIOA->OTYPER |= (((uint32_t)GPIO_OType_PP << (9 * 1)) 4 h: @4 C' b) q9 T) r. C
- | ((uint32_t)GPIO_OType_PP << 10 * 1))
复制代码 0 g8 T* |% D/ O2 W, f n/ q
2.4 配置上下拉模式(PUPDR)
8 d2 J+ w# u- Y! L% Y8 D$ {
- }6 J+ |* r1 w5 x3 L7 @5 [ t1 W% z7 f5 W A2 `
/ p( y3 Y& G" r) D3 L每2个位表示上下拉模式。
4 _$ _5 e8 x. e+ H2 t Q* V6 o- typedef enum
k S* N/ Q2 P% |2 b - {
9 N* c: f- B9 Y$ Q' u - GPIO_PuPd_NOPULL = 0x00,
; P7 o# t, g3 u8 N/ `# w/ {3 `; [ - GPIO_PuPd_UP = 0x01,9 ]# J1 A2 `4 S: C2 t( |, e
- GPIO_PuPd_DOWN = 0x029 S j. r- k4 E
- }GPIOPuPd_TypeDef;
复制代码
/ A/ X- t/ O2 V y. ?; q例如:
5 C" P* Q% b2 |, T$ w E- GPIOA->PUPDR &= ~((0x00000003 << (9 * 2)) | (0x00000003 << (10 * 2)));
复制代码 7 C8 L j- J/ }- B7 Q
3. 输出
7 l% t j/ I/ a2 B$ y5 f输出电平通过寄存器BSRR(输出高电平和低电平)和BRR(输出低电平)实现,写入1表示对应操作,写入0无效。例如:
# {" E- T: B9 [5 H! u2 J! i+ i. A( ?% t* j6 ^3 O
- #define SDA_HIGH(n) IO_I2CIO_SDA->BSRR = ((uint32_t)1 << PIN_I2CIO_SDA) , {9 B; @2 n: ~5 d+ C7 X
- #define SDA_LOW(n) IO_I2CIO_SDA->BRR = ((uint32_t)1 << PIN_I2CIO_SDA)
复制代码
, \" v0 _1 w& ]- a9 B5 a+ [) V! i BSRR的低16位分别对应16个PIN的输出高电平操作,高16为对应输出低电平操作。5 F; a1 h! m& n+ A$ s( T
: @( w- g" C* T
而BRR只有低16位有效,对应对应输出低电平操作。5 K; o) ^# [$ q" N' Q$ ]
% F1 F& M/ d- B3 [. p1 O2 Q8bit总线输出
2 \: d% n6 ]3 Z/ O7 Q0 |9 i# O2 {6 R* ]
- #define I8080_D8_OUT(dat) IO_I8080_D8->BSRR = (dat & 0xff) | ((uint32)((~dat) & 0xff) << 16)
复制代码 4. 读入IO
% n, H9 {# Z- O6 `6 e3 Y通过寄存器IDR读出对应I/O口的状态。低16位有效。
' u' J' C Q! d* I9 S7 p3 b' e3 ~ c9 q: B" |
- #define SDA_READ(n) (IO_I2CIO_SDA->IDR & ((uint32_t)1 << PIN_I2CIO_SDA))
复制代码 % k% ^9 y+ D7 `4 W3 F
7 x/ o% i# h3 s U6 P3 S* t
! n# n! d$ |7 P8 {6 E/ i |