STM32F0xx的IO口定义方式与STM32F10x类似,一组GPIO包含16个IO。每组GPIO同样用GPIO_TypeDef的结构指向对应的寄存器空间。
. o. G% q- ~9 @$ a3 D& a" s* V4 l
- <blockquote>#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
复制代码
9 Y4 d+ V. r# \) g) Y8 u1 G但是寄存器空间与STM32F10x的不同。5 Z8 u5 S3 W# M/ R! d
- <blockquote>typedef struct
复制代码
3 }* }. E7 Q% t9 a1. 使能GPIO的RCC
5 w3 R, E8 d4 C- o" A, i' pRCC->AHBENR |= RCC_AHBPeriph_GPIOn: T/ I" A4 L- U' z* ?
1 C3 ?3 Q7 @2 h% ^; T/ \其中n的范围为A-F。 K' L f" X* d; }
2 y. b, h/ O7 N0 w$ v如果涉及到复用,与STM32F10x不同,这里用寄存器AFR[2]来设定复用。每个IO用4bit来选择复用功能,最多有8种复用。& B3 I) u# f. J. K9 o1 `5 D; n; g
8 a2 p+ T$ Y; [
/ l% q& s V" R( N' a. v$ Q例如GPIOA9,GPIOA10的AFR设定:# `: z6 H, ^1 I2 ^; A
& W ~+ Z- c, c8 U, ]3 M( V) T; X/ C- *((uint32_t *)GPIOA->AFR + ((9 / 8))) &= ~(0x0000000F << ((9 % 8) * 4));( S3 ~8 T2 c2 K! N
- *((uint32_t *)GPIOA->AFR + ((9 / 8))) |= (0x00000001 << ((9 % 8) * 4));
9 Q4 H2 c ?3 u - *((uint32_t *)GPIOA->AFR + ((10 / 8))) &= ~(0x0000000F << ((10 % 8) * 4));$ W$ g: c$ ^: |
- *((uint32_t *)GPIOA->AFR + ((10 / 8))) |= (0x00000001 << ((10 % 8) * 4));
复制代码
6 \2 ^ h2 s% a, f* F2. 配置GPIO. Q3 x% Z- f* \& U0 z9 S. i
2.1 设置输出频率(OSPEEDR)6 D9 e$ k, [" j4 X3 o7 ^1 X8 J
$ P2 U* F. l5 {7 z* G! L9 V1 j
% h2 P6 H$ `8 g$ o: r$ u
( }. e1 D f# H, K; N( L9 y每2个位配置一个Pin。默认是2MHz。9 A7 o8 q2 s, N: L9 C
3 w! W7 L2 b& t3 f; G4 s
0b00, 0b10: 2MHz# k8 H* B1 y, @& ]
0 M7 q$ W; X: L0b10: 10MHz
- j5 a, N w( T4 d2 T; U! W$ O0 h1 S% q0 [! {- i$ B
0b11: 50MHz
$ @8 J1 T, T: d
, ?: M7 ^5 S6 n! M( d4 N- typedef enum% s2 J" T( l8 W3 b- N) q' n, [; Q: L
- {* _2 B1 J; Q' a; T
- GPIO_Speed_Level_1 = 0x00, /*!< I/O output speed: Low 2 MHz */5 Z( f8 E+ n+ D" z) p
- GPIO_Speed_Level_2 = 0x01, /*!< I/O output speed: Medium 10 MHz */2 N6 K @& g0 u
- GPIO_Speed_Level_3 = 0x03 /*!< I/O output speed: High 50 MHz */7 O0 j, C( I7 ]' @9 F6 R5 m
- }GPIOSpeed_TypeDef;
! o- R1 b W- R) @ - * W' _% a) F" e+ U) `
- #define GPIO_Speed_2MHz GPIO_Speed_Level_1 /*!< I/O output speed: Low 2 MHz */. h9 m/ I2 [ l/ ^# n1 [8 ]! _" C
- #define GPIO_Speed_10MHz GPIO_Speed_Level_2 /*!< I/O output speed: Medium 10 MHz */
$ A+ X9 V- K% c& U: s- O - #define GPIO_Speed_50MHz GPIO_Speed_Level_3 /*!< I/O output speed: High 50 MHz */
复制代码 & J$ X5 ~6 |3 o; x) n2 R
例如A9、A10都为50MHz: ! z9 O* u, E; I* q3 |
$ v4 j; }0 e" w: y$ [; x
- GPIOA->OSPEEDR |= (0x0000000F << (9 * 2));
复制代码 / Y% M# A, q, I! d; e W# S% t) m- y
2.2 配置输入输出(MODER)5 y0 b1 i9 O6 O% P
5 ?1 D% r9 m- P! H
- C5 ?1 f1 l( x3 y; t. G
' y$ ^! P6 L) V1 i- F每2个位配置一个Pin。 默认Input(除了SWD的A13,A14)# Y- g4 `& a: e& ]
1 N+ n9 N9 r! h, }: C, t0b00: Input' W9 y; s3 w0 Q
& H8 X/ O" h3 I' R( N
0b01: Output
. ^0 ^3 i+ O% t" a% o. n
9 p: J2 }+ x% J6 q0b10: AF9 e( l6 r" s3 Z; t9 b) x$ m
, e5 D) l$ j& S4 x5 F/ Z; @$ S0b11: Analog In/Out# R* ^0 B% [/ i
( j' m# t9 m2 q/ z2 j. c
- typedef enum4 D6 a6 l, l& P* k
- {& w" S X9 y5 h0 C
- GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode *// U3 e: C* L- f {9 z6 W
- GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */: r" {0 X& T( e+ A7 U7 e8 e
- GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */* P/ R" J7 G0 x4 y% g
- GPIO_Mode_AN = 0x03 /*!< GPIO Analog In/Out Mode */- d/ n5 R$ ~0 U8 O
- }GPIOMode_TypeDef;
复制代码 3 U7 o$ r' k5 D0 C: P# w( C# G. n
例如GPIOA9,GPIOA10为AF:
6 X- x" _1 K9 W- GPIOA->MODER |= ((uint32_t)GPIO_Mode_AF << (9 * 2)) | ((uint32_t)GPIO_Mode_AF << (10 * 2));
复制代码
: ^5 f) y8 `) S% K, p, x: o2.3 配置输出模式(OTYPER)+ E4 S- V* ^ Y, D+ N5 u
0 f3 c/ K& [4 V8 o
7 m# o5 K, c' H, O) c( g4 R$ H4 G3 e/ x, h4 V7 `- R% \
每个bit表示输出模式,
; m0 ~) X8 i- p7 v5 O0 A3 x3 p8 I' ^" k: a8 T
0b0: PP模式;
' U' C7 V3 ?6 O& J: a. C) m
& n3 V# S. E d% ^( U0b1: OD模式。
, i' [7 f5 O& k- F2 G; M) B' o
6 ~. E) M! _) O" U: S( O2 ~1 e8 a/ F- typedef enum0 v7 {5 W+ K N4 o9 h
- {
% @8 C, |8 j* D+ I8 B8 M( ` - GPIO_OType_PP = 0x00,8 f$ {3 ~4 T" J- _" {
- GPIO_OType_OD = 0x01
/ [7 v* h) Z# w1 P% t, i - }GPIOOType_TypeDef;
复制代码 0 _& L4 c% i+ U: E" T) Y
例如:
4 r- E x( ?" X9 n# k- GPIOA->OTYPER |= (((uint32_t)GPIO_OType_PP << (9 * 1)) 1 q: {2 Q0 Q; R' ^! V3 A4 b
- | ((uint32_t)GPIO_OType_PP << 10 * 1))
复制代码 5 ~4 u% |7 d2 c9 ?3 |1 F
2.4 配置上下拉模式(PUPDR)
; c. `$ f& V! g- _0 x( z% l. r
' o! M, p% Y* `( N+ D$ I6 A' n6 k8 M4 D
$ W, p- v8 y" M& c: o每2个位表示上下拉模式。
- J" J. n6 T5 }7 f: N- typedef enum5 R" y1 W- V1 Z' b% y! l
- {7 i0 s' ?% w8 e4 I. N: j
- GPIO_PuPd_NOPULL = 0x00,# I& N j* q! R
- GPIO_PuPd_UP = 0x01,2 `7 H* s P% F/ X7 v c
- GPIO_PuPd_DOWN = 0x02
, Z6 R: x! f! M R" H1 E+ X - }GPIOPuPd_TypeDef;
复制代码 ! t) F8 c3 ~& A2 Y
例如:
9 d: _# m4 k; g; J- GPIOA->PUPDR &= ~((0x00000003 << (9 * 2)) | (0x00000003 << (10 * 2)));
复制代码
, i9 `2 i( f- t U0 B- C* _3. 输出
, W6 l1 ? B& C" U输出电平通过寄存器BSRR(输出高电平和低电平)和BRR(输出低电平)实现,写入1表示对应操作,写入0无效。例如:" @; X+ |: ~2 c+ H. \* K8 y
3 f& a* s8 ?9 w# Y0 y% U3 h9 g
- #define SDA_HIGH(n) IO_I2CIO_SDA->BSRR = ((uint32_t)1 << PIN_I2CIO_SDA)
& a( d# S) V' H& A& Q - #define SDA_LOW(n) IO_I2CIO_SDA->BRR = ((uint32_t)1 << PIN_I2CIO_SDA)
复制代码 : t! H' h% e5 I, T* R& h" L! ?
BSRR的低16位分别对应16个PIN的输出高电平操作,高16为对应输出低电平操作。0 O. }9 n7 [3 t
7 d8 I4 H4 t; S' ]: Q
而BRR只有低16位有效,对应对应输出低电平操作。% c3 Y1 h7 e! g% P: O% T
: J7 V! H8 _) I! a/ K
8bit总线输出
: i+ a2 |7 i' j. M5 U3 F& P, @3 x6 |$ k6 A
- #define I8080_D8_OUT(dat) IO_I8080_D8->BSRR = (dat & 0xff) | ((uint32)((~dat) & 0xff) << 16)
复制代码 4. 读入IO
5 t, s2 I z( q% U通过寄存器IDR读出对应I/O口的状态。低16位有效。5 K* W+ ]# G' w( Y) Q1 C' P2 K) v& d
?$ D3 `7 p5 a$ I* W% p- M$ a8 g- #define SDA_READ(n) (IO_I2CIO_SDA->IDR & ((uint32_t)1 << PIN_I2CIO_SDA))
复制代码
& \3 ^( T) J# Q; Y5 p
! K; \% V4 k' b Y) q8 {$ d; b, \9 N" k1 T. h3 L2 j
|