stm32寄存器版學習筆記01 GPIO口的配置(LED、按鍵)


  STM32的I/O口可以由軟件配置成如下8種模式:輸入浮空、輸入上拉、輸入下拉、模擬輸入、開漏輸出、推挽輸出、推挽式復用功能及開漏復用功能。每個I/O口由7個寄存器來控制:配置模式的端口配置寄存器CRL和CRH(模式、速度);數據寄存器IDR和ODR;置位/復位寄存器BSRR;復位寄存器BRR;鎖存寄存器LCKR。

 

I/O口模式:

GPIO的8種模式
通用輸出 推挽輸出(Push-Pull) 可以輸出高、低電平,連接數字器件  
開漏輸出(Open-Drain) 開漏引腳不連接外部的上拉電阻時,只能輸出低電平;如果需要同時具備輸出高電平的功能,則需要接上拉電阻  
復用功能輸出 復用功能推挽輸出 片內外設功能(I2C的SCL,SDA) GPIO口被用作第二功能時的配置情況(即並非作為通用IO口使用)
復用功能開漏輸出 片內外設功能(TX1,MOSI,MISO,SCK,SS)
輸入 模擬輸入 應用ADC模擬輸入,或者低功耗下省電  
浮空輸入 可以做KEY識別,外部按鍵輸入 IO的電平狀態是不確定,完全由外部輸入決定
下拉輸入 IO內部下拉電阻輸入 不確定信號->低電平
上拉輸入 IO內部上拉電阻輸入 不確定信號->高電平

 

  

 



 

 

 

 

 

 

 

1.GPIO口配置步驟

①使能PORTx(x=A~G)

  APB2外設時鍾使能寄存器(RCC_APB2ENR)

置1開啟。清0關閉。

8-2位使能GPIO G-A

  Eg:RCC->APB2ENR| = 1 << 2;  //使能PORTA時鍾

②配置IO口模式 低8位(CRL) 高8位(CRH)

  端口配置低寄存器(GPIOx_CRL) (x=A..E)

  Eg:GPIOA->CRL |= 0x00000003;  //PA0推挽輸出

③配置端口輸入和輸出電平

  端口輸入數據寄存器(GPIOx_IDR) (x=A..E)

 

  端口輸出數據寄存器(GPIOx_ODR) (x=A..E)

Eg: GPIOA->ODR |= 1 <<8;  //PA8輸出高

 

2.GPIO配置相關寄存器

  端口位設置/清除寄存器(GPIOx_BSRR) (x=A..E)

ODR寄存器只進行置1操作,不支持寫0操作。用BSRR寄存器進行清除。

 

  端口位清除寄存器(GPIOx_BRR) (x=A..E)

 

  端口位清除寄存器(GPIOx_BRR) (x=A..E)  具體參看數據手冊

  當執行正確的寫序列設置了位16(LCKK)時,該寄存器用來鎖定端口位的配置。位[15:0]用於鎖定GPIO端口的配置。在規定的寫入操作期間,不能改變LCKP[15:0]。當對相應的端口位執行了LOCK序列后,在下次系統復位之前將不能再更改端口位的配置。 每個鎖定位鎖定控制寄存器(CRL, CRH)中相應的4個位。

 

3.LED

//led.c                    
//LED IO口初始化
void LED_Init(void)
{
    RCC->APB2ENR|=1<<2;      //使能PORTA時鍾        
    RCC->APB2ENR|=1<<5;      //使能PORTD時鍾         
    GPIOA->CRH&=0XFFFFFFF0; 
    GPIOA->CRH|=0X00000003;//PA8推挽輸出     
  GPIOA->ODR|=1<<8;                //PA8輸出高
                                              
    GPIOD->CRL&=0XFFFFF0FF;
    GPIOD->CRL|=0X00000300;//PD2推挽輸出
    GPIOD->ODR|=1<<2;         //PD2輸出高
}

//led.h
#ifndef __LED_H
#define __LED_H     
#include "sys.h"

//LED端口定義
#define LED0 PAout(8)    // PA8
#define LED1 PDout(2)    // PD2    

void LED_Init(void);    //初始化                         
#endif 

//main.c
#include "sys.h"
#include "usart.h"        
#include "delay.h"    
#include "led.h" 
int main(void)
{         
    Stm32_Clock_Init(9); //系統時鍾設置
    delay_init(72);             //延時初始化
    LED_Init();        //初始化與LED連接的硬件接口
    while(1)
    {
        LED0=0;
        LED1=1;
        delay_ms(300);
        LED0=1;
        LED1=0;
        delay_ms(300);
    }     
}

 

4.按鍵KEY輸入

//key.c
#include "key.h"
#include "delay.h"
//按鍵初始化函數
//PA0 PA15 PC5設置成輸入
void KEY_Init(void)
{
    RCC->APB2ENR|=1<<2;     //使能PORTA時鍾
    RCC->APB2ENR|=1<<4;     //使能PORTC時鍾
    JTAG_Set(SWD_ENABLE);    //關閉JTAG 開啟SWD PA15占用了JTAG一個口
    GPIOA->CRL&=0XFFFFFFF0;    //PA0設置成輸入  
    GPIOA->CRL|=0X00000008;   
    GPIOA->CRH&=0X0FFFFFFF;    //PA15設置成輸入
    GPIOA->CRH|=0X80000000;              
    GPIOA->ODR|=1<<15;           //PA15上拉 PA0默認下拉
    GPIOC->CRL&=0XFF0FFFFF;    //PC5設置成輸入  
    GPIOC->CRL|=0X00800000;   
    GPIOC->ODR|=1<<5;           //PC5上拉
} 
//按鍵處理函數
//mode:0不支持連續按;1,支持連續按
//響應優先級KEY0>KEY1>WK_UP
u8 KEY_Scan(u8 mode)
{     
    static u8 key_up=1;//按鍵按松開標志
    if(mode)key_up=1;  //支持連按      
    if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))
    {
        delay_ms(10);//去抖動
        key_up=0;
        if(KEY0==0)
                    return KEY0_PRES;
        else if(KEY1==0)
                    return KEY1_PRES;
        else if(WK_UP==1)
                    return WKUP_PRES; 
    }else if(KEY0==1&&KEY1==1&&WK_UP==0)
            key_up=1;          
    return 0;// 無按鍵按下
}

//key.h
#ifndef __KEY_H
#define __KEY_H     
#include "sys.h"

#define KEY0_PRES    1        //KEY0按下
#define KEY1_PRES    2        //KEY1按下
#define WKUP_PRES    3        //WK_UP按下

#define KEY0  PCin(5)          //PC5
#define KEY1  PAin(15)         //PA15 
#define WK_UP PAin(0)          //PA0  WK_UP
     
void KEY_Init(void);        
u8 KEY_Scan(u8 mode);        
#endif

//main.c
#include "sys.h"
#include "usart.h"        
#include "delay.h"    
#include "led.h" 
#include "key.h" 

int main(void)
{         
    u8 t;      
    Stm32_Clock_Init(9);     
    delay_init(72);            
    LED_Init();                   
    KEY_Init();          
    LED0 = 0;                    
    while(1)
    {
        t=KEY_Scan(0);        
        switch(t)
        {                 
            case KEY0_PRES:
                LED0=!LED0;
                break;
            case KEY1_PRES:
                LED1=!LED1;
                break;
            case WKUP_PRES:                
                LED0=!LED0;
                LED1=!LED1;
                break;
            default:
                delay_ms(10);    
        } 
    }         
}

                    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM