STM32F0xx的IO口定义方式与STM32F10x类似,一组GPIO包含16个IO。每组GPIO同样用GPIO_TypeDef的结构指向对应的寄存器空间。
7 H, v& K) ] f) e& R1 a, D, E: W) Y8 ]
- <blockquote>#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
复制代码
- y) c+ _9 y4 r& O3 ~7 \- ? ^但是寄存器空间与STM32F10x的不同。
. K+ R/ ?/ S+ X6 F4 r- <blockquote>typedef struct
复制代码 & \& [& Q8 V2 q8 V5 ^
1. 使能GPIO的RCC
3 s# F8 m- q+ w URCC->AHBENR |= RCC_AHBPeriph_GPIOn
+ A$ j( M7 g9 j Q% W& Z* T2 o5 G5 p3 A9 v q U
其中n的范围为A-F。
0 m8 j2 V) V( j, |- u0 ^+ H& X5 i8 d* P! d T& u; u
如果涉及到复用,与STM32F10x不同,这里用寄存器AFR[2]来设定复用。每个IO用4bit来选择复用功能,最多有8种复用。: r5 A7 \/ _1 k/ @1 X
( ~' U7 h9 b8 @8 h8 {) v1 A+ E2 B2 G) r' e9 W) U5 I
例如GPIOA9,GPIOA10的AFR设定: I/ F. M% h4 f5 M# u9 {, x2 c
" U4 ]( D7 k& o" i; ]3 @* W" W6 h
- *((uint32_t *)GPIOA->AFR + ((9 / 8))) &= ~(0x0000000F << ((9 % 8) * 4));) y( p* S9 X: q3 L1 O
- *((uint32_t *)GPIOA->AFR + ((9 / 8))) |= (0x00000001 << ((9 % 8) * 4)); ) I: N, C n: b" F1 A
- *((uint32_t *)GPIOA->AFR + ((10 / 8))) &= ~(0x0000000F << ((10 % 8) * 4));, [. s' W* T C5 b9 q& b0 l
- *((uint32_t *)GPIOA->AFR + ((10 / 8))) |= (0x00000001 << ((10 % 8) * 4));
复制代码 $ E/ _$ F4 ?$ E3 p% @1 D
2. 配置GPIO% g" B/ B, _) D' v% Y
2.1 设置输出频率(OSPEEDR)( h' E1 t$ t6 D8 E4 P. x
- p' {* x9 g3 `8 v2 F( r
$ W- C( A$ g% J" N' l* h& k
1 E+ d% u- M, n每2个位配置一个Pin。默认是2MHz。! I& t- Z' W5 t4 K* Q' W
% Z" V+ e; o0 e7 P0b00, 0b10: 2MHz, u9 f$ l, [7 z7 b9 b
7 h$ b. V+ D# _' y+ ^7 F3 i4 T
0b10: 10MHz
' {8 j2 i. a. i8 `1 A( @/ @) G% A1 z8 K I% a% @8 _% A+ V
0b11: 50MHz) _8 m* ~: F4 a2 K2 x
9 \4 k O8 N! r% P1 K( d- typedef enum
3 A/ R- j, {& u& ^: f# K* T - {
+ `; ~( j+ j* K& B - GPIO_Speed_Level_1 = 0x00, /*!< I/O output speed: Low 2 MHz */0 R; W( Y L& H; i' h! g
- GPIO_Speed_Level_2 = 0x01, /*!< I/O output speed: Medium 10 MHz */3 D" l5 t9 ]' L
- GPIO_Speed_Level_3 = 0x03 /*!< I/O output speed: High 50 MHz */; l; _3 b2 N2 z* ? l
- }GPIOSpeed_TypeDef;
1 Q. `+ A3 X1 I! _" Q3 c2 f
- L5 m8 g/ I% j+ ^) E9 e: [- #define GPIO_Speed_2MHz GPIO_Speed_Level_1 /*!< I/O output speed: Low 2 MHz *// K4 u: K4 m- P# O. }
- #define GPIO_Speed_10MHz GPIO_Speed_Level_2 /*!< I/O output speed: Medium 10 MHz */
+ w: a, f7 V2 K: E. a* I5 I0 [- s" S - #define GPIO_Speed_50MHz GPIO_Speed_Level_3 /*!< I/O output speed: High 50 MHz */
复制代码 ; s' y: |' {; B, ^
例如A9、A10都为50MHz:
U U- S# k! A2 x7 A3 K) F$ B) s/ m" q- {, w' I( u
- GPIOA->OSPEEDR |= (0x0000000F << (9 * 2));
复制代码 % I, v) R; A5 u+ E
2.2 配置输入输出(MODER)9 p# ?8 p4 _! S7 w3 t+ H6 a; B
+ y; S9 }# `6 s' _/ L
+ ?# |0 E9 E. x/ |+ L2 L; C& k/ l9 t5 j( p, ?
每2个位配置一个Pin。 默认Input(除了SWD的A13,A14)
! R8 d1 j: u' M/ I& R5 |
( M/ u# v& Q3 Z4 E0b00: Input8 i: J9 w! k( H5 B
* s6 [# A7 ?: j1 ^0b01: Output
! E1 y5 J/ L6 m ~
2 D/ r0 o* a' R4 c4 D5 b0b10: AF
8 Q9 o1 m8 G2 Y/ ]" v
4 m+ b2 p* w& n: i5 o7 g0b11: Analog In/Out6 L. T( c4 A9 t
. i* ?! i! E4 l1 P9 [' k8 p- typedef enum2 X& Y# ?. ] P3 |: @7 V8 q
- {
; P- X6 b3 @/ c! ^: y - GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */
# I; `+ V8 b" K t6 v" ?4 | - GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */
7 t: |8 E, W ~- J - GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */4 p# E) ~# ]: Y. p
- GPIO_Mode_AN = 0x03 /*!< GPIO Analog In/Out Mode */
$ ^2 w+ x3 P" E5 Y6 Y - }GPIOMode_TypeDef;
复制代码
/ x: q% j# M u L$ r, c! h$ {+ l例如GPIOA9,GPIOA10为AF:9 d5 I: v6 M1 a$ w) ` r, O
- GPIOA->MODER |= ((uint32_t)GPIO_Mode_AF << (9 * 2)) | ((uint32_t)GPIO_Mode_AF << (10 * 2));
复制代码
2 |: K* `4 ` O% Z; E3 R2.3 配置输出模式(OTYPER)+ N8 t ^% d; v
3 ?- W" Q! k4 {# F3 j
( X* B: P8 r: k; U) w: S7 T) |/ L7 E$ u m, p! R% j- {+ k
每个bit表示输出模式,# [$ y: `6 }7 [) E% Y+ x
" ?0 J( }4 W" C
0b0: PP模式;/ z8 J& p! g" W v: t! { ^0 M
+ S- y! ], m5 k0 n/ r0 x1 l- Z0b1: OD模式。
0 I) s! g& N- Z- ^9 {
6 O, M7 t; n V$ `- typedef enum
: W: @9 u8 F( U1 V7 K: d - {1 A! E3 t) G& B; `2 |
- GPIO_OType_PP = 0x00,, b' } A& o% u
- GPIO_OType_OD = 0x01
8 g3 x1 F$ T ] i - }GPIOOType_TypeDef;
复制代码
) J3 N& b: l8 O. B0 I) ? 例如:' F" ~$ G, J( a. L
- GPIOA->OTYPER |= (((uint32_t)GPIO_OType_PP << (9 * 1))
. D. L6 h9 [; d; L - | ((uint32_t)GPIO_OType_PP << 10 * 1))
复制代码
4 F' C0 `. g# k( t5 \! F4 [. H+ Y- `2.4 配置上下拉模式(PUPDR)! t& L ~7 \! |5 j: P) ^8 n
1 ~) m% N7 D3 x' j. r% h7 d! Y
# C+ x' V' L9 F+ J" T0 y) U
5 \; t4 ]6 M3 Z& g7 e
每2个位表示上下拉模式。
" e9 I4 \1 u/ G4 m: }3 b) M2 ?- typedef enum0 N! v. L! ^, q6 C7 y; i. C V+ x) T* e
- {# ~% k9 M' R* B/ k9 m1 [2 m
- GPIO_PuPd_NOPULL = 0x00,
! U8 O! S; c0 }8 c: F0 T - GPIO_PuPd_UP = 0x01,
) t" {5 s3 C$ F - GPIO_PuPd_DOWN = 0x02
6 y4 |) ?7 x0 T8 k6 ?5 v, j- i' W t - }GPIOPuPd_TypeDef;
复制代码
: L! v* b6 }# D5 K" ^5 M例如:
5 e( s' ^$ N; V7 Q/ B2 R: Z# z- GPIOA->PUPDR &= ~((0x00000003 << (9 * 2)) | (0x00000003 << (10 * 2)));
复制代码 8 x! U- E& v# R
3. 输出
& B1 O1 m- c5 j输出电平通过寄存器BSRR(输出高电平和低电平)和BRR(输出低电平)实现,写入1表示对应操作,写入0无效。例如:* @, P% V' c E; _# v/ x
; }1 @& O3 ]5 c* _7 v
- #define SDA_HIGH(n) IO_I2CIO_SDA->BSRR = ((uint32_t)1 << PIN_I2CIO_SDA)
s; I7 U: @8 d6 E/ G& ?% i6 q - #define SDA_LOW(n) IO_I2CIO_SDA->BRR = ((uint32_t)1 << PIN_I2CIO_SDA)
复制代码 6 O/ A$ Y& D- p9 x
BSRR的低16位分别对应16个PIN的输出高电平操作,高16为对应输出低电平操作。* z* F1 n2 I0 y# m! v" u2 B. `$ q" E
8 U q2 J% I! w# ]/ a1 N. S. d0 B而BRR只有低16位有效,对应对应输出低电平操作。2 V2 `8 Q# r1 G1 x6 z* B/ ~0 y
! V2 b) K9 u% r: c6 o' X( N( z* w8bit总线输出
$ A4 z0 v# Y: _ C& @
# A% m# o9 p! Z& v# e- #define I8080_D8_OUT(dat) IO_I8080_D8->BSRR = (dat & 0xff) | ((uint32)((~dat) & 0xff) << 16)
复制代码 4. 读入IO2 S- A/ T* G/ R" L2 ]7 T7 o7 \
通过寄存器IDR读出对应I/O口的状态。低16位有效。
( U7 e' Q" c, G, ]. }$ {
; h; D8 e1 a" k3 j- #define SDA_READ(n) (IO_I2CIO_SDA->IDR & ((uint32_t)1 << PIN_I2CIO_SDA))
复制代码
' v9 I* N' E- Z& D7 W2 p+ w; S
" k$ S$ k9 c7 W3 J, e9 F+ A
. ~8 K9 ?( n3 ]7 D1 P! N |