【基于KW41Z的智能电力监测仪的设计】第五贴:软件设计—GPIO学习篇
0 .题外话
借参加NXP设计大赛的机会,想一窥嵌入式编程的大门。以前,学习总是不踏实,好高骛远。虽然,玩过很多单片机,但总是不能学到器件的精髓。虽然英语也看得懂,但总是很懒。这次正好在毕业到入职之间有1个月的空闲时间,与其出去瞎转,倒不如认真学习学习嵌入式编程之道。认真从恩智浦这款优秀的微处理器上,得以领略到高层次编程的乐趣。
因为,之前学习过51之类的,都是从底层寄存器级开始编程,自己看着芯片手册写相关模块的程序,虽然很费时间,但毕竟习惯了那种学习方法,因此,刚刚接触到例程中的高层次的编程,则十分并不习惯。通过一下午的学习,基本上明白了NXP官方给的GPIO API库的使用方法,并且将原始程序进行了简单修改,实现了LED3和RGB(GREEN)的轮番点亮。
1. 首先介绍官方的例程效果
官方例程,按下SW3,进入中断,RGB(RED)实现亮灭转换。
2. 遇到的困难
本想修改一下例程,让RGB(GREEN)点亮,但尝试了几次,没有想象中的容易,因此,就硬下心来,将例程一点一点的吃透。
3.我想把感悟分享给初学者:
感悟1:学习一款板子,必须要把这个板子的基本构造,原理图等熟悉一遍,我这里把FFRDM-KW41Z Freedom Development BoardUser's Guide分享给大家,见附件。看完了手册,我们知道了RGB是由三个LED组成的:RED\GREEN\BLUE,它们分别位PTC1\PTA19\PTA18;而另外一个LED3是红色LED,它位于PTB0。知道了具体的连接,再看例程,就能举一反三,触类旁通。
感悟2:注意到source目录下gpio_input_interrupt.c是整个工程的主函数所在。打开后,可看到与GPIO相关的定义都与Board有关,因此,很容易使人想起去改写"board.h"文件,但我依葫芦画瓢改写后,依然不能点亮LED3,这时应当注意到还有一个BOARD_InitPins(void)函数,打开这个函数则一目了然。其原因是:我没有注意BOARD_InitPins()函数内容,GPIO 未使能。
改写主程序:- #include "fsl_debug_console.h"[/align]#include "fsl_port.h"
- #include "fsl_gpio.h"
- #include "fsl_common.h"
- #include "board.h"
- #include "pin_mux.h"
- #include "clock_config.h"
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- //#define BOARD_LED_GPIO BOARD_LED_RED_GPIO
- //#define BOARD_LED_GPIO_PIN BOARD_LED_RED_GPIO_PIN
- #define BOARD_LED_GPIO BOARD_LED_GREEN_GPIO
- #define BOARD_LED_GPIO_PIN BOARD_LED_GREEN_GPIO_PIN
-
- #define BOARD_SW_GPIO BOARD_SW3_GPIO
- #define BOARD_SW_PORT BOARD_SW3_PORT
- #define BOARD_SW_GPIO_PIN BOARD_SW3_GPIO_PIN
- #define BOARD_SW_IRQ BOARD_SW3_IRQ
- #define BOARD_SW_IRQ_HANDLER BOARD_SW3_IRQ_HANDLER
- #define BOARD_SW_NAME BOARD_SW3_NAME
-
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
-
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- /* Whether the SW button is pressed */
- volatile bool g_ButtonPress = false;
-
- /*******************************************************************************
- * Code
- ******************************************************************************/
- /*!
- * [url=home.php?mod=space&uid=159083]@brief[/url] Interrupt service fuction of switch. 中断服务函数
- *
- * This function toggles the LED
- */
- void BOARD_SW_IRQ_HANDLER(void)
- {
- /* Clear external interrupt flag. */
- GPIO_ClearPinsInterruptFlags(BOARD_SW_GPIO, 1U << BOARD_SW_GPIO_PIN);//1右移四位0x10
- /* Change state of button. */
- g_ButtonPress = true;
- /* Toggle LED. */
- GPIO_TogglePinsOutput(BOARD_LED_GPIO, 1U << BOARD_LED_GPIO_PIN);
- GPIO_TogglePinsOutput(BOARD_LED3_GPIO, 1U << BOARD_LED3_GPIO_PIN);
- }
-
- /*!
- * @brief Main function
- */
- int main(void)
- {
- /* Define the init structure for the input switch pin */
- gpio_pin_config_t sw_config = {
- kGPIO_DigitalInput, 0,
- };
-
- /* Define the init structure for the output LED pin */
- gpio_pin_config_t led_config = {
- kGPIO_DigitalOutput, 0,
- }; //配置结构体 设置输入,输出(输入/输出,输出1或者0),当在输入状态下,输出没有效果
-
- gpio_pin_config_t led3_config = {
- kGPIO_DigitalOutput, 1,
- };
-
- BOARD_InitPins();
- BOARD_BootClockRUN();
- BOARD_InitDebugConsole();
-
- /* Print a note to terminal. */
- PRINTF("\r\n GPIO Driver example\r\n");
- PRINTF("\r\n Press %s to turn on/off a LED \r\n", BOARD_SW_NAME);
-
- /* Init input switch GPIO. */
- PORT_SetPinInterruptConfig(BOARD_SW_PORT, BOARD_SW_GPIO_PIN, kPORT_InterruptFallingEdge);
- EnableIRQ(BOARD_SW_IRQ);
- GPIO_PinInit(BOARD_SW_GPIO, BOARD_SW_GPIO_PIN, &sw_config);
-
- /* Init output LED GPIO. */
- GPIO_PinInit(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, &led_config);
-
- //以下为修改部分
- GPIO_PinInit(BOARD_LED3_GPIO, BOARD_LED3_GPIO_PIN, &led3_config);
- //////////////////以上为修改部分/////////////////
-
- while (1)
- {
- if (g_ButtonPress)
- {
- PRINTF(" %s is pressed \r\n", BOARD_SW_NAME);
- /* Reset state of button. */
- g_ButtonPress = false;
- }
- }
- }
改写board.h文件:
- #ifndef _BOARD_H_
- #define _BOARD_H_
-
- #include "clock_config.h"
- #include "fsl_gpio.h"
-
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- /*! @brief The board name */
- #define BOARD_NAME "FRDM-KW41Z"
-
- /*! @brief The UART to use for debug messages. */
- #define BOARD_USE_LPUART
- #define BOARD_DEBUG_UART_TYPE DEBUG_CONSOLE_DEVICE_TYPE_LPUART
- #define BOARD_DEBUG_UART_BASEADDR (uint32_t) LPUART0
- #define BOARD_DEBUG_UART_CLKSRC kCLOCK_Osc0ErClk
- #define BOARD_DEBUG_UART_CLK_FREQ CLOCK_GetOsc0ErClkFreq()
- #define BOARD_UART_IRQ LPUART0_IRQn
- #define BOARD_UART_IRQ_HANDLER LPUART0_IRQHandler
-
- #ifndef BOARD_DEBUG_UART_BAUDRATE
- #define BOARD_DEBUG_UART_BAUDRATE 115200
- #endif /* BOARD_DEBUG_UART_BAUDRATE */
-
- /*! @brief The adc16 alternate reference voltage pin is used for frdmkw41 board rev A2 */
- #define BOARD_ADC_USE_ALT_VREF 1U
-
- /*! @brief The i2c instance used for i2c connection by default */
- #define BOARD_I2C_BASEADDR I2C1
-
- /*! @brief TSI electrodes mapping */
- #define BOARD_TSI_ELECTRODE_1 4U
- #define BOARD_TSI_ELECTRODE_2 7U
- #define BOARD_TSI_ELECTRODE_CNT 2U
-
- #define BOARD_ACCEL_I2C_BASEADDR I2C1
-
- /*! @brief The CMP instance/channel used for board. */
- #define BOARD_CMP_BASEADDR CMP0
- #define BOARD_CMP_CHANNEL 1U
-
- /*! @brief The rtc instance used for board. */
- #define BOARD_RTC_FUNC_BASEADDR RTC
-
- /*! @brief Define the port interrupt number for the board switches */
- #define BOARD_SW3_GPIO GPIOC
- #define BOARD_SW3_PORT PORTC
- #define BOARD_SW3_GPIO_PIN 4U
- #define BOARD_SW3_IRQ PORTB_PORTC_IRQn
- #define BOARD_SW3_IRQ_HANDLER PORTB_PORTC_IRQHandler
- #define BOARD_SW3_NAME "SW3"
-
- /* Board led color mapping */
- #define LOGIC_LED_ON 0U
- #define LOGIC_LED_OFF 1U
- #define BOARD_LED_RED_GPIO GPIOC
- #define BOARD_LED_RED_GPIO_PORT PORTC
- #define BOARD_LED_RED_GPIO_PIN 1U
- #define BOARD_LED_GREEN_GPIO GPIOA
- #define BOARD_LED_GREEN_GPIO_PORT PORTA
- #define BOARD_LED_GREEN_GPIO_PIN 19U
- #define BOARD_LED_BLUE_GPIO GPIOA
- #define BOARD_LED_BLUE_GPIO_PORT PORTA
- #define BOARD_LED_BLUE_GPIO_PIN 18U
- //以下为个人改写部分
- #define BOARD_LED3_GPIO GPIOB
- #define BOARD_LED3_GPIO_PORT PORTB
- #define BOARD_LED3_GPIO_PIN 0U
-
- /*#define LED3_INIT(output) \
- GPIO_PinInit(BOARD_LED3_GPIO, BOARD_LED3_GPIO_PIN, \
- &(gpio_pin_config_t){kGPIO_DigitalOutput, (output)}) /*!< Enable target LED3 */
- /*#define LED3_ON() \
- GPIO_ClearPinsOutput(BOARD_LED3_GPIO, 1U << BOARD_LED3_GPIO_PIN) /*!< Turn on target LED3 */
- /*#define LED3_OFF() \
- GPIO_SetPinsOutput(BOARD_LED3_GPIO, 1U << BOARD_LED3_GPIO_PIN) /*!< Turn off target LED3 */
- /*#define LED3_TOGGLE() \
- GPIO_TogglePinsOutput(BOARD_LED3_GPIO, 1U << BOARD_LED3_GPIO_PIN) /*!< Toggle on target LED3 */
-
-
-
- #define LED_RED_INIT(output) \
- GPIO_PinInit(BOARD_LED_RED_GPIO, BOARD_LED_RED_GPIO_PIN, \
- &(gpio_pin_config_t){kGPIO_DigitalOutput, (output)}) /*!< Enable target LED_RED */
- #define LED_RED_ON() \
- GPIO_ClearPinsOutput(BOARD_LED_RED_GPIO, 1U << BOARD_LED_RED_GPIO_PIN) /*!< Turn on target LED_RED */
- #define LED_RED_OFF() \
- GPIO_SetPinsOutput(BOARD_LED_RED_GPIO, 1U << BOARD_LED_RED_GPIO_PIN) /*!< Turn off target LED_RED */
- #define LED_RED_TOGGLE() \
- GPIO_TogglePinsOutput(BOARD_LED_RED_GPIO, 1U << BOARD_LED_RED_GPIO_PIN) /*!< Toggle on target LED_RED */
-
- #define LED_GREEN_INIT(output) \
- GPIO_PinInit(BOARD_LED_GREEN_GPIO, BOARD_LED_GREEN_GPIO_PIN, \
- &(gpio_pin_config_t){kGPIO_DigitalOutput, (output)}) /*!< Enable target LED_GREEN */
- #define LED_GREEN_ON() \
- GPIO_ClearPinsOutput(BOARD_LED_GREEN_GPIO, 1U << BOARD_LED_GREEN_GPIO_PIN) /*!< Turn on target LED_GREEN */
- #define LED_GREEN_OFF() \
- GPIO_SetPinsOutput(BOARD_LED_GREEN_GPIO, 1U << BOARD_LED_GREEN_GPIO_PIN) /*!< Turn off target LED_GREEN */
- #define LED_GREEN_TOGGLE() \
- GPIO_TogglePinsOutput(BOARD_LED_GREEN_GPIO, 1U << BOARD_LED_GREEN_GPIO_PIN) /*!< Toggle on target LED_GREEN */
-
- #define LED_BLUE_INIT(output) \
- GPIO_PinInit(BOARD_LED_BLUE_GPIO, BOARD_LED_BLUE_GPIO_PIN, \
- &(gpio_pin_config_t){kGPIO_DigitalOutput, (output)}) /*!< Enable target LED_BLUE */
- #define LED_BLUE_ON() \
- GPIO_ClearPinsOutput(BOARD_LED_BLUE_GPIO, 1U << BOARD_LED_BLUE_GPIO_PIN) /*!< Turn on target LED_BLUE */
- #define LED_BLUE_OFF() \
- GPIO_SetPinsOutput(BOARD_LED_BLUE_GPIO, 1U << BOARD_LED_BLUE_GPIO_PIN) /*!< Turn off target LED_BLUE */
- #define LED_BLUE_TOGGLE() \
- GPIO_TogglePinsOutput(BOARD_LED_BLUE_GPIO, 1U << BOARD_LED_BLUE_GPIO_PIN) /*!< Toggle on target LED_BLUE */
-
- #if defined(__cplusplus)
- extern "C" {
- #endif /* __cplusplus */
-
- /*******************************************************************************
- * API
- ******************************************************************************/
改写 BOARD_InitPins(void):
- #include "fsl_common.h"
- #include "fsl_port.h"
- #include "pin_mux.h"
-
- /*******************************************************************************
- * Code
- ******************************************************************************/
-
- void BOARD_InitPins(void)
- {
- /* Initialize LPUART0 pins below */
- /* Ungate the port clock */
- CLOCK_EnableClock(kCLOCK_PortC);
- CLOCK_EnableClock(kCLOCK_PortA);
- CLOCK_EnableClock(kCLOCK_PortB);
-
- /* Affects PORTC_PCR6 register */
- PORT_SetPinMux(PORTC, 6U, kPORT_MuxAlt4);
- /* Affects PORTC_PCR7 register */
- PORT_SetPinMux(PORTC, 7U, kPORT_MuxAlt4);
-
- /* Affects PORTC_PCR4 register */
- port_pin_config_t config;
- config.pullSelect = kPORT_PullUp;
- config.mux = kPORT_MuxAsGpio;
- PORT_SetPinConfig(PORTC, 4U, &config); //PTC4设置为上拉
-
- /* LED PIN_MUX Configuration */
- PORT_SetPinMux(PORTC, 1U, kPORT_MuxAsGpio);
- PORT_SetPinMux(PORTA, 19U, kPORT_MuxAsGpio);
- PORT_SetPinMux(PORTB, 0U, kPORT_MuxAsGpio);
-
- }
4.学习总结
经过今天的学习,我基本上了解了GPIO的用法,我所面临的问题主要是:
1) 如何将ADE7758驱动程序移植至KW41Z;
2) 如何将BLE与Thread、串口程序整合到一起。
最后将程序压缩包和GPIO改写后的测试视频上传到论坛,供坛友参考。
此内容由EEWORLD论坛网友传媒学子原创,如需转载或用于商业用途需征得作者同意并注明出处
本帖最后由 传媒学子 于 2017-7-11 00:31 编辑