STM32F0xx的IO口定义方式与STM32F10x类似,一组GPIO包含16个IO。每组GPIO同样用GPIO_TypeDef的结构指向对应的寄存器空间。2 J t7 H: T# T* }, F) Z
/ {" a# v) A' n( A# a, t5 ]/ i- <blockquote>#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
复制代码 / D7 v7 G0 D( V# N
但是寄存器空间与STM32F10x的不同。
! Y9 ^$ e0 S; C7 D2 c0 Z5 \- <blockquote>typedef struct
复制代码 5 j( Q4 t! { n& K
1. 使能GPIO的RCC
0 b* ?8 r# \; A1 v9 \RCC->AHBENR |= RCC_AHBPeriph_GPIOn
4 M/ J1 `. d- T1 C/ D
' N \6 E6 p4 R& \0 G其中n的范围为A-F。
+ s$ e* @: z( { K" O3 W0 o* T9 E: k
如果涉及到复用,与STM32F10x不同,这里用寄存器AFR[2]来设定复用。每个IO用4bit来选择复用功能,最多有8种复用。
: E- `* G7 u& k9 v
$ @6 g8 U4 \5 V& C$ e5 o
# }; {' f' N' p! ], {* f& e! x0 k例如GPIOA9,GPIOA10的AFR设定:
" P, N) ^2 ?& w
0 e; _. U9 ^$ C: ]8 Y- *((uint32_t *)GPIOA->AFR + ((9 / 8))) &= ~(0x0000000F << ((9 % 8) * 4));4 f3 M/ \& |4 V* ?% p1 H
- *((uint32_t *)GPIOA->AFR + ((9 / 8))) |= (0x00000001 << ((9 % 8) * 4)); & t# w/ z; @+ `( B, o! P, Y& e
- *((uint32_t *)GPIOA->AFR + ((10 / 8))) &= ~(0x0000000F << ((10 % 8) * 4));0 N/ `( B* a8 ?% Q% I/ K
- *((uint32_t *)GPIOA->AFR + ((10 / 8))) |= (0x00000001 << ((10 % 8) * 4));
复制代码
8 Q B+ S; Z2 U9 X d: H2. 配置GPIO) z6 z8 O; J( e! d
2.1 设置输出频率(OSPEEDR)
W+ z P, e% W u3 `: K8 v6 ]
8 u! K7 m, {. L0 z8 \9 c+ W5 ~' @( J4 F" E) x, B2 ~
2 l7 G _2 A, o6 e( g
每2个位配置一个Pin。默认是2MHz。
% D2 g+ N/ k2 ^! l8 X1 e$ R5 P, v) k- f+ c5 t, {% J; r7 _
0b00, 0b10: 2MHz2 B' ~, c; @6 F. T$ E9 w
2 q1 u3 {! r9 Z1 l0b10: 10MHz& c3 c6 [: W8 F, L' d
+ h* d* Z9 ~- s
0b11: 50MHz
- n7 l7 H Z/ D. m- f8 f" H
# S7 C6 x7 Y6 e( l( }! k. Y1 B- typedef enum
# n8 O+ [3 p7 ], p! z, n - {
/ s+ X, w0 [6 |5 e" Q - GPIO_Speed_Level_1 = 0x00, /*!< I/O output speed: Low 2 MHz */
7 Z2 v* I* s& _5 G8 n - GPIO_Speed_Level_2 = 0x01, /*!< I/O output speed: Medium 10 MHz */
2 \" P5 h3 r. k- ? - GPIO_Speed_Level_3 = 0x03 /*!< I/O output speed: High 50 MHz */
0 ?& c8 Z0 O' C3 P5 G" ] - }GPIOSpeed_TypeDef;/ ?; i$ a3 u! S- p2 _
7 o. V8 {: \. ^7 `% X9 n- #define GPIO_Speed_2MHz GPIO_Speed_Level_1 /*!< I/O output speed: Low 2 MHz */7 B" e/ `9 Z8 p1 ^1 B6 q a7 c
- #define GPIO_Speed_10MHz GPIO_Speed_Level_2 /*!< I/O output speed: Medium 10 MHz */# T k" K5 Y0 l" N$ Z( r. E$ O
- #define GPIO_Speed_50MHz GPIO_Speed_Level_3 /*!< I/O output speed: High 50 MHz */
复制代码 * T, h( J5 s$ ~1 b, T+ W
例如A9、A10都为50MHz: " F, C# n5 U. {+ w/ b P
$ h* |: A q# u/ Y* B3 _- GPIOA->OSPEEDR |= (0x0000000F << (9 * 2));
复制代码 0 V/ v: u$ {, Z S- r6 B
2.2 配置输入输出(MODER)8 O" ` s g* d2 i
7 t6 ~0 I* D w
/ [4 X. Q; [4 f$ m
, [/ N4 _# o/ v- @: u% U* O- q
每2个位配置一个Pin。 默认Input(除了SWD的A13,A14)
_0 _2 z* u2 Q$ D% X w9 D9 Q% _; D* w7 L! v
0b00: Input8 ^+ P5 L) ]# s- S2 u1 Z2 t4 |
0 N' ]. j2 L7 e) p8 |1 K9 V# K% x
0b01: Output2 ~: i0 p D4 n* ]+ K7 B% g* P
& G9 ?! a5 X3 j% l- Y6 b1 S
0b10: AF
7 k& m% F+ T q/ O: Y0 B! b- g# j
0b11: Analog In/Out4 r, f# U9 t& P& {
5 s% L2 y& W, I1 {7 g& _* g
- typedef enum2 E6 x# c: G. B$ O, i D2 b" t+ n
- {' ^5 a1 X+ v$ f* O6 k/ }: l
- GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */ }: n+ J \. M
- GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */9 _ U3 d$ x- c% O) V4 t% U8 o
- GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */
7 E5 k8 u3 N; z+ z9 b - GPIO_Mode_AN = 0x03 /*!< GPIO Analog In/Out Mode */
6 m y! ^+ S+ c$ S2 H - }GPIOMode_TypeDef;
复制代码
# A9 j; Z1 I+ ?7 t例如GPIOA9,GPIOA10为AF:
. {* n- b% G* `; l- |- GPIOA->MODER |= ((uint32_t)GPIO_Mode_AF << (9 * 2)) | ((uint32_t)GPIO_Mode_AF << (10 * 2));
复制代码
- v/ x; s2 E! D6 m- B2.3 配置输出模式(OTYPER)
) u+ ]# o- F' C' o* t# e S
/ |* Q! e3 `5 ]0 ?7 |0 j/ z& Y* P; Y( u! B$ p
/ D+ z6 h% S% g# n1 m每个bit表示输出模式,1 P1 C3 a7 G0 i n( B* H& B
& ?) m; V6 T3 L5 A4 V
0b0: PP模式;* _; _& Q3 j) E4 R6 ~+ G" t
& h- ^, T" S! ~$ O; W% s; f
0b1: OD模式。 & t) q" _' \5 R( U
; ~0 i) I+ T9 j: Z7 n- C& v
- typedef enum) \) m; Y% U9 m! j; R$ ^
- {
0 J+ i+ ]$ w7 x; P! T% f8 Q+ G - GPIO_OType_PP = 0x00,8 G; [5 Y. b9 v1 R- l2 R
- GPIO_OType_OD = 0x011 s- { w$ |" u% _+ f5 b ^
- }GPIOOType_TypeDef;
复制代码 ) C. ]- q, u0 r
例如:9 H$ W0 H. Z/ _% g. L, Z2 U
- GPIOA->OTYPER |= (((uint32_t)GPIO_OType_PP << (9 * 1))
D$ O& w: ~2 z9 d' q8 T - | ((uint32_t)GPIO_OType_PP << 10 * 1))
复制代码
. N/ q; {% B6 _) _. N: [5 A2.4 配置上下拉模式(PUPDR)
( e- C8 a& D8 p" g+ Z2 Z% Q3 |; S, s# u" A* G
' d$ ]; w+ ~; p
. K8 o2 g7 ]+ U0 G# a每2个位表示上下拉模式。* _# H) l& c' I
- typedef enum
3 D) J5 T7 X* A, C+ x+ q - {
5 ?$ g. G7 T$ H$ |; [ - GPIO_PuPd_NOPULL = 0x00,
3 F& y3 j" |5 k/ a. ]; p - GPIO_PuPd_UP = 0x01,+ D) P6 C7 ^( e7 v7 a2 M6 c
- GPIO_PuPd_DOWN = 0x02: b8 ], ], ]3 V0 X7 ~, {
- }GPIOPuPd_TypeDef;
复制代码 ( |1 N- \# f9 l4 a$ ]
例如:+ S5 ^3 J! T/ M4 h+ e3 q; T
- GPIOA->PUPDR &= ~((0x00000003 << (9 * 2)) | (0x00000003 << (10 * 2)));
复制代码
n1 i% N A8 U, t8 V4 I4 d, w# f" j1 R3. 输出
/ K) x( G- P+ A+ n/ Z输出电平通过寄存器BSRR(输出高电平和低电平)和BRR(输出低电平)实现,写入1表示对应操作,写入0无效。例如:
5 Y3 K/ z0 q8 h' u3 U5 | J5 z; n; G/ f) C2 h& s
- #define SDA_HIGH(n) IO_I2CIO_SDA->BSRR = ((uint32_t)1 << PIN_I2CIO_SDA)
l" _8 s$ v3 q7 R7 p. w9 l3 N - #define SDA_LOW(n) IO_I2CIO_SDA->BRR = ((uint32_t)1 << PIN_I2CIO_SDA)
复制代码 " f9 h( z, `6 f6 a* ?/ X0 y6 o: }/ O
BSRR的低16位分别对应16个PIN的输出高电平操作,高16为对应输出低电平操作。+ L: t; n! E6 C, a* ]
3 A& n- A: q4 o, R3 @" @) F
而BRR只有低16位有效,对应对应输出低电平操作。: w# [) W9 \$ Q) A5 p2 g
0 Z8 g+ n3 m8 a9 @, u
8bit总线输出1 r" x; F6 Q, f; C/ X. g
& U! U& B t, H/ S
- #define I8080_D8_OUT(dat) IO_I8080_D8->BSRR = (dat & 0xff) | ((uint32)((~dat) & 0xff) << 16)
复制代码 4. 读入IO
: m, L/ q" G L0 h; ]通过寄存器IDR读出对应I/O口的状态。低16位有效。- H3 a# m Z1 p: k, m4 f ?* [
- c" o& z4 m& L7 {
- #define SDA_READ(n) (IO_I2CIO_SDA->IDR & ((uint32_t)1 << PIN_I2CIO_SDA))
复制代码
; \! a! F' U t- q' P" E
; {; B. k6 Q# z" z3 A$ r% E7 _( G
|