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

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

[复制链接]
STMCU小助手 发布时间:2020-12-22 09:58
STM32初学笔记(三)单个GPIO引脚操作
3 @7 ^% x& E  Y; S( z
搭建完成项目框架后,来实现一个基本的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& y# `/ q' r/ U: d
  2.   //2、设置引脚输出一个高电平
    9 K! F/ M1 m6 b  f3 H" }
  3.   GPIOA->CRL = 0X03;
    " a: e3 r% G9 C7 `
  4.   GPIOA->ODR = 0X01;
    5 U5 Z5 u6 V0 t6 V) ~/ T
  5.   5 ~" z% G( s5 F
  6.   //1、设置GPIOA.8的工作模式,推挽输出最大50MHz
    1 H- D# o* ^, O$ ^5 d
  7.   //2、设置引脚输出一个高电平
    ) P# ^- V" M7 l& d% @
  8.   GPIOA->CRH = 0X03;
    * N* P& {# j& j. _) N( T( T: s
  9.   GPIOA->ODR = 0X10;
复制代码

  P6 D1 @6 A, P: B* Z
2、通过位操作寄存器
第1部分的操作,看似只对一位进行了设置,但是事实上对整个寄存器进行了操作,GPIOA端口的其他引脚的输出也会被改变。若要不改变其他的引脚输出,需要对寄存器当前值进行逻辑运算后再写入寄存器。
STM32的GPIO端口还提供了专门的位操作寄存器,端口位设置/复位寄存器(GPIOx_BSRR)和端口位复位寄存器(GPIOx_BRR),每一位对应一个引脚,1表示对该位进行操作,0表示不造作,不改变对应位的当前值。
  1.   //1、设置GPIOA.0的工作模式,推挽输出最大50MHz& a( w  L: h; c1 Z1 y" S
  2.   //2、设置引脚输出一个高电平
    $ b# o! O6 t8 ]1 ?
  3.   GPIOA->CRL = 0X03;# `# s/ {+ I# t
  4.   GPIOA->BSRR = 0X01;
复制代码
- z; h& ^3 G5 A' M0 Z" q3 R
3、通过库函数操作
调用库函数需要根据库函数手册了解函数的功能和参数,可以通过网络搜索下载固件库手册。
用到引脚的初始化函数,参数为引脚名称(如GPIOA)和初始化结构体;用到读输入数据函数、置位函数和复位函数。熟悉C语言的话,程序理解起来会很容易,未涉及任何计算。即使不了解硬件,从函数名和赋值的参数也能够大概理解每一句的含义,如果对硬件有基本的了解,那么理解的会更好。
相比于前两种方法来说,调用库函数省却了很多基础的运算,编写的代码经过长时间以后仍然能够很快看懂,其他人编写的代码也很容易读懂,便于借鉴交流。初学者会觉得函数太多,在了解硬件的知识以外,还得了解很多函数,很繁琐,很混乱;但学习库函数是一个磨刀不误砍柴工的事情,对于项目开发和维护非常方便。
  1. int main(void)' r/ a9 {8 U4 \; g3 I) s  r* j8 C1 k
  2. {: T9 S& x: S% O) A
  3.   //初始化端口,参数是一个结构体数据$ `6 e" _4 A0 v( O# H/ K% k
  4.   //GPIOA的低8位设置为推挽输出,高8位设置为浮空输入
    - Q3 v# U1 h. x+ J7 s" {0 @% a# G
  5.   //设置多个引脚时,使用或运算对各个引脚同时初始化
    5 g) T$ @4 B/ t0 z3 U( R6 ~/ R
  6.   GPIO_InitTypeDef GPIOAstruct1;
    $ Y* Z: J! p/ J% c) h
  7.   GPIO_InitTypeDef GPIOAstruct2;
    : ], V) R% d% t# u' _, ^' A4 B
  8.   / d: L9 p# k& _8 ], E
  9.   GPIOAstruct1.GPIO_Mode = GPIO_Mode_Out_PP;1 Q5 s( V- x4 Z  V  G( l" t; A
  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;
    " \+ E$ ^2 X, c! Q; }- h1 ~6 `: [
  11.   GPIOAstruct1.GPIO_Speed = GPIO_Speed_50MHz;& X2 X% j* e$ ]6 p/ R' `/ @
  12.   GPIO_Init(GPIOA, &GPIOAstruct1);
    + p- h8 W: g- k8 A, ~7 ~/ N
  13.   
    1 j) T  C) e0 v6 I, E1 a
  14.   GPIOAstruct2.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    3 A# e  o8 g8 N" y+ q  I5 h& Z) I
  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;& `8 ?0 U+ B. e& |$ k$ f
  16.   GPIOAstruct2.GPIO_Speed = GPIO_Speed_50MHz;/ [8 x6 J1 [0 Q$ P- @. G  \0 [; L7 j
  17.   GPIO_Init(GPIOA, &GPIOAstruct2);
    3 A- N: Y4 R5 o. Y

  18. 5 k, U2 ~5 O3 W& v0 E
  19.   /*
    % Y' S' L# g/ S7 s
  20.   实现一个简单的功能,读取高8位引脚的值,对相应的低8位(0-8,1-9,...)进行置位1和复位0操作. w/ J: v/ P8 g* P- A" o  [
  21.   使对应引脚电平相同% P8 ~, |' Q+ G8 c0 t1 N$ X. @
  22.   */* K: {% d* q( c& g
  23.   while (1)' m6 D6 x, x2 U1 ]4 W
  24.   {0 ]& r# i  d' }% J* U; O
  25. ' c# N/ U( f0 `2 U5 R+ D
  26.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_0);/ v1 a% u3 R  i4 f
  27.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_0);' s4 T8 ?" u& V2 ]6 J/ E/ f3 R
  28.    
    0 D  G) O& l3 K; x8 |  M6 x
  29.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_1);
    ' \, M! P2 S) ]( p' `0 C+ a8 ]
  30.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_1);) i0 d3 l3 c7 a) x
  31.       i6 I% ?' q2 K+ {) S$ ?* \& s9 g
  32.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_2);
    8 D. N7 F, G. d6 L2 D% W: q  e- f
  33.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_2);7 t! E8 h1 K" n( w$ K
  34.    
    - i: N7 V1 k  d$ Q: o" N; m& A- I
  35.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_3);- o5 [( x# `9 ^- m3 \  a6 \* ~; o
  36.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_3);
    3 T) w3 K7 J& ]( k# h
  37.     % l0 G. F% h: E! j9 K: Y
  38.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_4);
    % j# K& E' D8 r( m9 k
  39.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_4);- P+ \2 p% T4 U( @
  40.    
    8 g' G# M1 [2 j5 W
  41.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_5);
    : P$ {' C( s) y% [  \  ?! x- Y
  42.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_5);
    . I  w/ e8 T4 M' x+ {3 d
  43.    
    7 Z" [* b5 v8 R0 F
  44.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_6);4 h: x  o1 @  s4 ~
  45.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_6);9 T+ C+ g7 p  U  F
  46.     8 }- U5 U/ `8 \+ l; d* a
  47.     if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15) == 1)   GPIO_SetBits(GPIOA, GPIO_Pin_7);
    1 C1 G( s: _8 A. o6 R* z. ]
  48.     else   GPIO_ResetBits(GPIOA,GPIO_Pin_7);5 B  V# }2 G; [- k% O5 V8 p( ~/ u
  49.     1 ^* W1 H0 l" p6 E
  50.   }
    / t, q/ x0 \2 @/ e
  51.   : c) W4 |/ ^9 P2 e
  52.   return 0;
    . d6 L8 C0 z$ r" f
  53. }<span style="background-color: rgb(255, 255, 255);"> </span>
复制代码
! [4 k) ~- w4 s
文章出处:樊学谦  机械智者

# j) c( W# C. B* T/ ^
收藏 评论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 手机版