找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 15284|回复: 13
打印 上一主题 下一主题
收起左侧

初学stm32,对GPIO的理解(非常详细的源码解释说明)

  [复制链接]
跳转到指定楼层
楼主


单片机源程序如下:

  1. #include "stm32f10x.h"   
  2. #include "gpio.h"

  3. //对于STM32  GPIO一般用法配置(这里不包括复用功能),以下的说明可以应用点亮灯多种方式
  4. void GPIO_Configure_GPIOA(void)
  5. {
  6.        
  7.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//设置时钟,针对GPIOA时钟使能
  8.         /*        为什么要设置时钟呢???
  9.         任何外设都需要时钟,51单片机,stm32,430等等,
  10.         因为寄存器是由D触发器组成的,往触发器里面写东西,前提条件是有时钟输入。
  11.         stm32之所以是低功耗,他将所有的门都默认设置为disable,在你需要用哪个门的时候,
  12.         开哪个门就可以,也就是说用到什么外设,只要打开对应外设的时钟就可以,
  13.         其他的没用到的可以还是disable,这样耗能就会减少。
  14.         stm32的时钟是有分工的,并且每类时钟的频率不一样,因为没必要所有的时钟都是最高频率,只要够用就行,
  15.         好比一个门出来水流大小,我只要洗脸,但是出来的是和洪水一样涌出来的水,那就gg了,消耗能源也多,
  16.         所以不同的时钟也会有频率差别,或者在配置的时候可以配置时钟分频。
  17.         */
  18.        
  19.        
  20.         GPIO_InitTypeDef GPIO_InitStructure;//GPIO设备的初始化函数
  21.          //GPIO_InitTypeDef是一个结构体类型同义字,其功能是定义一个结构体,
  22.         //该结构体有三个成员分别是 u16类型的GPIO_Pin、
  23. //        GPIOSpeed_TypeDef 类型的GPIO_Speed  和GPIOMode_TypeDef 类型的GPIO_Mode。即以下三种:
  24.        
  25.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//普通推挽输出
  26.         //GPIO有8种工作模式(4种输入模式和4种输出模式):
  27.         /*
  28.         4种输入模式:
  29.         上拉输入模式(GPIO_Mode_IPU)-->在默认状态下(GPIO引脚无输入),读取得的GPIO引脚
  30.         数据为1,高电平。
  31.        
  32.         而下拉输入模式(GPIO_Mode_IPD)则相反。在默认状态下(GPIO引脚无输入),读取得的GPIO引脚
  33.         数据为0,低电平。
  34.        
  35.         浮空输入模式(GPIO_Mode_IN_FLOATING)在芯片内部既没有接上拉,也没有接下拉电阻,
  36.         经由触发器输入。这种模式用于标准的通信协议如I2C、USART的接收端
  37.        
  38.         模拟输入模式(GPIO_Mode_AIN)则关闭了施密特触发器,不接上、下拉电阻,经由另一线路
  39.         把电压信号传送到片上外设模块。如传送至ADC模块,由ADC采集电压信号。所以使用ADC外设时,必须设置为模拟输入模式
  40.        
  41.         4种输出模式:
  42.         普通推挽输出(GPIO_Mode_Out_PP)一般应用在输出电平为0和3.3伏的场合
  43.        
  44.         普通开漏输出(GPIO_Mode_Out_OD)一般在电平不匹配的场合,如需要输出5伏的高电平,就需要在外部接一个
  45.         上拉电阻,电源为5伏,把GPIO设置为开漏模式,当输出高阻态时,由上拉电阻和电源向外输出5伏的电平
  46.        
  47.         复用推挽输出(GPIO_Mode_AF_PP),是根据GPIO的复用功能来选择的,如GPIO的引脚用作串口的输出,
  48.         则使用复用推挽输出模式。
  49.        
  50.         复用开漏输出(GPIO_Mode_AF_OD),同理,其用在IC、SMBUS这些需要线与功能的复用场合
  51.         在使用任何一种开漏模式时,都需要接上拉电阻。
  52.         */
  53.        
  54.        
  55.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//针对某组的一个引脚进行初始化
  56.         //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;//针对某组的两个引脚进行初始化
  57.         //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;//针对某组的16个引脚进行初始化
  58.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  59.         /*
  60.          又称输出驱动电路的响应速度:(芯片内部在I/O口的输出部分安排了多个响应速度不同的输出驱动电路,
  61.          用户可以根据自己的需要选择合适的驱动电路,通过选择速度来选择不同的输出驱动模块,
  62.          达到最佳的噪声控制和降低功耗的目的。)

  63.     可理解为: 输出驱动电路的带宽:即一个驱动电路可以不失真地通过信号的最大频率。

  64.         (如果一个信号的频率超过了驱动电路的响应速度,就有可能信号失真。失真因素?)

  65.         如果信号频率为10MHz,而你配置了2MHz的带宽,则10MHz的方波很可能就变成了正弦波。
  66.         就好比是公路的设计时速,汽车速度低于设计时速时,可以平稳地运行,
  67.         如果超过设计时速就会颠簸,甚至翻车。

  68.         关键是: GPIO的引脚速度跟应用相匹配,速度配置越高,噪声越大,功耗越大。

  69.         带宽速度高的驱动器耗电大、噪声也大,带宽低的驱动器耗电小、噪声也小。
  70.         使用合适的驱动器可以降低功耗和噪声

  71.         比如:高频的驱动电路,噪声也高,当不需要高的输出频率时,请选用低频驱动电路,
  72.         这样非常有利于提高系统的EMI性能。当然如果要输出较高频率的信号,
  73.         但却选用了较低频率的驱动模块,很可能会得到失真的输出信号。
  74.         关键是GPIO的引脚速度跟应用匹配(推荐10倍以上?)。
  75.         */
  76.         GPIO_Init(GPIOA,&GPIO_InitStructure);//进行GPIOA初始化
  77. }

  78. void Delay_ms(u16 ms)
  79. {
  80.         int i;
  81.         while(ms--)
  82.         {
  83.                 i = 12000;
  84.                 while(i--);
  85.         }
  86.                
  87. }

  88. void GPIO_Achieve(u8 n,u16 ms)
  89. {
  90. //        u8 Readoutbit;
  91. //        u16 Readoutdate;
  92.         if(n == 0)
  93.         {
  94.                 GPIO_ResetBits(GPIOA,GPIO_Pin_1);//设置PA0引脚为低电平,清除引脚位
  95.                 Delay_ms(ms);//不精准的延时函数,毫秒单位
  96.                
  97.                
  98.                 /*这是GPIO_ResetBits(GPIOx,GPIO_Pin)代码
  99.                 void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
  100.         {
  101.   //Check the parameters
  102.   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  103.   assert_param(IS_GPIO_PIN(GPIO_Pin));
  104.   GPIOx->BRR = GPIO_Pin;//位复位寄存器赋值(将某个引脚变为低电平)
  105.         }
  106.                 */
  107.                
  108.                
  109.                 //Readoutbit = GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_0);//将PA0引脚输出的值赋给Readoutbit
  110.                 //Readoutdate = GPIO_ReadOutputData(GPIOA);//将PA所有引脚输出的值赋给Readoutdate
  111.                
  112.                 //GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);//获取PA0引脚的值
  113.                 //GPIO_ReadInputData(GPIOA);//获取PA所有引脚的值
  114.                 //GPIO_WriteBit(GPIOA,GPIO_Pin_0,RESET);//将RESET值写入给PA0引脚(其实就是将PA0引脚置0)
  115.                 //GPIO_Write(GPIOA,0xffff);//将0xffff值写入PA端口(其实就是将PA所有引脚置1)
  116.         }
  117.         else
  118.         {
  119.                 GPIO_SetBits(GPIOA,GPIO_Pin_1);//设置PA0引脚为高电平,置位引脚
  120.                 Delay_ms(ms);
  121.                 /*
  122.                 void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
  123.         {
  124.    //Check the parameters
  125.                 assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  126.                 assert_param(IS_GPIO_PIN(GPIO_Pin));
  127.                 GPIOx->BSRR = GPIO_Pin;//位置位寄存器赋值(将某个引脚变为高电平)
  128.         }
  129.                 */       
  130.                 //Readoutbit = GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_0);
  131.                 //Readoutdate = GPIO_ReadOutputData(GPIOA,GPIO_Pin_0);
  132.         }
  133. }
  134. /*
  135. 注释:
  136. GPIOx->BSRR= GPIO_Pin;-----------位置位寄存器---这是单个引脚的
  137. GPIOx->BRR= GPIO_Pin;------------位复位寄存器---这是单个引脚的
  138. GPIOx-ODR= PortVal;--------------端口输出寄存器---这是16个引脚的
  139. GPIOx-IDR= PortVal;--------------端口输入寄存器---这是16个引脚的


  140. 对于GPIO来说,还有其他函数

  141. 以上,是我对GPIO的部分理解,有些可能理解不到位,请谅解(有些是从网上查找的)
  142. */
复制代码

所有资料51hei提供下载:
TEXT1.rar (707 KB, 下载次数: 110)


评分

参与人数 2黑币 +62 收起 理由
YJGG + 12 赞一个!
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏14 分享淘帖 顶2 踩
回复

使用道具 举报

来自 2#
ID:325058 发表于 2020-4-2 16:54 | 只看该作者
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//针对某组的一个引脚进行初始化
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;//针对某组的两个引脚进行初始化
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;//针对某组的16个引脚进行初始化
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
请教,后面两个是对全部16个引脚进行设置,还是只对选择的引脚进行设置?看.h文件一头零水,没有看明白。
回复

使用道具 举报

板凳
ID:349194 发表于 2018-10-18 22:23 | 只看该作者
优秀
回复

使用道具 举报

地板
ID:345396 发表于 2018-10-19 18:05 | 只看该作者
复用,映射
回复

使用道具 举报

5#
ID:346711 发表于 2019-4-17 13:15 | 只看该作者
优秀!!!!!!
回复

使用道具 举报

6#
ID:515970 发表于 2019-4-18 23:18 来自手机 | 只看该作者
可以,够详细
回复

使用道具 举报

7#
ID:554513 发表于 2019-6-4 11:22 | 只看该作者
学习了
回复

使用道具 举报

8#
ID:537887 发表于 2019-6-6 09:11 | 只看该作者
可以,很详细的说明
回复

使用道具 举报

9#
ID:325058 发表于 2020-4-2 16:49 | 只看该作者
本帖最后由 suinile 于 2020-4-7 15:18 编辑

同一个端口的不同引脚配置成不同的输出模式,比如:端口A的1脚输出配置成频率2M 推挽输出、2脚输出配置设置成频率10M 开漏输出。
GPIO_InitTypeDef   GPIO_INIT_GPIOA;         //端口参数配置
     GPIO_INIT_GPIOA.GPIO_Pin = GPIO_Pin_1;                          
     GPIO_INIT_GPIOA.GPIO_Mode = GPIO_Mode_Out_PP;
     GPIO_INIT_GPIOA.GPIO_Speed = GPIO_Speed_2MHz;

     GPIO_INIT_GPIOA.GPIO_Pin = GPIO_Pin_2;
     GPIO_INIT_GPIOA.GPIO_Mode = GPIO_Mode_Out_OD;
     GPIO_INIT_GPIOA.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_INIT_GPIOA);//端口配置初始化
这种写法的话,是不是1脚的输出配置被2脚的输出配置覆盖掉了??
回复

使用道具 举报

10#
ID:722576 发表于 2020-4-5 14:54 | 只看该作者
优秀,学习一下
回复

使用道具 举报

11#
ID:128463 发表于 2020-4-11 10:16 | 只看该作者

优秀,学习一下
回复

使用道具 举报

12#
ID:636987 发表于 2022-4-3 20:43 | 只看该作者
suinile 发表于 2020-4-2 16:49
同一个端口的不同引脚配置成不同的输出模式,比如:端口A的1脚输出配置成频率2M 推挽输出、2脚输出配置设置 ...

是的。相当于对参数进行了两次赋值,当然,最后一次保留,然后通过初始化函数把参数设置传递到端口寄存器去。我也是初学者,不一定对。彼此学习
回复

使用道具 举报

13#
ID:74143 发表于 2022-4-9 16:16 | 只看该作者
可以,很详细的说明
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表