Arm Community
Arm Community
  • Site
  • User
  • Site
  • Search
  • User
  • Groups
    • Research Collaboration and Enablement
    • DesignStart
    • Education Hub
    • Innovation
    • Open Source Software and Platforms
  • Forums
    • AI and ML forum
    • Architectures and Processors forum
    • Arm Development Platforms forum
    • Arm Development Studio forum
    • Arm Virtual Hardware forum
    • Automotive forum
    • Compilers and Libraries forum
    • Graphics, Gaming, and VR forum
    • High Performance Computing (HPC) forum
    • Infrastructure Solutions forum
    • Internet of Things (IoT) forum
    • Keil forum
    • Morello Forum
    • Operating Systems forum
    • SoC Design and Simulation forum
    • 中文社区论区
  • Blogs
    • AI and ML blog
    • Announcements
    • Architectures and Processors blog
    • Automotive blog
    • Graphics, Gaming, and VR blog
    • High Performance Computing (HPC) blog
    • Infrastructure Solutions blog
    • Innovation blog
    • Internet of Things (IoT) blog
    • Operating Systems blog
    • Research Articles
    • SoC Design and Simulation blog
    • Smart Homes
    • Tools, Software and IDEs blog
    • Works on Arm blog
    • 中文社区博客
  • Support
    • Arm Support Services
    • Documentation
    • Downloads
    • Training
    • Arm Approved program
    • Arm Design Reviews
  • Community Help
  • More
  • Cancel
恩智浦汽车电子MCU讨论区博客
  • 中文社区
  • Jump...
恩智浦汽车电子MCU讨论区博客
恩智浦汽车电子MCU讨论区博客 [TRK-KEA使用经验分享] GPIO函式庫
  • Blog
  • 恩智浦汽车电子MCU讨论区博
  • Videos
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • Jump...
  • Cancel
  • New
恩智浦汽车电子MCU讨论区博客 requires membership for participation - click to join
More blogs in 恩智浦汽车电子MCU讨论区博客
  • 恩智浦汽车电子MCU讨论区博客

 

Tags
Actions
  • RSS
  • More
  • Cancel
Related blog posts
Related forum threads

[TRK-KEA使用经验分享] GPIO函式庫

Ming-Hung Liu
Ming-Hung Liu
October 30, 2015

1. 首先,官方提供了多種開發環境,範例包含了IAR,CodeWarrior,MDK,所以我使用MDK來玩這塊板子

題外話: CodeWarrior要額外付費,另外官方有針對Kinetis推出免費的IDE KDS,但安裝過後加上KSDK,發現SKEAZN642不支援,所以各位就用自己擅長的IAR或者MDK即可

2. 打開MDK,先安裝KEA的基礎函式庫包,左邊選擇Freescale>KEAxx Series,右邊在Device Specific點開後,按下Install,完成後如下圖:

3. 下載MDK範例http://cache.freescale.com/files/microcontrollers/software/board_support_packages/TRK-KEA64_KEIL_LABTS1.zip ,本篇使用Lab1做修改

4. 打開TRK-KEA64_Keil_Lab1.uvprojx專案,發現要點個LED燈都嫌麻煩,所以就自己寫一個函式庫,並分享給大家後續開發用,根據RMhttp://cache.freescale.com/files/microcontrollers/doc/ref_manual/KEA64RM.pdf,知道Register配置後,就可以開始著手了

5. 在專案上的Sources的資料夾點選滑鼠右鍵,選擇Add New Item to group

6. 選擇創建C File,名稱取名為gpio.c,位置記得選擇Sources,按下Add

7. 同樣的,在Header資料夾裡面創建gpio.h,種類為Header File,點選Add

8. 首先定義標頭檔案gpio.h,參考RM得知幾個Register的address,定義在原來的函式庫包SKEAZN642.h,如下定義:

/* ----------------------------------------------------------------------------
   -- GPIO Peripheral Access Layer
   ---------------------------------------------------------------------------- */

/*!
 * @addtogroup GPIO_Peripheral_Access_Layer GPIO Peripheral Access Layer
 * @{
 */

/** GPIO - Register Layout Typedef */
typedef struct {
  __IO uint32_t PDOR;                              /**< Port Data Output Register, offset: 0x0 */
  __O  uint32_t PSOR;                              /**< Port Set Output Register, offset: 0x4 */
  __O  uint32_t PCOR;                              /**< Port Clear Output Register, offset: 0x8 */
  __O  uint32_t PTOR;                              /**< Port Toggle Output Register, offset: 0xC */
  __I  uint32_t PDIR;                              /**< Port Data Input Register, offset: 0x10 */
  __IO uint32_t PDDR;                              /**< Port Data Direction Register, offset: 0x14 */
  __IO uint32_t PIDR;                              /**< Port Input Disable Register, offset: 0x18 */
} GPIO_Type;

/* ----------------------------------------------------------------------------
   -- GPIO Register Masks
   ---------------------------------------------------------------------------- */

/*!
 * @addtogroup GPIO_Register_Masks GPIO Register Masks
 * @{
 */

/* PDOR Bit Fields */
#define GPIO_PDOR_PDO_MASK                       0xFFFFFFFFu
#define GPIO_PDOR_PDO_SHIFT                      0
#define GPIO_PDOR_PDO(x)                         (((uint32_t)(((uint32_t)(x))<<GPIO_PDOR_PDO_SHIFT))&GPIO_PDOR_PDO_MASK)
/* PSOR Bit Fields */
#define GPIO_PSOR_PTSO_MASK                      0xFFFFFFFFu
#define GPIO_PSOR_PTSO_SHIFT                     0
#define GPIO_PSOR_PTSO(x)                        (((uint32_t)(((uint32_t)(x))<<GPIO_PSOR_PTSO_SHIFT))&GPIO_PSOR_PTSO_MASK)
/* PCOR Bit Fields */
#define GPIO_PCOR_PTCO_MASK                      0xFFFFFFFFu
#define GPIO_PCOR_PTCO_SHIFT                     0
#define GPIO_PCOR_PTCO(x)                        (((uint32_t)(((uint32_t)(x))<<GPIO_PCOR_PTCO_SHIFT))&GPIO_PCOR_PTCO_MASK)
/* PTOR Bit Fields */
#define GPIO_PTOR_PTTO_MASK                      0xFFFFFFFFu
#define GPIO_PTOR_PTTO_SHIFT                     0
#define GPIO_PTOR_PTTO(x)                        (((uint32_t)(((uint32_t)(x))<<GPIO_PTOR_PTTO_SHIFT))&GPIO_PTOR_PTTO_MASK)
/* PDIR Bit Fields */
#define GPIO_PDIR_PDI_MASK                       0xFFFFFFFFu
#define GPIO_PDIR_PDI_SHIFT                      0
#define GPIO_PDIR_PDI(x)                         (((uint32_t)(((uint32_t)(x))<<GPIO_PDIR_PDI_SHIFT))&GPIO_PDIR_PDI_MASK)
/* PDDR Bit Fields */
#define GPIO_PDDR_PDD_MASK                       0xFFFFFFFFu
#define GPIO_PDDR_PDD_SHIFT                      0
#define GPIO_PDDR_PDD(x)                         (((uint32_t)(((uint32_t)(x))<<GPIO_PDDR_PDD_SHIFT))&GPIO_PDDR_PDD_MASK)
/* PIDR Bit Fields */
#define GPIO_PIDR_PID_MASK                       0xFFFFFFFFu
#define GPIO_PIDR_PID_SHIFT                      0
#define GPIO_PIDR_PID(x)                         (((uint32_t)(((uint32_t)(x))<<GPIO_PIDR_PID_SHIFT))&GPIO_PIDR_PID_MASK)

/*!
 * @}
 */ /* end of group GPIO_Register_Masks */


/* GPIO - Peripheral instance base addresses */
/** Peripheral GPIOA base address */
#define GPIOA_BASE                               (0x400FF000u)
/** Peripheral GPIOA base pointer */
#define GPIOA                                    ((GPIO_Type *)GPIOA_BASE)
/** Peripheral GPIOB base address */
#define GPIOB_BASE                               (0x400FF040u)
/** Peripheral GPIOB base pointer */
#define GPIOB                                    ((GPIO_Type *)GPIOB_BASE)
/** Array initializer of GPIO peripheral base pointers */
#define GPIO_BASES                               { GPIOA, GPIOB }

/*!
 * @}
 */ /* end of group GPIO_Peripheral_Access_Layer */

9. 有了這些定義的Address後,要封裝成簡單易用的就不是很困難了,當然RM也可以查的到,輸入以下原始碼在gpio.h

/*
    Title: GPIO library for TRK-KEA
    File: gpio.h
    Author: MOP
    Date: 2015/10/30
    License: GNU GPL
*/

#include "derivative.h"

typedef enum
{
    GPIO_A0,
    GPIO_A1,
    GPIO_A2,
    GPIO_A3,
    GPIO_A4,
    GPIO_A5,
    GPIO_A6,
    GPIO_A7,
    GPIO_B0,
    GPIO_B1,
    GPIO_B2,
    GPIO_B3,
    GPIO_B4,
    GPIO_B5,
    GPIO_B6,
    GPIO_B7,
    GPIO_C0,
    GPIO_C1,
    GPIO_C2,
    GPIO_C3,
    GPIO_C4,
    GPIO_C5,
    GPIO_C6,
    GPIO_C7,
    GPIO_D0,
    GPIO_D1,
    GPIO_D2,
    GPIO_D3,
    GPIO_D4,
    GPIO_D5,
    GPIO_D6,
    GPIO_D7,
    GPIO_E0,
    GPIO_E1,
    GPIO_E2,
    GPIO_E3,
    GPIO_E4,
    GPIO_E5,
    GPIO_E6,
    GPIO_E7,
    GPIO_F0,
    GPIO_F1,
    GPIO_F2,
    GPIO_F3,
    GPIO_F4,
    GPIO_F5,
    GPIO_F6,
    GPIO_F7,
    GPIO_G0,
    GPIO_G1,
    GPIO_G2,
    GPIO_G3,
    GPIO_G4,
    GPIO_G5,
    GPIO_G6,
    GPIO_G7,
    GPIO_H0,
    GPIO_H1,
    GPIO_H2,
    GPIO_H3,
    GPIO_H4,
    GPIO_H5,
    GPIO_H6,
    GPIO_H7,    
}gpio_t;

typedef enum
{
    LOW,
    HIGH,
}level;

typedef enum
{
    DISABLE,
    ENABLE,
}pullup_t;


int gpio_set_input(gpio_t num,pullup_t pullup);

int gpio_set_output(gpio_t num);

int gpio_output_high(gpio_t num);

int gpio_output_low(gpio_t num);

level gpio_input_read(gpio_t num);

int gpio_output_toggle(gpio_t num);

10. 以上定義了開發板所有的腳位,除了PTI,依照RM說明可能他是關閉功能的狀態,也沒查到相關資料,就先不管這個板子上PTI腳位

11. 再來實作各個Function,輸入以下程式碼在gpio.c中

/*
    Title: GPIO library for TRK-KEA
    File: gpio.c
    Author: MOP
    Date: 2015/10/30
    License: GNU GPL
*/

#include "gpio.h"

int gpio_set_input(gpio_t num,pullup_t pullup)
{    
        if(num>GPIO_H7)
            return -1;
        
      if(num<GPIO_E0)
        {        
            GPIOA->PDDR &= ~((uint32_t)(1)<<num);
            GPIOA->PIDR &= ~((uint32_t)(1)<<num);
            if(pullup==DISABLE)
                PORT->PUEL &= ~((uint32_t)(1)<<num);
            else
                PORT->PUEL |= ((uint32_t)(1)<<num);
        }
        else
        {
            num-=GPIO_E0;
            GPIOB->PDDR &= ~((uint32_t)(1)<<num);
            GPIOB->PIDR &= ~((uint32_t)(1)<<num);
            if(pullup==DISABLE)
                PORT->PUEH &= ~((uint32_t)(1)<<num);
            else
                PORT->PUEH |= ((uint32_t)(1)<<num);        
        }
        return 0;
}

int gpio_set_output(gpio_t num)
{    
        if(num>GPIO_H7)
            return -1;
        
      if(num<GPIO_E0)
        {        
            GPIOA->PDDR |= ((uint32_t)(1)<<num);
            GPIOA->PIDR |= ((uint32_t)(1)<<num);
        }
        else
        {
            num-=GPIO_E0;
            GPIOB->PDDR |= ((uint32_t)(1)<<num);
            GPIOB->PIDR |= ((uint32_t)(1)<<num);
        }
        return 0;
}

int gpio_output_high(gpio_t num)
{
        if(num<GPIO_E0)
        {        
            GPIOA->PSOR |= ((uint32_t)(1)<<num);
        }
        else
        {
            num-=GPIO_E0;
            GPIOB->PSOR |= ((uint32_t)(1)<<num);
        }
        return 0;
}

int gpio_output_low(gpio_t num)
{
        if(num<GPIO_E0)
        {        
            GPIOA->PCOR |= ((uint32_t)(1)<<num);
        }
        else
        {
            num-=GPIO_E0;
            GPIOB->PCOR |= ((uint32_t)(1)<<num);
        }
        return 0;
}

int gpio_output_toggle(gpio_t num)
{
        if(num<GPIO_E0)
        {        
            GPIOA->PTOR |= ((uint32_t)(1)<<num);
        }
        else
        {
            num-=GPIO_E0;
            GPIOB->PTOR |= ((uint32_t)(1)<<num);
        }    
        return 0;
}

level gpio_input_read(gpio_t num)
{
        if(num<GPIO_E0)
        {        
            if((GPIOA->PDIR & ((uint32_t)(1)<<num)) >> num)
                return HIGH;
            else
                return LOW;
            
        }
        else
        {
            num-=GPIO_E0;
            if((GPIOB->PDIR & ((uint32_t)(1)<<num)) >> num)
                return HIGH;
            else
                return LOW;
        }    
}

12. 以上根據RM各Register的功能來實作的,使用者現在可以輕鬆使用GPIO的功能

13. 改寫main函數,根據Lab1的文檔http://cache.freescale.com/files/microcontrollers/doc/app_note/AN4942.pdf ,改寫成閃燈功能,如下:

/***********************************************************************************************
*
* @brief    main() - Program entry function
* @param    none
* @return   none
*
************************************************************************************************/  
int main(void)
{
    UINT32 counter = 0;
    
    gpio_set_input(GPIO_D0,DISABLE); /*Set pin in port PTD0 as input*/
                                     /* Enable input in port PTD0*/
                                     /* No internal pullup */

    gpio_set_output(GPIO_C0); /* Set pin in port PTC0 as output*/
    
    Clk_Init();                         /* Configure clocks to run at 20 Mhz*/
    UART_Init();                        /*Initialize Uart 2 at 9600 bauds */
    Uart_SetCallback(Uart_Interrupt);   /* Set the callback function that the UART driver will call when receiving a char */
    NVIC_EnableIRQ(UART2_IRQn);         /* Enable UART2 interrupt*/
    
    for(;;) {    
        if(gpio_input_read(GPIO_D0)) /*If input in port PTD0 has logic 1*/
        {    
            gpio_output_high(GPIO_C0); /* Set output in port PTC0*/
            delay(500000);
            gpio_output_low(GPIO_C0); /* Clear output in port PTC0*/
            delay(500000);
        }
        else /*If input in port PTD0 has logic 0*/
        {
            gpio_output_high(GPIO_C0); /* Set output in port PTC0*/
            delay(1000000);
            gpio_output_low(GPIO_C0); /* Clear output in port PTC0*/
            delay(1000000);
        }
        counter++;
    }

}

其中delay函數是用估計的方式,且稍微跟實際時間做校正,單位為us,定義如下

void delay(uint32_t us)
{
    us*=4;
    while(us--);
}

以上完成了開發,文末會附上整個專案

13. 我將我的開發板焊接上杜邦母座,方便接線,包含PTA~PTI腳位跟兩隻GND和兩隻5V腳位,實拍如下圖:

IMAG1861.jpg

正面圖

IMAG1862.jpg

反面圖,焊接的還不錯,給自己打80分

14. 回到MDK,用MicroUSB傳輸線連接電腦和開發板,會自動安裝OpenSDA的驅動,按下Download,MDK會自動抓取燒寫工具

15. P&E燒寫管理員,支援板上的燒寫動作,但似乎無法Debug,點選Connect

16. 按下YES,擦除MCU上的Flash並把程式燒寫進去

17. 燒寫好後,輸出如下圖Log訊息

18. 在開發板上按下Reset按鍵,即可觀看D3 LED每一秒閃爍一次,其中板上四個LED的對應如下:

LED
PIN
Board
D3 LEDPTC0J9-1
D5 LEDPTC1J9-2
D6 LEDPTC2

J9-3

D8 LEDPTC3J9-4

19. 將杜邦線一端接上5V,一端接上PTD上的第一隻腳位,即PTD0,這時候D3 LED會變成每0.5秒閃爍一次,接線如下圖

IMAG1863.jpg

至此,完成了整個實測,大家可以使用我的GPIO函式庫功能輕鬆達到你們想要的應用

TRK-KEA64_Keil_Lab1.rar
Anonymous
  • Song Bin 宋斌
    Offline Song Bin 宋斌 over 7 years ago

    Mop兄弟的分享十分嚴謹,贊一個

    • Cancel
    • Up 0 Down
    • Reply
    • More
    • Cancel
  • 曾舒婷
    Offline 曾舒婷 over 7 years ago

    赞!

    • Cancel
    • Up 0 Down
    • Reply
    • More
    • Cancel
恩智浦汽车电子MCU讨论区博客
  • i.MX6-Android User Manual V2.2.pdf

    Grace
    Grace
    i.MX6Q Android manual
    • April 21, 2016
  • 恩智浦汽车电子MCU讨论区简介

    Song Bin 宋斌
    Song Bin 宋斌
    本讨论区是ARM中文社区子版块,专供中国用户使用中文讨论和分享恩智浦公司ARM相关汽车电子技术。                 您可以提问,分享文档,视频,发起投票。       本专区由恩智浦公司和ARM共同维护
    • February 18, 2016
  • [TRK-KEA使用经验分享] 第1篇:安装开发环境

    litx
    litx
    TRK-KEA64 光盘里工具和文档很全,软件安装基本是下一步。CodeWarrior Development Studio(开发工作室)是完整的用于编程应用中硬件bring-up的集成开发环境。 采用CodeWarrior IDE,开发人员可以得益于采用各种处理器和平台(从Motorola到TI到Intel)间的通用功能性。根据Gartner Dataquest的报告,CodeWarrior编译…
    • November 6, 2015