当前位置: 移动技术网 > IT编程>开发语言>C/C++ > STM32之GPIO底层原理与编程实践

STM32之GPIO底层原理与编程实践

2020年01月16日  | 移动技术网IT编程  | 我要评论

合肥天气预报15天,香港机房托管,和同事姐姐婚外情

一、什么是gpio

  gpio全称为general purpose input output,中文理解为通用输入输出端口。它指的是编程可控制的引脚,即可以控制引脚是作为输入来用,还是输出功能,又或者是交给片上外设使用(复用)。

 

二、gpio结构框图

  理解gpio硬件电路的实现,有助于编程的理解。下图是官方手册给出的gpio框图:

 

  此框图中只有最右端的i/o pin是板上外露可见的,其他部分均在芯片内部。该框图结构被分为两个部分,其一是输出结构,主要由引脚(i/o pin)、保护二极管(protection diode)、双mos管(p-mos+n-mos)、输出控制(output control)、输出数据寄存器(output data register)、位置位/复位寄存器(bit set/reset register)组成 ;其二是输入结构,由引脚、保护二极管、双开关(on/off)、ttl肖特基触发器(ttl schmitt trigger)、输入数据寄存器(input data register)组成。

  1.保护二极管

    两个二极管构成了双向限幅电路。当外部输入电压大于vdd时,上方二极管导通(全文皆忽略二极管和mos管导通压降),使得电压限制在vdd左右;当外部输入电压低于vss,下方二极管导通,电压限制在vss左右。然而这样的保护并不能使引脚直接驱动大功率器件,例如电机,就需要外加驱动电路。

  2.双开关

    这个双开关电路与上拉、下拉和浮空模式有关,当处于上拉模式时上方开关闭合,下方断开,除非引脚的外部输入为低电平,否则输入到肖特基触发器的电平都是高电平;当处于下拉模式时上方开关断开,下方闭合,除非引脚的外部输入为高电平,否则输入到肖特基触发器的电平都是低电平;当处于浮空模式时开关全部断开,电平默认为高阻态,输入的电平完全取决于外部输入。上下拉多用于按键检测,而浮空则常用于adc检测。

  3.肖特基触发器

    该触发器主要是将模拟电压转为0/1数字信号,上图中模拟输入(analog input)就取自触发器之前,而输入数据寄存器则取自触发器之后的数字信号。

  4.输入数据寄存器

    这个寄存器用来存储各个引脚电平状态,可通过读取该寄存器内容,来获取任意引脚状态。

  5.位置位/复位寄存器

    通过读写该寄存器,可以间接地更改输出数据寄存器的值。

  6.输出数据寄存器

    可以直接读写该寄存器,来更改各个引脚的输出状态,当寄存器值保持不变时,每个引脚的电平也就不发生变化。

  7.双mos管

    双mos管组成一个推挽输出(push-pull)电路,当输出寄存器中值为1时,经过反相器,两管的共栅极输入低电平,则pmos导通,nmos截止,引脚输出高电平;当输出寄存器中值为0时,经过反相器,两管的共栅极输入高电平,则nmos导通,pmos截止,引脚输出低电平。当pmos被禁用时,电路变为开漏输出,引脚仍可输出低电平,但无法正常输出高电平,取而代之的是高阻态。如果此时想要输出高电平,则必须接上拉电阻。开漏输出仅在一些特殊场合下使用,更多的是推挽输出。

 

三、gpio寄存器

  1.apb2外设时钟使能寄存器(rcc_apb2enr)

    rcc_apb2enr并不属于gpio的寄存器组,但是它控制着gpio的引脚时钟使能,芯片上电后,所有外设时钟默认是关闭的,所以在使用gpio前要先打开端口时钟使能。该寄存器内容如下,我们只关心iopxen位,置1则开启时钟。

    

       

 

  2.端口配置低位寄存器(gpiox_crl)

    该寄存器可配置低8个gpio引脚的工作模式:模拟输入、浮空输入、上拉\下拉输入、通用推挽输出、通用开漏输出、复用推挽输出、复用开漏输出。复用输入模式没有单独的配置,只要将引脚配置为浮空/上拉/下拉输入模式,由片上外设驱动即可。crl还可以在输出模式下配置工作频率,频率越大,功耗越高。注意每个引脚模式配置占4bit。对于上拉\下拉输入来说,是上拉还是下拉取决于odr寄存器配置的值。

    

 

  3.端口配置高位寄存器(gpiox_crh)

    该寄存器同gpiox_crl,只是它控制的是高8个gpio引脚的工作模式。

    

 

  4.输入数据寄存器(gpiox_idr)

    该寄存器存储了当前引脚的状态,无论gpio在哪种工作模式下,都可以读取该寄存器,但在模拟输入模式下,寄存器的值一直为0。

    

 

     

  5.输出数据寄存器(gpiox_odr)

    在通用输出模式下,该寄存器可用来控制电平高低;在复用推挽输出模式下,可读取odr获取引脚状态(在复用开漏输出模式下,可读取idr获取引脚状态)。在上拉或下拉输入模式下,odr可决定是上拉还是下拉。

    

 

 

   

  6.位置位/复位寄存器(gpiox_bsrr)

    通过该寄存器,可以单独控制某个引脚的电平变化。因为向这个寄存器写0的结果是无操作,写1是置位或者复位,所以访问该寄存器可以直接用=号;而odr寄存器写0则表示给低电平,写1表示给高电平,为了不影响其他引脚,写入必须用&=和|=号。另外还有个寄存器叫gpiox_brr,同该寄存器差不多,只不过brr只能复位,高16位是保留的。

    

 

 

 

四、gpio编程

  gpio最常用的就是通用推挽输出和上拉/下拉输入这两种模式。一下程序实现功能为:

    pa0为按键输入,按下为低电平。pc13是led控制引脚,低电平点亮led。当按下按键时,led亮;松开按键时,led灭。

  程序代码如下,根据gpio原理,编程顺序一般是:先开启时钟使能,配置引脚工作模式,最后给引脚电平信号。

  

int main(void)
{
    
    uint32_t key_value;
    
    //开启gpio外设时钟使能
    //porta,第三位置1
    rcc->apb2enr |= (1<<2);
    //portc,第五位置1
    rcc->apb2enr |= (1<<4);
    
    //gpio输入输出模式配置
    //清零pa0控制位
    gpioa->crl &= ~((uint32_t)(0x0f)<<(4*0));
    //设置pa0为上拉输入
    gpioa->crl |=  (uint32_t)(0x08)<<(4*0);
    gpioa->odr |=  (uint32_t)(0x01)<<0;    
    //清零pc13控制位
    gpioc->crh &= ~((uint32_t)(0x0f)<<(4*5));
    //设置pc13为推免输出
    gpioc->crh |=  (uint32_t)(0x01)<<(4*5);
    
    
    while(1){
            //获取pa0电平状态,key_value==1表示按键没有按下
            key_value = (gpioa->idr & (uint32_t)(0x01)) == (uint32_t)(0x01);
            //改变pc13电平
            if (key_value==0)
                //pc13低电平输出
                gpioc->odr &= ~((uint32_t)(0x01)<<13);                
            else
                //pc13高电平输出
                gpioc->odr |= (uint32_t)(0x01)<<13;
    }
}

  

 

  

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网