K60學(xué)習(xí)打卡之GPIO初始化

一、代碼分析
本次分析的代碼非常簡(jiǎn)短

GPIO_QuickInit(HW_GPIOE, 6, kGPIO_Mode_OPP);

這句代碼的意思也和單一,就是將GPIOE模塊的第6引腳配置為推挽輸出方式。
但是內(nèi)部還是比較復(fù)雜的,其函數(shù)原型如下:

uint8_t GPIO_QuickInit(uint32_t instance, uint32_t pinx, GPIO_Mode_Type mode)

instance表示的是GPIO模塊號(hào);pinx表示引腳的標(biāo)號(hào),在0-31之間;mode表示引腳的使用模式。在gpio.h文件中有如下定義:

/* GPIO端口定義 */
#define HW_GPIOA  (0x00U) /*GPIO模塊A,依次類推*/  
#define HW_GPIOB  (0x01U)
#define HW_GPIOC  (0x02U)
#define HW_GPIOD  (0x03U)
#define HW_GPIOE  (0x04U)
#define HW_GPIOF  (0x05U)//在數(shù)據(jù)手冊(cè)中是沒(méi)有GPIOF這個(gè)模塊的

/* GPIO 端口模式的定義*/
typedef enum
{
    kGPIO_Mode_IFT = 0x00,       /**< 浮空輸入 */
    kGPIO_Mode_IPD = 0x01,       /**< 下拉輸入 */
    kGPIO_Mode_IPU = 0x02,       /**< 上拉輸入 */
    kGPIO_Mode_OOD = 0x03,       /**< 開漏輸出 */
    kGPIO_Mode_OPP = 0x04,       /**< 推挽輸出 */
}GPIO_Mode_Type;

這個(gè)函數(shù)在gpio.c文件中的實(shí)現(xiàn)如下:

uint8_t GPIO_QuickInit(uint32_t instance, uint32_t pinx, GPIO_Mode_Type mode)
{
    GPIO_InitTypeDef GPIO_InitStruct1;
    GPIO_InitStruct1.instance = instance;
    GPIO_InitStruct1.mode = mode;
    GPIO_InitStruct1.pinx = pinx;
    GPIO_Init(&GPIO_InitStruct1);
    return  instance;
}

在實(shí)現(xiàn)的過(guò)程中,在這里使用了一個(gè)結(jié)構(gòu)體變量GPIO_InitTypeDef,這個(gè)結(jié)構(gòu)體在gpio.h中定義如下:

typedef struct
{
    uint8_t                instance;    ///<引腳端口HW_GPIOA~HW_GPIOF
    GPIO_Mode_Type         mode;        ///<工作模式
    uint32_t               pinx;        ///<引腳號(hào)0~31
}GPIO_InitTypeDef;

這樣,在GPIO初始化函數(shù)中的工作就和清楚了,就是將參數(shù)傳遞進(jìn)來(lái)完成結(jié)構(gòu)體的初始化。然后由GPIO_Init()函數(shù)完成初始化。到這里第一層的函數(shù)調(diào)用就結(jié)束了。

接下來(lái)是第二層的函數(shù)調(diào)用,也就是GPIO_Init()函數(shù).
由于這個(gè)函數(shù)過(guò)于復(fù)雜,這里只復(fù)制其中一部分代碼進(jìn)行分析,其他的大都是重復(fù)的結(jié)構(gòu)。這個(gè)函數(shù)內(nèi)部打功能大致是根據(jù)引腳的配置模式先進(jìn)行設(shè)置,然后再完成初始化,使用的代碼如下:

void GPIO_Init(GPIO_InitTypeDef * GPIO_InitStruct)
{
    /* config state */
    switch(GPIO_InitStruct->mode)
    {
      ...
            PORT_PinPullConfig(GPIO_InitStruct->instance, GPIO_InitStruct->pinx, kPullDisabled);
            PORT_PinOpenDrainConfig(GPIO_InitStruct->instance, GPIO_InitStruct->pinx, DISABLE);
            GPIO_PinConfig(GPIO_InitStruct->instance, GPIO_InitStruct->pinx, kOutput);
    ...         
    }
    /* config pinMux */
    PORT_PinMuxConfig(GPIO_InitStruct->instance, GPIO_InitStruct->pinx, kPinAlt1);
}

由此可見,第二層的函數(shù)調(diào)用內(nèi)部就是再次調(diào)用了四個(gè)函數(shù)。來(lái)進(jìn)行設(shè)置。依舊沒(méi)有涉及到真正的核心部分。

接下來(lái)我們進(jìn)入第三層的函數(shù)調(diào)用:
我現(xiàn)在逐個(gè)來(lái)進(jìn)行深入的分析,首先是第一個(gè)函數(shù):

  PORT_PinPullConfig();

該函數(shù)的函數(shù)原型及實(shí)現(xiàn)如下:

void PORT_PinPullConfig(uint32_t instance, uint8_t pin, PORT_Pull_Type pull)
{
    SIM->SCGC5 |= SIM_GPIOClockGateTable[instance];
    switch(pull)
    {
        case kPullDisabled:
            PORT_InstanceTable[instance]->PCR[pin] &= ~PORT_PCR_PE_MASK;
            break;
        case kPullUp:
            PORT_InstanceTable[instance]->PCR[pin] |= PORT_PCR_PE_MASK;
            PORT_InstanceTable[instance]->PCR[pin] |= PORT_PCR_PS_MASK;
            break;
        case kPullDown:
            PORT_InstanceTable[instance]->PCR[pin] |= PORT_PCR_PE_MASK;
            PORT_InstanceTable[instance]->PCR[pin] &= ~PORT_PCR_PS_MASK;
            break;
        default:
            break;
    }
}

該函數(shù)的功能就是通過(guò)編程人員選擇的引腳模式,對(duì)寄存器進(jìn)行配置,換句話說(shuō),到這里,就開始涉及到一些底層了。那么具體是如何做的呢?
首先,看第一句的代碼:

SIM->SCGC5 |= SIM_GPIOClockGateTable[instance];

對(duì)于這句代碼的分析如下:
在MK60D10.h文件中定義了如下語(yǔ)句:

    #define SIM_BASE                                 0x40047000u
    #define SIM                                      (SIM_Type *)SIM_BASE

在這之中,SIM_Type 是一個(gè)結(jié)構(gòu)體,定義在MK60D10.h文件中。這兩句話表示:SIM是一個(gè)首地址為0x40047000的SIM_Type類型的結(jié)構(gòu)體。在這個(gè)結(jié)構(gòu)體中,定義了如下一句代碼:

  __IO uint32_t SCGC5;                             /**< System Clock Gating Control Register 5, offset: 0x1038 */

其實(shí)到了這個(gè)地步,就是實(shí)實(shí)在在和底層硬件相關(guān)了。單單看注釋很簡(jiǎn)單,系統(tǒng)時(shí)鐘門控寄存器5,偏移0x1038.但是這幾句話什么意思呢?先放在這里!這幾天估計(jì)還不會(huì)有什么時(shí)間進(jìn)行系統(tǒng)的學(xué)習(xí),只是抽點(diǎn)時(shí)間零敲碎打。

今天的后面幾步是沒(méi)有什么時(shí)間做完了!明天繼續(xù),這兩天時(shí)間很緊,估計(jì)不會(huì)參閱什么文檔了!只是跟著代碼走,看到哪算哪!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 上次我們說(shuō)到SCGC5,也就是系統(tǒng)門控時(shí)鐘5,這個(gè)是SIM模塊里面的寄存器。那么今天我們就來(lái)看看,這個(gè)SIM模塊究...
    Cheer_up閱讀 1,506評(píng)論 4 1
  • 今天把最后的配置講完,不過(guò)可能要分兩次。首先是下面的函數(shù): 表示將上面的寄存器的相應(yīng)位設(shè)置為0或是1,在實(shí)際的功能...
    Cheer_up閱讀 636評(píng)論 0 1
  • 今天要探究的是下面的函數(shù) 第一句代碼昨天我已經(jīng)研究過(guò)了,這里又出現(xiàn)了一次,可見寫這個(gè)函數(shù)的人,為了保證每一個(gè)函數(shù)的...
    Cheer_up閱讀 295評(píng)論 0 1
  • 其實(shí)這篇文章主要是介紹自己為其寫的GPIO庫(kù),自己借鑒了原子寫的STM32,野火寫的K60,還有LPC官方庫(kù),然后...
    楊奉武閱讀 1,007評(píng)論 0 0
  • 樹莓派GPIO最入門教程:先從控制一個(gè)LED小燈開始 玩轉(zhuǎn)樹莓派2017-07-09 00:00 點(diǎn)亮LED 概述...
    玩轉(zhuǎn)樹莓派閱讀 32,600評(píng)論 0 73

友情鏈接更多精彩內(nèi)容