|
STM32初学笔记(三)单个GPIO引脚操作 3 h1 o" y: c. \; J
搭建完成项目框架后,来实现一个基本的GPIO操作,使引脚输出高低电平。除了本篇文章提到的3种方法以外,STM32还可以使用一种叫做位绑定的方法,这里暂时不用。 嵌入式程序开发主要分为两大类:(1)直接操作寄存器;(2)调用库函数。直接操作寄存器,开发难度大、速度慢、程序不便于阅读和移植等,51单片机就是使用这种开发方式,本篇文章的前两个引脚操作方法也是这种方式;库函数开发方式是开发者调用封装好的库函数接口,不直接操作寄存器,上一篇中创建的工程项目就是基于标准库的。 本篇文章主要内容: 1、直接操作端口寄存器 2、通过位操作寄存器 3、通过库函数操作 1、直接操作端口寄存器 操作寄存器必须对STM32各个寄存器功能,需要仔细学习芯片的参考手册相关内容。 以STM32F103为例,它有5个GPIO端口为A、B、C、D、E,每个端口有2个控制寄存器端口配置低寄存器(GPIOx_CRL)和端口配置高寄存器(GPIOx_CRH),1个端口输入数据寄存器(GPIOx_IDR),1个端口输出数据寄存器(GPIOx_ODR),以及一些其他的寄存器。 操作GPIOA端口,共有16个引脚,每个引脚需要控制寄存器中的4位来控制工作模式,所以需要两个32位的控制寄存器。 - //1、设置GPIOA.0的工作模式,推挽输出最大50MHz: G: a8 g$ ^5 i$ ?, C! T: ?# d
- //2、设置引脚输出一个高电平6 h# x2 I# c& T7 b+ v: a
- GPIOA->CRL = 0X03;0 }* c2 J3 h+ Z: v- ~
- GPIOA->ODR = 0X01;% N. c& E: l. n7 R
- 1 G# `' e0 ~$ o; k* { F
- //1、设置GPIOA.8的工作模式,推挽输出最大50MHz
1 Q; b, D( A" {& b1 O) g4 r - //2、设置引脚输出一个高电平, @: Y3 K; z) S+ A" V
- GPIOA->CRH = 0X03;
# K0 ^* h2 M& A2 }0 x. ^ - GPIOA->ODR = 0X10;
复制代码
! k/ `2 A/ q8 @* I4 f2、通过位操作寄存器 第1部分的操作,看似只对一位进行了设置,但是事实上对整个寄存器进行了操作,GPIOA端口的其他引脚的输出也会被改变。若要不改变其他的引脚输出,需要对寄存器当前值进行逻辑运算后再写入寄存器。 STM32的GPIO端口还提供了专门的位操作寄存器,端口位设置/复位寄存器(GPIOx_BSRR)和端口位复位寄存器(GPIOx_BRR),每一位对应一个引脚,1表示对该位进行操作,0表示不造作,不改变对应位的当前值。 - //1、设置GPIOA.0的工作模式,推挽输出最大50MHz$ W" J5 a* M- i+ c( S7 V) o$ E' z
- //2、设置引脚输出一个高电平: e5 O+ R# J* Y+ o. S- b
- GPIOA->CRL = 0X03;
4 ?) d- [. g% y9 t' z; ^ - GPIOA->BSRR = 0X01;
复制代码 0 P# V" f: J/ T
3、通过库函数操作 调用库函数需要根据库函数手册了解函数的功能和参数,可以通过网络搜索下载固件库手册。 用到引脚的初始化函数,参数为引脚名称(如GPIOA)和初始化结构体;用到读输入数据函数、置位函数和复位函数。熟悉C语言的话,程序理解起来会很容易,未涉及任何计算。即使不了解硬件,从函数名和赋值的参数也能够大概理解每一句的含义,如果对硬件有基本的了解,那么理解的会更好。 相比于前两种方法来说,调用库函数省却了很多基础的运算,编写的代码经过长时间以后仍然能够很快看懂,其他人编写的代码也很容易读懂,便于借鉴交流。初学者会觉得函数太多,在了解硬件的知识以外,还得了解很多函数,很繁琐,很混乱;但学习库函数是一个磨刀不误砍柴工的事情,对于项目开发和维护非常方便。 - int main(void)
7 `$ s2 ^$ \( p; h* H - {
0 L" b0 ~! A* M3 ?' g - //初始化端口,参数是一个结构体数据; r5 B: W2 ]' p& n
- //GPIOA的低8位设置为推挽输出,高8位设置为浮空输入
( q. q; S( @( S' \$ H - //设置多个引脚时,使用或运算对各个引脚同时初始化
. b7 A; w( D6 t% y7 W- Z - GPIO_InitTypeDef GPIOAstruct1;) E+ H4 e \+ @ g8 d
- GPIO_InitTypeDef GPIOAstruct2;4 W! @8 ]9 V2 Q. @' L, l( |
-
, E J( }: [( o* U- B( _ - GPIOAstruct1.GPIO_Mode = GPIO_Mode_Out_PP;
; F0 s8 I4 S" ?7 Q; J3 E6 @ - GPIOAstruct1.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;+ X/ @/ d7 }% i: {" E5 W4 ]) D
- GPIOAstruct1.GPIO_Speed = GPIO_Speed_50MHz;% {4 F, t8 |7 ~9 B o w
- GPIO_Init(GPIOA, &GPIOAstruct1);
2 c- S' s( o% D# U/ M0 E" ^ - 4 b/ U, h7 K2 ~1 |6 _' m. H, R
- GPIOAstruct2.GPIO_Mode = GPIO_Mode_IN_FLOATING;* _3 L* I- S; h4 Q0 o
- GPIOAstruct2.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;! g9 G/ W3 j" y6 P1 C: x* h( k8 H; D
- GPIOAstruct2.GPIO_Speed = GPIO_Speed_50MHz;
% l- K+ M/ Z# L8 A- B- { - GPIO_Init(GPIOA, &GPIOAstruct2);
3 V3 r9 G# u5 @' ^
J7 Z3 Z* | e3 ?$ n- /*
, S2 q0 Y6 J/ A3 K* f4 l - 实现一个简单的功能,读取高8位引脚的值,对相应的低8位(0-8,1-9,...)进行置位1和复位0操作
0 b% g# A1 ]# \( z! A. ? - 使对应引脚电平相同
/ P; z2 s; t. J% W1 |! ?* A7 z* T0 \ - */7 y& b: ^; Y* Z
- while (1)
& r; [8 r, \% m9 z: x - {
+ ~; g% p; \# h8 T
, Y( u& z: n6 [9 p2 m5 Z- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_0);; W ~7 s5 Z$ O- b/ y5 j) _
- else GPIO_ResetBits(GPIOA,GPIO_Pin_0);4 F3 i+ h: u/ A% P) u
- $ e% E2 ~8 C7 j& k P
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_1);
5 ^" ?: U4 Y$ C- q% Y - else GPIO_ResetBits(GPIOA,GPIO_Pin_1);
! e1 I4 b: W5 C# ^- | -
0 H2 E5 Z) ]6 D. F - if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_2);
3 I$ _) E3 n4 E* H5 w - else GPIO_ResetBits(GPIOA,GPIO_Pin_2);* @3 L& V5 l( Q/ R e& m
-
2 d! n5 j# I- T, b9 k, @$ C - if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_3);
" E: V6 `3 B" F$ B$ E. ` R1 ] - else GPIO_ResetBits(GPIOA,GPIO_Pin_3);
6 y) i5 l& R9 I( l; q - ) U8 N' ]1 L. a
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_4);
, }+ c) j/ m/ y0 ~+ A - else GPIO_ResetBits(GPIOA,GPIO_Pin_4);
+ B7 o7 c9 S+ Z6 o2 q - , s3 s3 }$ U$ T
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_5);
n; _0 r) s% N/ p* M - else GPIO_ResetBits(GPIOA,GPIO_Pin_5);4 s# d# G4 Y! X
- * o6 J! g o1 B3 [! E
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_6);. z6 ]) v$ T) ?2 A$ \. h# s3 n
- else GPIO_ResetBits(GPIOA,GPIO_Pin_6);
( o3 I, Z j' T w7 M+ O( T% h* k -
; H [" R7 l- G& A! Q7 w - if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_7);
8 ^5 j. ~4 u5 Q# k3 O1 o5 I4 v - else GPIO_ResetBits(GPIOA,GPIO_Pin_7);3 ?. f) Z2 A. {
-
! `, S, W' m3 V1 i) x - }
( r3 t1 f$ u& n. z+ D% g$ ? -
& P) H. H; x5 m3 p" D - return 0; B5 S! E; r* N# M4 m! G5 L
- }<span style="background-color: rgb(255, 255, 255);"> </span>
复制代码 + Q* ~8 @& E: t& A# h
文章出处:樊学谦 机械智者 6 G" y4 x8 _2 U1 D
|