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

STM32初学笔记(三)单个GPIO引脚操作

[复制链接]
STMCU小助手 发布时间:2020-12-22 09:58
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.   //1、设置GPIOA.0的工作模式,推挽输出最大50MHz: G: a8 g$ ^5 i$ ?, C! T: ?# d
  2.   //2、设置引脚输出一个高电平6 h# x2 I# c& T7 b+ v: a
  3.   GPIOA->CRL = 0X03;0 }* c2 J3 h+ Z: v- ~
  4.   GPIOA->ODR = 0X01;% N. c& E: l. n7 R
  5.   1 G# `' e0 ~$ o; k* {  F
  6.   //1、设置GPIOA.8的工作模式,推挽输出最大50MHz
    1 Q; b, D( A" {& b1 O) g4 r
  7.   //2、设置引脚输出一个高电平, @: Y3 K; z) S+ A" V
  8.   GPIOA->CRH = 0X03;
    # K0 ^* h2 M& A2 }0 x. ^
  9.   GPIOA->ODR = 0X10;
复制代码

! k/ `2 A/ q8 @* I4 f
2、通过位操作寄存器
第1部分的操作,看似只对一位进行了设置,但是事实上对整个寄存器进行了操作,GPIOA端口的其他引脚的输出也会被改变。若要不改变其他的引脚输出,需要对寄存器当前值进行逻辑运算后再写入寄存器。
STM32的GPIO端口还提供了专门的位操作寄存器,端口位设置/复位寄存器(GPIOx_BSRR)和端口位复位寄存器(GPIOx_BRR),每一位对应一个引脚,1表示对该位进行操作,0表示不造作,不改变对应位的当前值。
  1.   //1、设置GPIOA.0的工作模式,推挽输出最大50MHz$ W" J5 a* M- i+ c( S7 V) o$ E' z
  2.   //2、设置引脚输出一个高电平: e5 O+ R# J* Y+ o. S- b
  3.   GPIOA->CRL = 0X03;
    4 ?) d- [. g% y9 t' z; ^
  4.   GPIOA->BSRR = 0X01;
复制代码
0 P# V" f: J/ T
3、通过库函数操作
调用库函数需要根据库函数手册了解函数的功能和参数,可以通过网络搜索下载固件库手册。
用到引脚的初始化函数,参数为引脚名称(如GPIOA)和初始化结构体;用到读输入数据函数、置位函数和复位函数。熟悉C语言的话,程序理解起来会很容易,未涉及任何计算。即使不了解硬件,从函数名和赋值的参数也能够大概理解每一句的含义,如果对硬件有基本的了解,那么理解的会更好。
相比于前两种方法来说,调用库函数省却了很多基础的运算,编写的代码经过长时间以后仍然能够很快看懂,其他人编写的代码也很容易读懂,便于借鉴交流。初学者会觉得函数太多,在了解硬件的知识以外,还得了解很多函数,很繁琐,很混乱;但学习库函数是一个磨刀不误砍柴工的事情,对于项目开发和维护非常方便。
  1. int main(void)
    7 `$ s2 ^$ \( p; h* H
  2. {
    0 L" b0 ~! A* M3 ?' g
  3.   //初始化端口,参数是一个结构体数据; r5 B: W2 ]' p& n
  4.   //GPIOA的低8位设置为推挽输出,高8位设置为浮空输入
    ( q. q; S( @( S' \$ H
  5.   //设置多个引脚时,使用或运算对各个引脚同时初始化
    . b7 A; w( D6 t% y7 W- Z
  6.   GPIO_InitTypeDef GPIOAstruct1;) E+ H4 e  \+ @  g8 d
  7.   GPIO_InitTypeDef GPIOAstruct2;4 W! @8 ]9 V2 Q. @' L, l( |
  8.   
    , E  J( }: [( o* U- B( _
  9.   GPIOAstruct1.GPIO_Mode = GPIO_Mode_Out_PP;
    ; F0 s8 I4 S" ?7 Q; J3 E6 @
  10.   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
  11.   GPIOAstruct1.GPIO_Speed = GPIO_Speed_50MHz;% {4 F, t8 |7 ~9 B  o  w
  12.   GPIO_Init(GPIOA, &GPIOAstruct1);
    2 c- S' s( o% D# U/ M0 E" ^
  13.   4 b/ U, h7 K2 ~1 |6 _' m. H, R
  14.   GPIOAstruct2.GPIO_Mode = GPIO_Mode_IN_FLOATING;* _3 L* I- S; h4 Q0 o
  15.   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
  16.   GPIOAstruct2.GPIO_Speed = GPIO_Speed_50MHz;
    % l- K+ M/ Z# L8 A- B- {
  17.   GPIO_Init(GPIOA, &GPIOAstruct2);
    3 V3 r9 G# u5 @' ^

  18.   J7 Z3 Z* |  e3 ?$ n
  19.   /*
    , S2 q0 Y6 J/ A3 K* f4 l
  20.   实现一个简单的功能,读取高8位引脚的值,对相应的低8位(0-8,1-9,...)进行置位1和复位0操作
    0 b% g# A1 ]# \( z! A. ?
  21.   使对应引脚电平相同
    / P; z2 s; t. J% W1 |! ?* A7 z* T0 \
  22.   */7 y& b: ^; Y* Z
  23.   while (1)
    & r; [8 r, \% m9 z: x
  24.   {
    + ~; g% p; \# h8 T

  25. , Y( u& z: n6 [9 p2 m5 Z
  26.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_0);; W  ~7 s5 Z$ O- b/ y5 j) _
  27.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_0);4 F3 i+ h: u/ A% P) u
  28.     $ e% E2 ~8 C7 j& k  P
  29.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_1);
    5 ^" ?: U4 Y$ C- q% Y
  30.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_1);
    ! e1 I4 b: W5 C# ^- |
  31.    
    0 H2 E5 Z) ]6 D. F
  32.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_2);
    3 I$ _) E3 n4 E* H5 w
  33.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_2);* @3 L& V5 l( Q/ R  e& m
  34.    
    2 d! n5 j# I- T, b9 k, @$ C
  35.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_3);
    " E: V6 `3 B" F$ B$ E. `  R1 ]
  36.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_3);
    6 y) i5 l& R9 I( l; q
  37.     ) U8 N' ]1 L. a
  38.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_4);
    , }+ c) j/ m/ y0 ~+ A
  39.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_4);
    + B7 o7 c9 S+ Z6 o2 q
  40.     , s3 s3 }$ U$ T
  41.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_5);
      n; _0 r) s% N/ p* M
  42.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_5);4 s# d# G4 Y! X
  43.     * o6 J! g  o1 B3 [! E
  44.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_6);. z6 ]) v$ T) ?2 A$ \. h# s3 n
  45.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_6);
    ( o3 I, Z  j' T  w7 M+ O( T% h* k
  46.    
    ; H  [" R7 l- G& A! Q7 w
  47.     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
  48.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_7);3 ?. f) Z2 A. {
  49.    
    ! `, S, W' m3 V1 i) x
  50.   }
    ( r3 t1 f$ u& n. z+ D% g$ ?
  51.   
    & P) H. H; x5 m3 p" D
  52.   return 0;  B5 S! E; r* N# M4 m! G5 L
  53. }<span style="background-color: rgb(255, 255, 255);"> </span>
复制代码
+ Q* ~8 @& E: t& A# h
文章出处:樊学谦  机械智者
6 G" y4 x8 _2 U1 D
赞 收藏 评论1 发布时间:2020-12-22 09:58

举报

1个回答
kylixyao 回答时间:2020-12-22 15:01:49
支持
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版