你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32学习笔记05—GPIO输入输出实验

[复制链接]
STMCU-管管 发布时间:2020-10-27 14:55
STM32学习笔记05—GPIO输入输出实验

, T5 i/ J9 j8 z, M) z
/ d( i, Y7 N$ c. r, ?! k8 |4 a- D) q
5.1 STM32单片机GPIO概述
/ j) Q  s! b' q2 |' l4 |2 A& w       STM32中每个IO口都有很多个作用,比如这次我们使用的STM32F103ZET6的PA0口,既可以作为IO口使用,还可以作为待机唤醒(WAKEUP),模拟输入(ADC功能)等。根据数据手册中列出的每个I/O端口的特定硬件特征,GPIO端口的每个位可以由软件分别配置成多种模式。: y- [( C. B5 [( V8 U, c" i3 U
4 B: `8 N6 |  U7 n. t3 z
3 M3 _: F+ \) a( w4 s9 F
(1)输入浮空
- ?6 z% T* n; v% R3 s6 S(2)输入上拉: f  R2 O8 G0 D( ^0 t
(3)输入下拉1 e" a- |/ H) x2 P& f/ T
(4)模拟输入
- o5 w2 k1 V3 J5 a& c8 W$ w(5)开漏输出2 M. t8 K$ M& p  _
(6)推挽式输出
- {7 E1 @. @  U) W(7)推挽式复用功能
9 `0 ^6 }2 z# I- r(8)开漏复用功能
' n- i" }0 V% @) A4 U- a. h2 S4 y3 A7 U  w7 f4 p  m% \
' ^+ r; ~5 k6 Q! [6 t
       每个I/O端口位可以自由编程,然而I/O端口寄存器必须按32位字被访问(不允许半字或字节访问)。GPIOx_BSRR和GPIOx_BRR寄存器允许对任何GPIO寄存器的读/更改的独立访问;这样,在读和更改访问之间产生IRQ时不会产生异常错误。; _# j9 G( M/ l8 q! V2 @

2 I7 Z3 ^& j1 M3 u9 s
# ~# k$ U* J7 W% z0 X% B% K
STM32F103系列的基本IO口结构如下图所示2 [" t" ?" t9 H( x
1.png
% j% q. `3 u% C1 c2 E, X

$ ^! Q6 p0 {. H! I% A1 z$ t# ]7 `" C8 @
/ W* v; L# ^) o
从结构图可以看出来,STM32的GPIO口可以配置好几个选项,内部上拉下拉电阻的选择,推挽输出或者开漏输出,对于复用功能,有专门的复用输入支路和输出支路。STM32F103的端口由10个寄存器控制,但是常用的并不多,时钟控制寄存器APB2ENR,模式控制寄存器CRH和CRL,输入寄存器IDR,输出寄存器ODR。
# b) L2 e! p) q) h7 Z+ f
& a1 H( z( t1 V' f0 S, G! I# O! ]+ G

, F( }' g1 H9 m' y5.2 相关寄存器
- z( u2 J) W& H) H5.2.1 APB2 外设时钟使能寄存器:RCC_APB2ENR0 ?+ o  n/ c7 ?2 j
2.png & ]1 ~3 }% I; `
Bit 14:串口1时钟使能(写1开启,写0关闭)/ ]# k- S" @5 b9 s- V' i$ K
Bit 12:SPI1时钟使能(写1开启,写0关闭)3 K; j6 ^/ Y. ]" C$ ]
Bit 11:定时器1时钟使能(写1开启,写0关闭)4 L( k  C$ Z) q0 @/ r/ ~, h6 r
Bit 10:ADC2时钟使能(写1开启,写0关闭)
4 W) e/ e+ f4 c: |5 P5 \6 k7 xBit 9:ADC1时钟使能(写1开启,写0关闭)+ D- H  ^" f' E4 S) |2 m( s
Bit 6:GPIOE时钟使能(写1开启,写0关闭)
! M4 Z7 G- X  ~, R) x+ |Bit 5:GPIOD时钟使能(写1开启,写0关闭)! ?: l9 B! H  E7 I5 B# a
Bit 4:GPIOC时钟使能(写1开启,写0关闭)
) |, U/ t; D- @4 j0 J  ABit 3:GPIOB时钟使能(写1开启,写0关闭)
0 K  K3 a( c. u& H, \$ kBit 2:GPIOA时钟使能(写1开启,写0关闭)5 g7 J9 n$ H9 a; E. K5 S
Bit 0:辅助时钟IO时钟使能(写1开启,写0关闭)
7 P' E; ~3 k( n5 H
* [8 j- o0 \& Q
: L' \* `4 Y. W7 w4 }: M8 {  G

4 \. u5 f8 B) i* K5.2.2 端口配置低寄存器:GPIOx_CRL(x=A..E)
! X& l0 v5 E* |6 d1 U 3.png
+ }2 j4 \! P  a6 \9 @端口配置表:0 E- ^2 O5 R3 A9 i6 {% n
4.png
( s: \8 j0 H6 s& G8 Y) ~! C5.2.3 端口配置高寄存器:GPIOx_CRH(x=A..E)
: E* ^3 ~5 L7 p2 G% ?  |+ P 5.png & s  ]/ H1 M5 `# {: I
配置方式和端口配置低寄存器一致。! p0 M3 e7 }( @! J

0 Z  q/ l3 u$ a* o

9 t- g! G) \. Z0 s; \* H4 L2 j; }: a) T
5.2.4 端口输入数据寄存器:GPIOx_IDR(x=A..E)
+ a" B, M$ T, B$ c# n3 g: Z 6.png   q  v# G. ^% Z6 A' K" m
Bit 15~Bit 0:端口输入数据(这些位属于只读并只能以字的形式读出)
, I: H; u# B0 T- X) @
( n2 G3 l, A/ @" `
" R6 j2 t* ?2 v, m% ]4 W

3 A+ q2 _( h5 r: j% S4 x5.2.5 端口输出数据寄存器:GPIOx_ODR(x=A..E)* w: }( t$ Q2 h8 W& _
7.png
+ T. Q1 v+ h5 x  VBit 15~Bit 0:端口输出数据(这些位属于只读并只能以字的形式操作)
1 I0 {: b( G$ C- T注:在输入模式下,ODR的数据可以控制端口内部是上拉还是下拉,写入1意味着端口上拉输入。9 O# [; w2 m; m# d& B
8 Z" D2 b* M% Q- L
; h8 L9 C6 T( v0 K( l
5.3 GPIO的输入与输出例程
( p' r+ S3 ]! w* ]: F       我们现在在PA0端口接一个按键,PA端口接一个LED,当按下按键的时候,LED以100ms亮,100ms灭,抬起按键后LED常亮。1 t- T1 j( i2 N, I/ Q

3 j2 Y3 ], S" R" c; ~; _* H
( t2 J& e, N- d/ \) x

. u9 Y7 ?% |/ h  `$ Y# h(1)在stm32f103x.h文件中添加GPIO的结构体和地址映射。
6 g3 K  O' j1 o 8.png
. F. }2 b2 P$ V; z. m& h$ a(2)在HEADERWARE目录下创建GPIO文件夹,并创建gpio.c和gpio.h两个文件1 l0 E  }" O$ I* [+ n$ S
9.png
0 {6 o( _/ M: @) K(3)在gpio.h文件中输入以下内容:" T# P8 K8 v! V( _  r  B
10.png ( i3 N0 A4 \3 u: U6 m6 W& |$ B
(4)在gpio.c文件中输入以下内容
; }& B/ a. p9 j! F/ y 11.png 4 x- g! M' }3 C5 W5 ^2 z6 @
(5)将gpio.c文件和gpio.h文件添加进项目
2 |& |4 e: d1 f! e( t% A 12.png
/ b( i/ p4 s: u6 d+ F(6)在1.c文件中输入以下内容:
0 j% R/ K5 @7 k# X- G 13.png
* g+ ?# Z+ I! O6 p  D$ R( L3 I8 M       注:实验中,按键一端接GND,LED一端接VCC,所以按键是检测到0代表按下,端口输出低电平代表LED点亮。
& b! w2 l! s% P1 N" X! \2 e; _7 ?8 E7 T

$ A) ~. i' T# t) V) V0 v8 {5.4 CM3内核的位带操作1 B6 b) n& |8 Z) B) K2 X$ w" c
       Cortex-M3内核中有一个非常有用的功能,叫做位带操作,支持了位带操作以后,可以使用普通的加载/存储指令来对单一的比特进行读写。在CM3中,有两个区中实现了位带。其中一个是SRAM区的最低1MB范围,第二个则是片内外设区的最低1MB范围。这两个区中的地址除了可以像普通的RAM一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个32位的字。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的。下图从另一个侧面演示比特的膨胀对应关系。
2 r% o4 C( T: K" E1 K. l7 j 14.png
8 \) P# S& ^' w" p# @7 ^欲设置地址0x20000000中的比特2,则使用位带操作的设置过程如下图所示。
' ~+ L; t. e) [7 ~8 j 15.png + x4 L  N3 G" b- o2 o& y# q
    30年前其实就已经有位带操作的概念了,自8051单片机开始,到现在的CM3内核,位带操作有什么优越性呢?最容易想到的就是通过GPIO的管脚来单独控制每盏LED的点亮与熄灭。另一方面,也对操作串行接口器件提供了很大的方便(典型如74HC165,CD4094)。位带操作使代码更简洁,这只是位带操作优越性的初等体现,位带操作还有一个重要的好处是在务中,用于实现共享资源在任务间的“互锁”访问。多任务的共享资源必须满足一次只有一个任务访问它——亦即所谓的“原子操作”。, A/ j2 N* S0 g" Q1 q; Z
  j  W4 t! g4 h2 T$ \) H
' I9 r9 A& `% W& ~
5.5 利用位带操作实现GPIO的输入与输出
  t4 H0 v" h. f9 R; D  v9 x7 n现在利用位带操作来实现上一题目中的功能。
8 I3 ~/ x0 J. n& o1 h# t: y0 `9 o7 ]+ T) g9 s5 L% I. i& D

% Q5 F+ s# T( n. r9 G(1)在sys.h文件中添加实现位带操作的代码。
1 f( ]$ M% l( `* u% p& O 16.png $ W; G0 Q8 ^5 [1 |5 z1 o+ T3 A
(2)修改gpio.h中的代码如下图所示。; C: Y3 S* [; B. }
17.png 3 N, z6 b" m, \
(3)修改gpio.c中的代码如下图所示。  l) O2 }( |8 ~: G4 H' |
18.png
+ Q% w5 j7 E3 U: Y5 }! ~8 P(4)修改1.c中的代码如下图所示。
1 Y* x9 r. @; i+ R 19.png
3 s5 e0 I8 s& X" T9 X5.6 外部中断的实现
0 ]: z# w' R- \; Z* P) T, u    关于STM32F103的中断机制在之前已经详细讲述过,现在利用外部中断来实现上一题目的功能。
* w! N8 ]- {7 a6 O
- |  g1 [- C6 V8 v1 V0 g6 s
" w! B: b: K6 T! J
(1)修改gpio.c中的代码如下图所示。
% L3 h; g% A5 d 20.png 3 I! f2 W) t* b2 M
(2)添加代码到文件stm32f103.h中。' Y1 l4 W. E0 G) L2 {0 _
21.png 3 J5 ^/ m% {( G  _
(3)修改1.c中的代码如下图所示。
- ]6 `; W& q; r: E# d  I8 E$ l$ M6 ^% \
6 {6 I. N% ^! o# u0 A; r 22.png
- q7 M1 `9 s7 l; G! F& P
9 s7 C! C/ I/ f9 s: r& r上一篇:1 y* Q6 J$ X# T" I
STM32学习笔记04—SysTick时钟
/ V% F7 x$ j: L4 `; H2 X! a: |3 q( f
) p* T, f( M3 `/ T  R; G
收藏 2 评论0 发布时间:2020-10-27 14:55

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版