STM32F0xx的IO口定义方式与STM32F10x类似,一组GPIO包含16个IO。每组GPIO同样用GPIO_TypeDef的结构指向对应的寄存器空间。) x; ?9 R1 ~5 O) m3 _8 Z. q
* `' Z# Y( g7 T; l
- <blockquote>#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
复制代码
: O, F }* _3 I! u8 E但是寄存器空间与STM32F10x的不同。
/ V" d1 ]/ |" {; n$ ?- <blockquote>typedef struct
复制代码 + B+ H5 U# x7 o$ E0 A0 O
1. 使能GPIO的RCC
4 w, J3 L) x$ I" n, Z, ~# n# ARCC->AHBENR |= RCC_AHBPeriph_GPIOn
/ k$ [: ]) j6 D0 H! d* M, ^" L; Y) A( ?" ?
其中n的范围为A-F。
) @, [: k1 O5 q& F9 w3 R# e0 t, i; \' [& e( c# X! [4 c% ^
如果涉及到复用,与STM32F10x不同,这里用寄存器AFR[2]来设定复用。每个IO用4bit来选择复用功能,最多有8种复用。
6 O# e+ [. h t1 P- X2 r- b m/ Z, M4 A" a5 }) Q8 W% h' Q
% e7 G$ q7 u2 I& ]9 `& `例如GPIOA9,GPIOA10的AFR设定:
3 s- E& s- c8 H/ p
! r' l4 v* q" U- *((uint32_t *)GPIOA->AFR + ((9 / 8))) &= ~(0x0000000F << ((9 % 8) * 4));9 o8 j" y$ j: q# i0 x
- *((uint32_t *)GPIOA->AFR + ((9 / 8))) |= (0x00000001 << ((9 % 8) * 4)); % V' Z% o8 q$ Q1 G$ D: F$ X
- *((uint32_t *)GPIOA->AFR + ((10 / 8))) &= ~(0x0000000F << ((10 % 8) * 4));( K( d1 o( Y8 v) o# ]
- *((uint32_t *)GPIOA->AFR + ((10 / 8))) |= (0x00000001 << ((10 % 8) * 4));
复制代码 ' A. G7 |9 [3 b) G& d# T
2. 配置GPIO
H# ]- l* y0 o6 @/ b. |2.1 设置输出频率(OSPEEDR)$ C) Y- O, I$ |- I7 d
" j/ _% K( S8 ]( n2 e6 v% x& u# I1 Y
5 y* t7 H. I2 k每2个位配置一个Pin。默认是2MHz。. k$ u4 m* ?' o
% B! l1 ~( m1 o0b00, 0b10: 2MHz
7 a5 c' r" u. ?, B4 X8 x V" k! `6 i+ P% X' p8 Z( T8 G, A
0b10: 10MHz
2 u1 K4 D. p3 n
9 K- Y5 [4 w/ h: T+ |2 D0b11: 50MHz
; s6 h9 A: |( i5 d
1 Q7 C5 x* e: _* z9 W+ \: b! {# _- typedef enum
* }5 [: ^5 O# @ - {3 }- H3 D0 ^. O* j% C% @* s
- GPIO_Speed_Level_1 = 0x00, /*!< I/O output speed: Low 2 MHz */
" I U9 _0 u5 f; t* h - GPIO_Speed_Level_2 = 0x01, /*!< I/O output speed: Medium 10 MHz */# q! R4 Z9 t O1 x/ O
- GPIO_Speed_Level_3 = 0x03 /*!< I/O output speed: High 50 MHz */
3 X: a8 A$ ^. s/ v6 G/ B - }GPIOSpeed_TypeDef;) H4 Q7 \. Y7 c& y0 k$ G7 s' K
- 1 y& y C4 E' S, u; b& d- G: \
- #define GPIO_Speed_2MHz GPIO_Speed_Level_1 /*!< I/O output speed: Low 2 MHz */
1 B) Y* J% |" b - #define GPIO_Speed_10MHz GPIO_Speed_Level_2 /*!< I/O output speed: Medium 10 MHz */
# ^! f; F& _5 g0 @ - #define GPIO_Speed_50MHz GPIO_Speed_Level_3 /*!< I/O output speed: High 50 MHz */
复制代码 ) `. e+ g8 G7 p! M* I0 k
例如A9、A10都为50MHz: 0 M' m& |, p4 }0 P T* I# z
/ w8 o8 _( H; |$ E N% B4 X- GPIOA->OSPEEDR |= (0x0000000F << (9 * 2));
复制代码 & |/ A6 A% r! e6 b
2.2 配置输入输出(MODER)
, _1 o C: S1 p. ~4 a" b( V9 H& S5 o. v/ d. b1 v6 c
+ e5 \0 y/ z+ a, |, N9 Q0 @6 L
* P% `2 X4 @7 @& H4 Y* q# w每2个位配置一个Pin。 默认Input(除了SWD的A13,A14)
% ]3 q+ {# E* Q! g! r+ B0 d0 C/ t3 K* Y8 \( N8 z* n
0b00: Input
: q- ?! M1 k# _
$ u g0 f7 Q: \ S! H5 V0b01: Output
X, ?2 g' q% b& y- Q" R" N! c X
+ c3 ]" l; S+ v9 x# w0b10: AF
8 G! p3 ^7 c2 t
7 t. N, O' C5 l$ f4 U0b11: Analog In/Out
7 s1 J. M! a; _" v* A7 P1 U
. K8 v5 R0 A4 s* z- typedef enum0 T2 d G' }) Z. J5 W7 y0 J
- {: G* n* X3 c6 C0 s6 T/ G' N. F$ Y
- GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */ n; l0 l! J4 z+ |) u" P9 c: ?
- GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */7 N! E5 J' |3 `# i
- GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */- C2 v- ]: e* h
- GPIO_Mode_AN = 0x03 /*!< GPIO Analog In/Out Mode */* L& n# R7 Y* |2 C9 s0 b
- }GPIOMode_TypeDef;
复制代码
* k3 L. y4 k+ a2 Y4 l% u) V% W7 g' o例如GPIOA9,GPIOA10为AF:
: ? Z4 i8 m: K4 m: ?3 ~- GPIOA->MODER |= ((uint32_t)GPIO_Mode_AF << (9 * 2)) | ((uint32_t)GPIO_Mode_AF << (10 * 2));
复制代码 1 b& J! p! j- w2 C/ S- d
2.3 配置输出模式(OTYPER)
`1 `5 M& E" V! y' q# P+ s2 w: f5 p6 B: O
) }' Y! R9 }2 B* v1 q$ u+ g& _( l
0 H* Z( a- E! X" x每个bit表示输出模式,
' Z# L4 O+ ?9 i! J* p7 F8 Z7 A# n" Z( f0 z9 `0 j$ ?9 R% D
0b0: PP模式; x& R. F) f5 W3 m
, j' @- p6 ^5 Q0b1: OD模式。 , J( q( T0 m& |5 T1 m3 t+ M
& ^" M' m. z# q2 ~
- typedef enum
. t) f3 J; X# [8 C- E1 v - {
2 u5 v+ W' ?- f" F5 _% T - GPIO_OType_PP = 0x00,8 S2 \6 {" ^' {& O0 |
- GPIO_OType_OD = 0x01" r6 R7 I+ A9 i4 w$ a- I
- }GPIOOType_TypeDef;
复制代码
V. H& K& u! U$ ^7 @- ?5 ?- Y 例如:3 }) I( d5 |0 r! T% l5 |5 {5 \
- GPIOA->OTYPER |= (((uint32_t)GPIO_OType_PP << (9 * 1))
5 D6 ?# T' E+ e5 H' }3 X - | ((uint32_t)GPIO_OType_PP << 10 * 1))
复制代码
% ?1 M( b3 B1 w/ L9 o& i4 S2.4 配置上下拉模式(PUPDR)
& u% l' P; X5 A' N* @: e5 k8 B; {& q4 |9 u( Q
4 ]% x1 [4 \8 P4 D* I' k
; }% z; Y, c) l& j/ K' G. z每2个位表示上下拉模式。6 t6 S$ D( o& z
- typedef enum
8 I t: A% u3 {( p) R p - {
/ A0 O' L/ |. T/ j ~* w/ r2 A( ~( G - GPIO_PuPd_NOPULL = 0x00,# }$ h7 `7 f4 a P
- GPIO_PuPd_UP = 0x01,8 {" V; \; w# T- r
- GPIO_PuPd_DOWN = 0x02
+ s! s7 D0 X% c" o6 C6 X - }GPIOPuPd_TypeDef;
复制代码 8 E* ~' f! G" |, C* f9 C
例如:& `. z1 F/ p6 \3 k
- GPIOA->PUPDR &= ~((0x00000003 << (9 * 2)) | (0x00000003 << (10 * 2)));
复制代码
4 U( a, k' }8 Y2 ?" x3. 输出
a9 T1 o; a5 X1 _+ z s" g输出电平通过寄存器BSRR(输出高电平和低电平)和BRR(输出低电平)实现,写入1表示对应操作,写入0无效。例如:
0 s- C" ~( p& J) z, P
& `) O2 X7 n0 q' {+ {1 y. s! x- #define SDA_HIGH(n) IO_I2CIO_SDA->BSRR = ((uint32_t)1 << PIN_I2CIO_SDA) $ }; ]; S% T4 ?9 W) `2 f5 t/ n% D
- #define SDA_LOW(n) IO_I2CIO_SDA->BRR = ((uint32_t)1 << PIN_I2CIO_SDA)
复制代码 3 m$ G" F% ^ ?. i1 _4 c
BSRR的低16位分别对应16个PIN的输出高电平操作,高16为对应输出低电平操作。6 D$ @ G2 A' q3 E
8 u% d2 @$ m u6 x _5 J9 I. c- G
而BRR只有低16位有效,对应对应输出低电平操作。: P( ^* V/ |" S2 \. U2 H
& X1 X/ x5 }# x# p
8bit总线输出! w5 J4 j. P6 i, B' i7 _
7 [. x! z5 \! n% L
- #define I8080_D8_OUT(dat) IO_I8080_D8->BSRR = (dat & 0xff) | ((uint32)((~dat) & 0xff) << 16)
复制代码 4. 读入IO
' l% V) L6 G& i5 P* |$ [- l通过寄存器IDR读出对应I/O口的状态。低16位有效。
+ ^, U) y) X# @9 d4 T
$ h* {; X: e2 c# u& h" }- #define SDA_READ(n) (IO_I2CIO_SDA->IDR & ((uint32_t)1 << PIN_I2CIO_SDA))
复制代码
, O/ A$ H7 C8 D% F+ x* \
9 {' P6 i8 t! Y$ r$ t _! k `
7 V2 W: u8 i+ N; X% n |