STM32F0xx的IO口定义方式与STM32F10x类似,一组GPIO包含16个IO。每组GPIO同样用GPIO_TypeDef的结构指向对应的寄存器空间。) A5 t- D# W* ^* q& o- \. T0 H
( [9 n. S0 ]5 `: G* Y6 O7 L- <blockquote>#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
复制代码
+ {. L% @$ p8 Y+ y" l5 U但是寄存器空间与STM32F10x的不同。
8 i# g" ~" U" C" S- <blockquote>typedef struct
复制代码 $ {9 B, z3 t. @" a3 A
1. 使能GPIO的RCC
- @% }6 k) Y* H! |+ ]RCC->AHBENR |= RCC_AHBPeriph_GPIOn( s6 S( ~% h+ e+ R: A0 x4 m
5 `8 l6 @0 ^& h) ?% i其中n的范围为A-F。5 s: j, }- w9 S- K0 t
2 g: E E0 m. D8 y% E6 q5 b3 p
如果涉及到复用,与STM32F10x不同,这里用寄存器AFR[2]来设定复用。每个IO用4bit来选择复用功能,最多有8种复用。
8 i% {5 a0 h2 O; L: c( M! U$ x; E6 j( c5 n: D
: U4 @8 r! @% l2 G1 G$ n8 G例如GPIOA9,GPIOA10的AFR设定:) ^* y# i5 ^1 D Q E
" U5 n& }5 R% `. E6 b* } a& b; Y- *((uint32_t *)GPIOA->AFR + ((9 / 8))) &= ~(0x0000000F << ((9 % 8) * 4));
* f: M0 P6 V% R; y, W& ~ - *((uint32_t *)GPIOA->AFR + ((9 / 8))) |= (0x00000001 << ((9 % 8) * 4)); ( O8 n& u* k! Y4 s( m4 C
- *((uint32_t *)GPIOA->AFR + ((10 / 8))) &= ~(0x0000000F << ((10 % 8) * 4));2 b' |) {6 n3 r" T, n% a, e
- *((uint32_t *)GPIOA->AFR + ((10 / 8))) |= (0x00000001 << ((10 % 8) * 4));
复制代码
P3 }" z' S5 H2. 配置GPIO
1 m. \+ D, h+ O& a% o, d2.1 设置输出频率(OSPEEDR)+ `( L: u- ^* E( h! M4 X& m
' z3 x7 ~& w. _* y2 p% I( r
3 n4 y& `1 p) j; j p1 y, `3 p8 a
每2个位配置一个Pin。默认是2MHz。
# F B) R8 a& ?: Z2 t
( ^" a O: h8 w4 t; m# g% v0b00, 0b10: 2MHz
$ {* h; M: f. k6 t- |& w
0 C, i7 X% v9 C9 \+ |( |7 r0b10: 10MHz' i# K. [' |+ P! C: f% ~- |9 X9 t
5 C; V) K$ J% l) i8 Q0b11: 50MHz
! o$ Q- e/ }5 C' d' `4 @+ p" Q# p8 x, K) Q7 @
- typedef enum
& A: @. z$ J3 L4 g3 T) ~ - {
' Z: {. G& M6 o) G2 V - GPIO_Speed_Level_1 = 0x00, /*!< I/O output speed: Low 2 MHz */: b! g+ ]/ W, h: e1 i$ ^( Q N
- GPIO_Speed_Level_2 = 0x01, /*!< I/O output speed: Medium 10 MHz */
: Q" E8 w' j( {" Y5 {7 x - GPIO_Speed_Level_3 = 0x03 /*!< I/O output speed: High 50 MHz */2 J& h8 F9 m+ G i K( r
- }GPIOSpeed_TypeDef;
9 A( K+ x$ t. o9 t
: z% ]2 j: [2 p. K8 }) i$ A- #define GPIO_Speed_2MHz GPIO_Speed_Level_1 /*!< I/O output speed: Low 2 MHz */; G. ^! u$ |- m0 G4 Z
- #define GPIO_Speed_10MHz GPIO_Speed_Level_2 /*!< I/O output speed: Medium 10 MHz */. ]/ \, O' o! ~2 r2 ~6 f, Z
- #define GPIO_Speed_50MHz GPIO_Speed_Level_3 /*!< I/O output speed: High 50 MHz */
复制代码
- `/ J8 M* Y" Y+ h0 M! {例如A9、A10都为50MHz:
2 K' [9 i! R0 K# n( \8 O/ M8 H F% ]- M1 Q" b. H
- GPIOA->OSPEEDR |= (0x0000000F << (9 * 2));
复制代码
- X1 E3 U' i2 [2.2 配置输入输出(MODER)
( M* a W$ T) z [
% d" v* N: H" h8 S$ s5 E! k& {7 \4 e" o, ~0 Z- M
4 _) P) c, B! M每2个位配置一个Pin。 默认Input(除了SWD的A13,A14); \% R/ z, a( |+ M% Z
, O8 M' B1 _9 u0b00: Input0 x' j1 m% p9 D, v. f8 }0 _4 T
" L: m. _" a2 E8 j4 F1 K9 x0b01: Output
1 i% V% J/ E- o k9 {; O6 P/ ?4 G9 z6 ?
0b10: AF
7 p$ j( y6 l# w% h; s& i9 s9 r5 E+ } [% z
0b11: Analog In/Out
1 x: Z C7 n* d3 h' w; x
* }7 b- w; p( {$ `3 { R2 A3 R& v- typedef enum
8 Q( ~0 @) q$ k K1 `! Q5 w - {3 f' ~. j. v( A8 w$ [$ ~) Q" J% X! D
- GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */
% ~$ s- q5 n* {# m - GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */3 ]) Q. }, e2 @& t8 H7 s9 t
- GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */
5 u7 o7 k" l3 h, @5 D - GPIO_Mode_AN = 0x03 /*!< GPIO Analog In/Out Mode */7 ~- h/ B. P! G1 H
- }GPIOMode_TypeDef;
复制代码
1 k$ I+ {5 s: r例如GPIOA9,GPIOA10为AF:
3 k+ \3 |) Q( I- GPIOA->MODER |= ((uint32_t)GPIO_Mode_AF << (9 * 2)) | ((uint32_t)GPIO_Mode_AF << (10 * 2));
复制代码 0 p% N0 [( g# h9 H
2.3 配置输出模式(OTYPER). D3 B7 W& \$ q8 a- l* O+ j$ f5 c3 w
& W5 e- ~ \) d- e5 r! Q$ U9 x
% O, S: l- E, N- | I
7 j1 g; f0 X) C9 r每个bit表示输出模式,
8 w4 \- y2 R4 a. T# Q; J: k9 B; a$ Q0 D2 E" V2 ]( c V, J9 l$ q
0b0: PP模式;+ c# c4 Q' A3 I9 Y3 d
0 ]" c' O& @# P' f& e) Q0b1: OD模式。
2 I: Q8 N, q6 m! m$ B
2 j8 V9 ?$ X, P* W" T8 `- typedef enum
: j E% u( t. _ - {
1 ~4 C. g$ r: y2 S/ u - GPIO_OType_PP = 0x00,
* c5 G' s) w3 p) X7 j9 P1 F - GPIO_OType_OD = 0x01. u0 Y) M j# q; E/ I
- }GPIOOType_TypeDef;
复制代码 # u! \5 ~$ G! N, Z% w! v5 j0 J
例如:
! r7 Z; A! k2 w! f! O: v: o9 u5 k& ~- GPIOA->OTYPER |= (((uint32_t)GPIO_OType_PP << (9 * 1))
: ^* \+ _$ Y/ }6 v. d - | ((uint32_t)GPIO_OType_PP << 10 * 1))
复制代码
8 e5 _: B. M2 o6 K! P# V2.4 配置上下拉模式(PUPDR)
! m5 d& D# n+ [: K( f/ ~
p$ \" C8 v3 a$ j8 M( ~
0 U: L/ L$ {& V) L, f2 W3 J* \9 {. `0 T! h# h/ h8 n# }
每2个位表示上下拉模式。) F6 F4 @: e( M! F
- typedef enum& ]+ F! e/ U7 q- e
- {8 t/ R, X* p; c; E% U! z
- GPIO_PuPd_NOPULL = 0x00,
6 n* a4 \4 Z' \6 ]5 A5 f - GPIO_PuPd_UP = 0x01,7 t) F, x! g' G: b' R0 k3 n* W7 Z
- GPIO_PuPd_DOWN = 0x02/ k7 S* e) v1 Z1 s. @
- }GPIOPuPd_TypeDef;
复制代码 % b& f, B: g/ a1 {% g( u
例如:: L3 c! B( T2 C# u3 O' |2 b
- GPIOA->PUPDR &= ~((0x00000003 << (9 * 2)) | (0x00000003 << (10 * 2)));
复制代码
7 F4 c0 Z) X1 n: Y: A/ ~( K3. 输出7 ^& J6 n: D7 f3 G' i$ K# K4 ?
输出电平通过寄存器BSRR(输出高电平和低电平)和BRR(输出低电平)实现,写入1表示对应操作,写入0无效。例如:
0 B9 o; o4 t5 R1 D0 @ z6 H u6 U a q6 S; @
- #define SDA_HIGH(n) IO_I2CIO_SDA->BSRR = ((uint32_t)1 << PIN_I2CIO_SDA)
4 \! t# L5 Y: i d, A - #define SDA_LOW(n) IO_I2CIO_SDA->BRR = ((uint32_t)1 << PIN_I2CIO_SDA)
复制代码
3 c0 f7 G @2 n& |8 f3 l* C BSRR的低16位分别对应16个PIN的输出高电平操作,高16为对应输出低电平操作。" c3 y0 N9 Q( y+ K) U- a
+ _8 G: B/ v4 d) q$ ]5 P而BRR只有低16位有效,对应对应输出低电平操作。
0 k5 E+ g) T+ d4 a' c2 I$ I
8 h9 X+ [. H9 Z# U, i8bit总线输出
( R) v& C, O1 ^ |4 L) q- @+ I% I( w" W) e
- #define I8080_D8_OUT(dat) IO_I8080_D8->BSRR = (dat & 0xff) | ((uint32)((~dat) & 0xff) << 16)
复制代码 4. 读入IO
* b/ b/ k8 Q( a5 J& g通过寄存器IDR读出对应I/O口的状态。低16位有效。
" U; D& ^$ _9 j5 @6 j+ W4 P# t3 q3 g- ^% A5 o6 e
- #define SDA_READ(n) (IO_I2CIO_SDA->IDR & ((uint32_t)1 << PIN_I2CIO_SDA))
复制代码 8 M7 ^) }. M! ^3 {! s
1 X' F; C; h) a. n! i4 I7 e+ {) r: i0 B& j
|