• STM32技术--GPIO配置


    以下以STM32F407ZGT6为例。

    一.GPIO的作用

    1.当作输入输出口 输出数字信号 0/1
    TTL电平 0 0~1.5V 1 2.5~5V
    STM32中 - 0±0.1V 1 3.3±0.3V
    2.直接驱动外部电路 如LED,蜂鸣器等等
    3.使用I/O口模拟通信协议 IIC
    4.模拟PWM波 通过循环改变占空比来实现

    二.STM32F407ZGT6芯片中GPIO口的数量及命名

    1.114个I/O口,每个I/O口上有不同的通用功能,复用功能等
    2.命名 Port + 端口号 + 管脚号
    端口号 : A B C D E F G H 在A~G上每个端口有16个管脚(0~15),H只有2个管脚(1,2)
    例 PA5 A端口的第5个管脚

    三.如何操作GPIO口

    通过AHB1时钟总线与GPIO口通信 操作提供的接口----寄存器

    四.STM32F407ZTG6中GPIO的寄存器

    1.寄存器:一块存储空间(8/16/32位),具有RAM具有的特性(掉电数据丢失,读写速度快),每个位 都有自己独特的作用。
    2.如何操作寄存器
    通过指针操作 例如我们想操作一个地址为0x4000的寄存器只需要通过*(unsigned int *)0x4000进行我们需要的操作(赋值,加减,位操作)
    3.寄存器的特性
    有读/写,只读,只写,读取/清零,读取/置位,切换,保留(reserved)等
    数据(DR)寄存器:保存接受/发送的数据,一般用=接受
    配置(控制CR)寄存器:配置相关的工作模式,一般用&=~进行清零或|=置一 ^= 进行反转
    状态(SR)寄存器:外设所处的状态,一般用 &1 操作来进行读取
    4.GPIO的工作模式
    上拉:1.拉高电平2.增强电路的驱动能力
    下拉:1.拉低电平2.增强电路的驱动能力
    输入:4种
    浮空输入:输入的是数字量,不具有上下拉驱动能力的输入 – 按键识别
    上拉输入:输入的是数字量,具有上拉驱动能力的输入
    下拉输入:输入的是数字量,具有下拉驱动能力的输入
    模拟输入:输入的是模拟量 – 模数转换 ADC
    输出:4种
    通用:IO功能
    复用:除了IO以外的功能,比如串口,定时器等
    开漏输出:只能输出0(想要输出1,需要接上拉电阻)--总线通信
    推挽输出:既能输出0,又能输出1.
    5.通过配置步骤(以LED为例)
    1.查看原理图,找到led对应的IO口

    以pf6为例,当向该引脚输出0时led亮。

    2.查看该IO口的通用功能是否用作作IO口

     在这里PF6的通用功能为io口的功能


    3.打开该GPIO口对应的时钟
    4.配置工作模式

     

    在该图中A,B,C,D,E,F,G,H,I的时钟总线都是AHB1,所以在我们操作该GPIO口时要将该时钟打开,只需通过位操作将相应位置一即可,具体操作位

    RCC->AHB1ENR |= (1<<0);这里左移0位即为将GPIOA置为1。

    接下来配置GPIOF的工作模式,以第6位为例

    因为时通用功能,所以复用暂时不看以后会提到

    led的工作模式位通用推挽输出,无上下拉,快速模式(可自己选择)

    若要将pf6配置为通用,要在第12,13位中写入01操作如下:

    //pf6 通用推挽输出
    GPIOF->MODER &=~ (3<<12); //清零
    GPIOF->MODER |= (1<<12); //通用输出模式
    GPIOF->OTYPER &=~ (1<<6); //输出推挽
    GPIOF->OSPEEDR &=~ (3<<12); //速度清零
    GPIOF->OSPEEDR |= (2<<12); //快速
    GPIOF->ODR |= (1<<6); //led灭

     这里因为GPIOF->ODR的复位值为0x0000 0000,而根据 原理图当该引脚输出0时led亮,所以在初始化中需要将该位置1,需要让led灭的时候把相应位置为0即可。

    led是输出的体现,那么独立按键就是输入的体现了,下面让我们看一下怎么配置key的工作方式。

    还是按上面的步骤:

    1.查看原理图,确定引脚,以及工作方式

    以key1为例,可以看出当按键没用按下的时候,该IO口检测到的(就是向IO口输入的)为低电平,按键按下时,就会检测到高电平。我们可以搜索他的标号(KEY1)来确定他的端口号,所以我么只要配置PA0,为输入模式就可以使用KEY1这个独立按键了

    2.看该IO口是否有IO口的功能

    通用功能是IO口的功能 

    3.打开对应的时钟

    4.配置相应的工作模式

    RCC->AHB1ENR &=~ (1<<0);
    RCC->AHB1ENR |= (1<<0);
    //pa0 浮空输入
    GPIOA->MODER &=~ 3;
    GPIOA->PUPDR &=~ 3;

    这样就配置完成了,我们只要检测GPIOA->IDR这个输入数据寄存器就可以确定按键是否按下了。

    完整代码如下:

    复制代码
     1 #include "led.h"
     2 #include "delay.h"
     3 
     4 
     5 
     6 /*
     7 函数名称:led_config()
     8 函数功能:初始化led
     9 函数参数:无
    10 
    11 */
    12 void led_config()
    13 {
    14     //pf6
    15     //开时钟
    16     RCC->AHB1ENR |= ((1<<5)|(1<<2));
    17     //pf6 通用推挽输出
    18     GPIOF->MODER &=~ ((3<<12)|(3<<18)|(3<<20));        //清零
    19     GPIOF->MODER |= ((1<<12)|(1<<18)|(1<<20));        //通用输出模式
    20     GPIOF->OTYPER &=~ ((1<<6)|(1<<9)|(1<<10));        //输出推挽
    21     GPIOF->OSPEEDR &=~ ((3<<12)|(3<<18)|(3<<20));    //速度清零
    22     GPIOF->OSPEEDR |= ((2<<12)|(2<<18)|(2<<20));    //快速
    23     GPIOF->ODR |= ((1<<6)|(1<<9)|(1<<10));                //led灭
    24     
    25     GPIOC->MODER &=~ (3<<0);
    26     GPIOC->MODER |= (1<<0);
    27     GPIOC->OTYPER &=~ (1<<0);
    28     GPIOC->OSPEEDR &=~ (3<<0);
    29     GPIOC->OSPEEDR |= (2<<0);
    30     GPIOC->ODR |= (1<<0);
    31     
    32 }
    33 
    34 
    35 void led1_Flash()
    36 {
    37     
    38     LED1(1);
    39     delay_nms(500);
    40     LED1(0);
    41     delay_nms(500);
    42 }
    43 
    44 //流水灯
    45 void led_pipeline()
    46 {
    47     LED1(1);
    48     delay_nms(500);
    49     LED1(0);
    50     LED2(1);
    51     delay_nms(500);
    52     LED2(0);
    53     LED3(1);
    54     delay_nms(500);
    55     LED3(0);
    56     LED4(1);
    57     delay_nms(500);
    58     LED4(0);
    59 }
    60 
    61 //呼吸灯
    62 void breath_led()
    63 {
    64     uint32_t i;
    65     for(i=0;i<1000;i++)
    66     {
    67         LED2(1);
    68         delay_nus(i);
    69         LED2(0);
    70         delay_nus(1000-i);
    71     }
    72     for(i=0;i<1000;i++)
    73     {
    74         LED2(0);
    75         delay_nus(1000-i);
    76         LED2(1);
    77         delay_nus(i);
    78     }
    79 
    80 }
    复制代码
    复制代码
    #include "key.h"
    #include "delay.h"
    
    /*
    
    函数功能:初始化key
    函数名称:key_config()
    函数参数:无
    */
    void key_config()
    {
        //开时钟
        RCC->AHB1ENR &=~ (1|(1<<4));
        RCC->AHB1ENR |= (1|(1<<4));
        //pa0 浮空输入
        GPIOA->MODER &=~ 3;
        GPIOA->PUPDR &=~ 3;
        
        GPIOE->MODER &=~ ((3<<4)|(3<<6)|(3<<8));
        GPIOE->PUPDR &=~ ((3<<4)|(3<<6)|(3<<8));
    }
    
    
    /*
    
    函数功能:获取按键的值
    函数名称:getKeyValue()
    函数参数:无
    */
    uint8_t getKeyValue()
    {
        uint8_t value;
        if(key1)
        {
            delay_nms(10);
            if(key1)
            {
                value = 1;
            }
        }
        else if(!key2)
        {
            delay_nms(10);
            if(!key2)
            {
                value = 2;
            }
        }
        else if(!key3)
        {
            delay_nms(10);
            if(!key3)
            {
                value = 3;
            }
        }
        else if(!key4)
        {
            delay_nms(10);
            if(!key4)
            {
                value = 4;
            }
        }
        
        return value;
    }
    复制代码

     

  • 相关阅读:
    [置顶] 从零开始学C++之STL(二):实现简单容器模板类Vec(vector capacity 增长问题、allocator 内存分配器)
    HDU4607(求树中的最长链)
    java从文件中读取数据然后插入到数据库表中
    rcp(插件开发)插件B需要引用插件A中的jar包-如何处理依赖关系
    HDU 2084 数塔
    Object-c学习之路二(oc内存管理黄金法则1)
    android adb命令 unable to connect to 192.168.1.155:5555
    安装node.js / npm / express / KMC
    oracle断电重启之ORA-00600[4194]
    virtualbox虚拟机迁移出现"connot find device eth0"错误
  • 原文地址:https://www.cnblogs.com/laoxiongzhijia/p/14429793.html
Copyright © 2020-2023  润新知