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腳位,實拍如下圖:
正面圖
反面圖,焊接的還不錯,給自己打80分
14. 回到MDK,用MicroUSB傳輸線連接電腦和開發板,會自動安裝OpenSDA的驅動,按下Download,MDK會自動抓取燒寫工具
15. P&E燒寫管理員,支援板上的燒寫動作,但似乎無法Debug,點選Connect
16. 按下YES,擦除MCU上的Flash並把程式燒寫進去
17. 燒寫好後,輸出如下圖Log訊息
18. 在開發板上按下Reset按鍵,即可觀看D3 LED每一秒閃爍一次,其中板上四個LED的對應如下:
J9-3
19. 將杜邦線一端接上5V,一端接上PTD上的第一隻腳位,即PTD0,這時候D3 LED會變成每0.5秒閃爍一次,接線如下圖
至此,完成了整個實測,大家可以使用我的GPIO函式庫功能輕鬆達到你們想要的應用
Mop兄弟的分享十分嚴謹,贊一個
赞!