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

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

[复制链接]
STMCU小助手 发布时间:2020-12-22 09:58
STM32初学笔记(三)单个GPIO引脚操作

% Q( J8 D3 g% E' Y: A; F, {; 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
    # B4 u. [$ s& Q% U5 L) o8 d
  2.   //2、设置引脚输出一个高电平% J* q1 K4 W/ T0 o' j
  3.   GPIOA->CRL = 0X03;
    / o0 H: i9 [5 _
  4.   GPIOA->ODR = 0X01;
    9 `" x$ A$ C' N- |) ^
  5.   
    # {" P/ t. M) ^( D7 J, }
  6.   //1、设置GPIOA.8的工作模式,推挽输出最大50MHz3 _. h6 F6 a$ \- Z' Z# P
  7.   //2、设置引脚输出一个高电平
    6 o" u9 k' U3 g. C" u2 n
  8.   GPIOA->CRH = 0X03;
    " F/ ^5 r, k/ Y0 r1 E$ m0 P8 G
  9.   GPIOA->ODR = 0X10;
复制代码

: F. P+ }: i- C
2、通过位操作寄存器
第1部分的操作,看似只对一位进行了设置,但是事实上对整个寄存器进行了操作,GPIOA端口的其他引脚的输出也会被改变。若要不改变其他的引脚输出,需要对寄存器当前值进行逻辑运算后再写入寄存器。
STM32的GPIO端口还提供了专门的位操作寄存器,端口位设置/复位寄存器(GPIOx_BSRR)和端口位复位寄存器(GPIOx_BRR),每一位对应一个引脚,1表示对该位进行操作,0表示不造作,不改变对应位的当前值。
  1.   //1、设置GPIOA.0的工作模式,推挽输出最大50MHz
    5 E. `; {7 Y) \+ @
  2.   //2、设置引脚输出一个高电平
    ' i. J0 s/ J$ v, b5 z
  3.   GPIOA->CRL = 0X03;
      [/ T9 z. A. w/ V
  4.   GPIOA->BSRR = 0X01;
复制代码

( H6 C: ]7 Y% i
3、通过库函数操作
调用库函数需要根据库函数手册了解函数的功能和参数,可以通过网络搜索下载固件库手册。
用到引脚的初始化函数,参数为引脚名称(如GPIOA)和初始化结构体;用到读输入数据函数、置位函数和复位函数。熟悉C语言的话,程序理解起来会很容易,未涉及任何计算。即使不了解硬件,从函数名和赋值的参数也能够大概理解每一句的含义,如果对硬件有基本的了解,那么理解的会更好。
相比于前两种方法来说,调用库函数省却了很多基础的运算,编写的代码经过长时间以后仍然能够很快看懂,其他人编写的代码也很容易读懂,便于借鉴交流。初学者会觉得函数太多,在了解硬件的知识以外,还得了解很多函数,很繁琐,很混乱;但学习库函数是一个磨刀不误砍柴工的事情,对于项目开发和维护非常方便。
  1. int main(void)
    & Y( v  u$ |& }/ w& I. H
  2. {; b& P% ~8 ~9 O- k
  3.   //初始化端口,参数是一个结构体数据
    * x/ h/ K( \8 A" P9 l
  4.   //GPIOA的低8位设置为推挽输出,高8位设置为浮空输入
    + v8 `6 Q4 Y5 e
  5.   //设置多个引脚时,使用或运算对各个引脚同时初始化! n% M$ m) z* A5 J8 E7 I# v" ^
  6.   GPIO_InitTypeDef GPIOAstruct1;
    % g  b$ D: {' C7 g* u' j
  7.   GPIO_InitTypeDef GPIOAstruct2;8 K, [! G4 ?( [9 L8 a
  8.   $ I" z; L5 R. p
  9.   GPIOAstruct1.GPIO_Mode = GPIO_Mode_Out_PP;* r, K* B1 {/ J+ F  B
  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;  O$ ?" T$ O* c* C
  11.   GPIOAstruct1.GPIO_Speed = GPIO_Speed_50MHz;
    ) z- |( B2 B& ?1 @5 N- Q! e% A7 G0 T
  12.   GPIO_Init(GPIOA, &GPIOAstruct1);
    7 \4 p3 F; m+ J7 |7 a+ d
  13.   
    % U- l5 E' ^8 I- Z( F
  14.   GPIOAstruct2.GPIO_Mode = GPIO_Mode_IN_FLOATING;  k. c- s) u9 ^/ f  z
  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;% A, ^8 [, C. D& W9 h$ A4 j5 M( t
  16.   GPIOAstruct2.GPIO_Speed = GPIO_Speed_50MHz;$ g: s, F2 \2 S$ J) V- m
  17.   GPIO_Init(GPIOA, &GPIOAstruct2);
    & o0 B2 F# P. g8 R' t; c6 L

  18. 0 }( i1 C5 C! w& w9 S
  19.   /*9 M1 h! s- b. U+ L
  20.   实现一个简单的功能,读取高8位引脚的值,对相应的低8位(0-8,1-9,...)进行置位1和复位0操作
    ' _- i( H* L' O8 G
  21.   使对应引脚电平相同) R1 l. z6 K% k+ \5 M$ i
  22.   */4 R0 L' @+ D3 C
  23.   while (1)) ^& z, |0 |8 o0 y( P5 B
  24.   {! E0 Q; p- a+ z, H. L$ w2 H& p
  25. 5 b6 @" O; F) o
  26.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_0);% ]# i7 p5 O  A% ]
  27.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_0);, v$ [5 z2 p4 `$ d7 a7 ?
  28.    
    + Q; L& J5 M: f6 n) ^( H+ e0 q
  29.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_1);' n- |& j7 ]! `# g
  30.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_1);4 t! }: j. Z7 \# W
  31.     4 q3 n4 B( y) h' {2 _
  32.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_2);
    + I% e4 L6 P. p  m& r* t! n+ l
  33.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_2);
      C3 K8 e  O9 |: H" H
  34.     5 `3 q6 `, |% Z
  35.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_3);
    5 @7 }  g+ ]4 p* w8 V6 X2 R
  36.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_3);
    1 N2 u) ]. K* \# N9 m1 @
  37.     3 n" E% }/ E, B
  38.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_4);4 R4 h3 `2 e. k
  39.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_4);5 P# W! C8 p* ?0 N1 I
  40.     ( l# {' i! H$ q) }2 o9 F9 A
  41.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_5);
    8 `: k, K7 V$ t  p
  42.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_5);( t# r( J& y' x/ ~" F
  43.    
    9 [/ x! B  ^2 t" x, Y( w
  44.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_6);  ]' `3 D& A0 k6 C- \) @) J% A
  45.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_6);$ D! T+ Z  Y( x; R+ e1 v
  46.     0 P, S, X) p  D1 Z
  47.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_7);0 {: v+ `2 _& v- K
  48.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_7);
    ) s9 N2 g$ ?+ A( G$ N! N
  49.     + f, h& c; P' n0 |. O# c
  50.   }
    1 Q1 C; t% b5 x
  51.     t# e$ f/ p4 Q
  52.   return 0;  Z2 {9 m) E5 G5 W
  53. }<span style="background-color: rgb(255, 255, 255);"> </span>
复制代码
, G5 {) V- E6 x# f+ D: r$ a' m
文章出处:樊学谦  机械智者
- K( R" L; L* }( `8 v: f* |* [
收藏 评论1 发布时间:2020-12-22 09:58

举报

1个回答
kylixyao 回答时间:2020-12-22 15:01:49
支持

所属标签

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