STM32——GPIO(2)

发布者:technology78最新更新时间:2020-12-09 来源: eefocus关键字:STM32  GPIO 手机看文章 扫描二维码
随时随地手机看文章


/* GPIO_InitTypeDef结构体 */

typedef enum

{

  GPIO_Speed_10MHz = 1,  //枚举常量,值为 1,代表输出速率最高为 10MHz

  GPIO_Speed_2MHz,       //对不赋值的枚举变量,自动加 1,此常量值为 2

  GPIO_Speed_50MHz       //常量值为 3

} GPIOSpeed_TypeDef;

 

typedef enum

{

  GPIO_Mode_AIN = 0x0, //模拟输入模式

  GPIO_Mode_IN_FLOATING = 0x04, //浮空输入模式

  GPIO_Mode_IPD = 0x28, //下拉输入模式

  GPIO_Mode_IPU = 0x48, //上拉输入模式

  GPIO_Mode_Out_OD = 0x14, //开漏输出模式

  GPIO_Mode_Out_PP = 0x10, //通用推挽输出模式

  GPIO_Mode_AF_OD = 0x1C,  //复用功能开漏输出

  GPIO_Mode_AF_PP = 0x18   //复用功能推挽输出

} GPIOMode_TypeDef;

 

typedef struct

{

  uint16_t GPIO_Pin;              /* 指定要配置的引脚 */

  GPIOSpeed_TypeDef GPIO_Speed;   /* 指定GPIO引脚输出的最高频率 */

  GPIOMode_TypeDef GPIO_Mode;     /* 指定GPIO引脚工作状态 */

} GPIO_InitTypeDef;

/* 初始化GPIO -- GPIO_Init() */

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

{

  uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;

  uint32_t tmpreg = 0x00, pinmask = 0x00;

  /* 断言,用于检查输入的参数是否正确 */

  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

  assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));

  assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));

  /*---------------------------- GPIO 的模式配置 -----------------------*/

  /*把输入参数 GPIO_Mode 的低四位暂存在 currentmode*/

  currentmode = ((uint32_t)GPIO_InitStruct -

                 > GPIO_Mode) & ((uint32_t)0x0F);

  /*判断是否为输出模式,输出模式,可输入参数中输出模式的 bit4 位都是 1*/

  if ((((uint32_t)GPIO_InitStruct -

        > GPIO_Mode) & ((uint32_t)0x10)) != 0x00)

  {

    /* 检查输入参数 */

    assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));

    /* 输出模式,所以要配置 GPIO 的速率:00(输入模式) 01(10MHz) 10(2MHz) 11 */

    currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;

  }

  /*----------------------------配置 GPIO 的 CRL 寄存器 -----------------------

  -*/

  /* 判断要配置的是否为 pin0 ~~ pin7 */

  if (((uint32_t)GPIO_InitStruct -

       > GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)

  {

    /*备份原 CRL 寄存器的值*/

    tmpreg = GPIOx->CRL;

    /*循环,一个循环设置一个寄存器位*/

    for (pinpos = 0x00; pinpos < 0x08; pinpos++)

    {

      /*pos 的值为 1 左移 pinpos 位*/

      pos = ((uint32_t)0x01) << pinpos;

      /* 令 pos 与输入参数 GPIO_PIN 作位与运算,为下面的判断作准备 */

      currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;

      /*判断,若 currentpin=pos,说明 GPIO_PIN 参数中含的第 pos 个引脚需要配置*/

      if (currentpin == pos)

      {

        /*pos 的值左移两位(乘以 4),因为寄存器中 4 个寄存器位配置一个引脚*/

        pos = pinpos << 2;

        /*以下两个句子,把控制这个引脚的 4 个寄存器位清零,其它寄存器位不变*/

        pinmask = ((uint32_t)0x0F) << pos;

        tmpreg &= ~pinmask;

        /* 向寄存器写入将要配置的引脚的模式 */

        tmpreg |= (currentmode << pos);

        /* 复位 GPIO 引脚的输入输出默认值*/

        /*判断是否为下拉输入模式*/

        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)

        {

          /*下拉输入模式,引脚默认置 0,对 BRR 寄存器写 1 可对引脚置 0*/

          GPIOx->BRR = (((uint32_t)0x01) << pinpos);

        }

        else

        {

          /*判断是否为上拉输入模式*/

          if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)

          {

            /*上拉输入模式,引脚默认值为 1,对 BSRR 寄存器写 1 可对引脚置 1*/

            GPIOx->BSRR = (((uint32_t)0x01) << pinpos);

          }

        }

      }

    }

    /*把前面处理后的暂存值写入到 CRL 寄存器之中*/

    GPIOx->CRL = tmpreg;

  }

  /*---------------------------- 以下部分是对 CRH 寄存器配置的 -----------------

  --------当要配置的引脚为 pin8 ~~ pin15 的时候,配置 CRH 寄存器, -----

  ------------- -----这过程和配置 CRL 寄存器类似------------------------------

  ------

  -------读者可自行分析,看看自己是否了解了上述过程--^_^-----------*/

  /* Configure the eight high port pins */

  if (GPIO_InitStruct->GPIO_Pin > 0x00FF)

  {

    tmpreg = GPIOx->CRH;

    for (pinpos = 0x00; pinpos < 0x08; pinpos++)

    {

      pos = (((uint32_t)0x01) << (pinpos + 0x08));

      /* Get the port pins position */

      currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);

      if (currentpin == pos)

      {

        pos = pinpos << 2;

        /* Clear the corresponding high control register bits */

        pinmask = ((uint32_t)0x0F) << pos;

        tmpreg &= ~pinmask;

        /* Write the mode configuration in the corresponding bits */

        tmpreg |= (currentmode << pos);

        /* Reset the corresponding ODR bit */

        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)

        {

          GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));

        }

        /* Set the corresponding ODR bit */

        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)

        {

          GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));

        }

      }

    }

    GPIOx->CRH = tmpreg;

  }

}


关键字:STM32  GPIO 引用地址:STM32——GPIO(2)

上一篇:Cortex M3内核架构
下一篇:STM32项目(一) —— 展示车座椅

推荐阅读最新更新时间:2024-11-12 11:49

STM32单片机对红外接收系统的设计
4.23.1概述 人的眼睛能看到的可见光按波长从长到短排列,依次为红、橙、黄、绿、青、蓝、紫。其中红光的波长范围为0.62~0.76μm;紫光的波长范围为0.38~0.46μm。比紫光光波长更短的光叫紫外线,比红光波长更长的光叫红外线最广义地来说,传感器是一种能把物理量或化学量转变成便于利用的电信号的器件,红外传感器就是其中的一种。随着现代科学技术的发展,红外线传感器的应用已经非常广泛。 4.23.1.1红外接收头工作原理 红外接收头一般是接收、放大、解调一体头,一般红外信号经接收头解调后,数据“0”和“1”的区别通常体现在高低电平的时间长短或信号周期上,单片机解码时,通常将接收头输出脚连接到单片机的外部中断,结合定时器判断外
[单片机]
<font color='red'>STM32</font>单片机对红外接收系统的设计
stm32 外部PB8中断
一、初始化该引脚时钟 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB ,ENABLE); 二、初始化该引脚为外部中断 void GPIO_Config_Init(void) { GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //PB8 dog_wake GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } 三、初始化外
[单片机]
STM32之Bit banding
【1】Bit banding即位带操作,STM32的寄存器大都为32位,想要修改某个特定位很困难,位带操作即可解决这个问题,它是将寄存器的特定位和bit-band区域的一个32位地址绑定,也就是一对32,你对这个位带区域的32地址赋值即可控制相应位,可赋值范围是0-2的32次方,但这里赋值0和1便足够。 【2】位带操作是硬件支持还是需要软件设置? 硬件支持,只要你能根据公式找到对应地址,你就可以轻松使用位带操作!这里推荐使用宏定义,可以看这里: https://blog.csdn.net/wofreeo/article/details/82255491 【3】位带操作支持所有寄存器吗? 可见包含了
[单片机]
怎么解决STM32(MDK)中不能使用printf()函数的问题
简单地说:想在mdk 中用printf,需要同时重定义fputc函数和避免使用semihosting(半主机模式), 标准库函数的默认输出设备是显示器,要实现在串口或LCD输出,必须重定义标准库函数里调用的与输出设备相关的函数. 例如:printf输出到串口,需要将fputc里面的输出指向串口(重定向),方法如下: #ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker- Libraries- Small printf set to 'Yes') calls __io_putchar() */ #define PUTCHAR_
[单片机]
怎么解决<font color='red'>STM32</font>(MDK)中不能使用printf()函数的问题
基于STM32的语音导览系统的设计方案
景点语音导览主要有以下几种方式:一种是通过全球定位系统(GPS)的用户终端接收工作卫星的导航信息,从而解算出车辆的经纬度信息,进而计算出实时坐标,将其与景点坐标相比较,当车辆驶入景点一定距离范围内时,不用人工干预,系统自动播报景点语音信息;另一种是对车轮轴的转角脉冲进行计数,将计数值和预置值对比,即可确定播放时刻,达到准确播放景点语音信息的目的;第三种方案是利用无线射频识别技术,在每一个景点范围内设置一个具有唯一ID的射频发射器,采用间歇工作方式发射信号,当旅游列车即将到达景点时,车载系统接收到射频发射器信号并解码出景点的ID号,由系统控制自动播放对应编号的景点语音信息。由于景点自然环境的复杂性,第一种方式难以满足系统要求;第二种
[单片机]
基于<font color='red'>STM32</font>的语音导览系统的设计方案
ADC采集电压和显示 基于STM32的ADC—电压采集
功能介绍放开头, 使用便捷无需愁 这是全网最详细、性价比最高的STM32实战项目入门教程,通过合理的硬件设计和详细的视频笔记介绍,硬件使用STM32F103主控资料多方便学习,通过3万字笔记、12多个小时视频、20多章节代码手把手教会你如何开发和调试。让你更快掌握嵌入式系统开发。 V3.3.0-STM32智能小车 视频: https://www.bilibili.com/video/BV16x4y1M7EN/?spm_id_from=333.337.search-card.all.click V3:HAL库开发、功能:PID速度控制、PID循迹、PID跟随、遥控、避障、PID角度控制、视觉控制、电磁循迹、RTOS等功能。 我们
[单片机]
ADC采集电压和显示 基于<font color='red'>STM32</font>的ADC—电压采集
用定时器生成PWM波的方法
用定时器生成PWM波 PWM全称是Pulse Width Modulation,通过控制高频信号的占空比,眼睛当成低通滤波器,可以控制亮暗。再循环更改PWM的阈值,就弄出了呼吸的效果,相关文章推荐:STM32中PWM的配置与应用详解。 这里采用一个比较简单的方法生成PWM波:设置定时器中断然后根据阈值判断置高和置低。 void TIM3_IRQHandler(void) { TIM_ClearITPendingBit(TIM3,TIM_IT_Update); if(counter==255) counter = 0; else counter+=1; if(mode
[单片机]
毕业设计| STM32版RFID医嘱专用手环
作为医嘱手环,除了有手环的常规功能之外,还有和医院的互动功能: ◇心率、血氧监测 使用MAX30102模块,算法是FFT快速傅里叶变换,同时心率、血氧信息会通过8266WiFi发送给上位机,在动态网页上实时显示。 ◇RFID识别药品 通过按键选择OLED屏幕上的“核验”功能进行核验,核验的过程分为核验RFID标签扇区密码,读取相应扇区存放的数据,再进行字符串对比。如果读出的字符串和手环内部设置的患者编号不同,LED红灯亮起,OLED显示“核验错误”,同时蜂鸣器进行报错,直到用户按下确定键。核验正确则亮绿灯,延时2s消失。同时核验记录会通过8266WiFi发送给上位机。注意:要先在RFID标签相应扇区里写入信息◇ 接收通
[单片机]
毕业设计| <font color='red'>STM32</font>版RFID医嘱专用手环
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved