[原创] 【基于KW41Z的智能电力监测仪的设计】第五贴:软件设计—GPIO学习篇

传媒学子   2017-7-11 00:20 楼主
【基于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 未使能。
改写主程序:
  1. #include "fsl_debug_console.h"[/align]#include "fsl_port.h"
  2. #include "fsl_gpio.h"
  3. #include "fsl_common.h"
  4. #include "board.h"
  5. #include "pin_mux.h"
  6. #include "clock_config.h"
  7. /*******************************************************************************
  8. * Definitions
  9. ******************************************************************************/
  10. //#define BOARD_LED_GPIO BOARD_LED_RED_GPIO
  11. //#define BOARD_LED_GPIO_PIN BOARD_LED_RED_GPIO_PIN
  12. #define BOARD_LED_GPIO BOARD_LED_GREEN_GPIO
  13. #define BOARD_LED_GPIO_PIN BOARD_LED_GREEN_GPIO_PIN
  14. #define BOARD_SW_GPIO BOARD_SW3_GPIO
  15. #define BOARD_SW_PORT BOARD_SW3_PORT
  16. #define BOARD_SW_GPIO_PIN BOARD_SW3_GPIO_PIN
  17. #define BOARD_SW_IRQ BOARD_SW3_IRQ
  18. #define BOARD_SW_IRQ_HANDLER BOARD_SW3_IRQ_HANDLER
  19. #define BOARD_SW_NAME BOARD_SW3_NAME
  20. /*******************************************************************************
  21. * Prototypes
  22. ******************************************************************************/
  23. /*******************************************************************************
  24. * Variables
  25. ******************************************************************************/
  26. /* Whether the SW button is pressed */
  27. volatile bool g_ButtonPress = false;
  28. /*******************************************************************************
  29. * Code
  30. ******************************************************************************/
  31. /*!
  32. * [url=home.php?mod=space&uid=159083]@brief[/url] Interrupt service fuction of switch. 中断服务函数
  33. *
  34. * This function toggles the LED
  35. */
  36. void BOARD_SW_IRQ_HANDLER(void)
  37. {
  38. /* Clear external interrupt flag. */
  39. GPIO_ClearPinsInterruptFlags(BOARD_SW_GPIO, 1U << BOARD_SW_GPIO_PIN);//1右移四位0x10
  40. /* Change state of button. */
  41. g_ButtonPress = true;
  42. /* Toggle LED. */
  43. GPIO_TogglePinsOutput(BOARD_LED_GPIO, 1U << BOARD_LED_GPIO_PIN);
  44. GPIO_TogglePinsOutput(BOARD_LED3_GPIO, 1U << BOARD_LED3_GPIO_PIN);
  45. }
  46. /*!
  47. * @brief Main function
  48. */
  49. int main(void)
  50. {
  51. /* Define the init structure for the input switch pin */
  52. gpio_pin_config_t sw_config = {
  53. kGPIO_DigitalInput, 0,
  54. };
  55. /* Define the init structure for the output LED pin */
  56. gpio_pin_config_t led_config = {
  57. kGPIO_DigitalOutput, 0,
  58. }; //配置结构体 设置输入,输出(输入/输出,输出1或者0),当在输入状态下,输出没有效果
  59. gpio_pin_config_t led3_config = {
  60. kGPIO_DigitalOutput, 1,
  61. };
  62. BOARD_InitPins();
  63. BOARD_BootClockRUN();
  64. BOARD_InitDebugConsole();
  65. /* Print a note to terminal. */
  66. PRINTF("\r\n GPIO Driver example\r\n");
  67. PRINTF("\r\n Press %s to turn on/off a LED \r\n", BOARD_SW_NAME);
  68. /* Init input switch GPIO. */
  69. PORT_SetPinInterruptConfig(BOARD_SW_PORT, BOARD_SW_GPIO_PIN, kPORT_InterruptFallingEdge);
  70. EnableIRQ(BOARD_SW_IRQ);
  71. GPIO_PinInit(BOARD_SW_GPIO, BOARD_SW_GPIO_PIN, &sw_config);
  72. /* Init output LED GPIO. */
  73. GPIO_PinInit(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, &led_config);
  74. //以下为修改部分
  75. GPIO_PinInit(BOARD_LED3_GPIO, BOARD_LED3_GPIO_PIN, &led3_config);
  76. //////////////////以上为修改部分/////////////////
  77. while (1)
  78. {
  79. if (g_ButtonPress)
  80. {
  81. PRINTF(" %s is pressed \r\n", BOARD_SW_NAME);
  82. /* Reset state of button. */
  83. g_ButtonPress = false;
  84. }
  85. }
  86. }
改写board.h文件:
  1. #ifndef _BOARD_H_
  2. #define _BOARD_H_
  3. #include "clock_config.h"
  4. #include "fsl_gpio.h"
  5. /*******************************************************************************
  6. * Definitions
  7. ******************************************************************************/
  8. /*! @brief The board name */
  9. #define BOARD_NAME "FRDM-KW41Z"
  10. /*! @brief The UART to use for debug messages. */
  11. #define BOARD_USE_LPUART
  12. #define BOARD_DEBUG_UART_TYPE DEBUG_CONSOLE_DEVICE_TYPE_LPUART
  13. #define BOARD_DEBUG_UART_BASEADDR (uint32_t) LPUART0
  14. #define BOARD_DEBUG_UART_CLKSRC kCLOCK_Osc0ErClk
  15. #define BOARD_DEBUG_UART_CLK_FREQ CLOCK_GetOsc0ErClkFreq()
  16. #define BOARD_UART_IRQ LPUART0_IRQn
  17. #define BOARD_UART_IRQ_HANDLER LPUART0_IRQHandler
  18. #ifndef BOARD_DEBUG_UART_BAUDRATE
  19. #define BOARD_DEBUG_UART_BAUDRATE 115200
  20. #endif /* BOARD_DEBUG_UART_BAUDRATE */
  21. /*! @brief The adc16 alternate reference voltage pin is used for frdmkw41 board rev A2 */
  22. #define BOARD_ADC_USE_ALT_VREF 1U
  23. /*! @brief The i2c instance used for i2c connection by default */
  24. #define BOARD_I2C_BASEADDR I2C1
  25. /*! @brief TSI electrodes mapping */
  26. #define BOARD_TSI_ELECTRODE_1 4U
  27. #define BOARD_TSI_ELECTRODE_2 7U
  28. #define BOARD_TSI_ELECTRODE_CNT 2U
  29. #define BOARD_ACCEL_I2C_BASEADDR I2C1
  30. /*! @brief The CMP instance/channel used for board. */
  31. #define BOARD_CMP_BASEADDR CMP0
  32. #define BOARD_CMP_CHANNEL 1U
  33. /*! @brief The rtc instance used for board. */
  34. #define BOARD_RTC_FUNC_BASEADDR RTC
  35. /*! @brief Define the port interrupt number for the board switches */
  36. #define BOARD_SW3_GPIO GPIOC
  37. #define BOARD_SW3_PORT PORTC
  38. #define BOARD_SW3_GPIO_PIN 4U
  39. #define BOARD_SW3_IRQ PORTB_PORTC_IRQn
  40. #define BOARD_SW3_IRQ_HANDLER PORTB_PORTC_IRQHandler
  41. #define BOARD_SW3_NAME "SW3"
  42. /* Board led color mapping */
  43. #define LOGIC_LED_ON 0U
  44. #define LOGIC_LED_OFF 1U
  45. #define BOARD_LED_RED_GPIO GPIOC
  46. #define BOARD_LED_RED_GPIO_PORT PORTC
  47. #define BOARD_LED_RED_GPIO_PIN 1U
  48. #define BOARD_LED_GREEN_GPIO GPIOA
  49. #define BOARD_LED_GREEN_GPIO_PORT PORTA
  50. #define BOARD_LED_GREEN_GPIO_PIN 19U
  51. #define BOARD_LED_BLUE_GPIO GPIOA
  52. #define BOARD_LED_BLUE_GPIO_PORT PORTA
  53. #define BOARD_LED_BLUE_GPIO_PIN 18U
  54. //以下为个人改写部分
  55. #define BOARD_LED3_GPIO GPIOB
  56. #define BOARD_LED3_GPIO_PORT PORTB
  57. #define BOARD_LED3_GPIO_PIN 0U
  58. /*#define LED3_INIT(output) \
  59. GPIO_PinInit(BOARD_LED3_GPIO, BOARD_LED3_GPIO_PIN, \
  60. &(gpio_pin_config_t){kGPIO_DigitalOutput, (output)}) /*!< Enable target LED3 */
  61. /*#define LED3_ON() \
  62. GPIO_ClearPinsOutput(BOARD_LED3_GPIO, 1U << BOARD_LED3_GPIO_PIN) /*!< Turn on target LED3 */
  63. /*#define LED3_OFF() \
  64. GPIO_SetPinsOutput(BOARD_LED3_GPIO, 1U << BOARD_LED3_GPIO_PIN) /*!< Turn off target LED3 */
  65. /*#define LED3_TOGGLE() \
  66. GPIO_TogglePinsOutput(BOARD_LED3_GPIO, 1U << BOARD_LED3_GPIO_PIN) /*!< Toggle on target LED3 */
  67. #define LED_RED_INIT(output) \
  68. GPIO_PinInit(BOARD_LED_RED_GPIO, BOARD_LED_RED_GPIO_PIN, \
  69. &(gpio_pin_config_t){kGPIO_DigitalOutput, (output)}) /*!< Enable target LED_RED */
  70. #define LED_RED_ON() \
  71. GPIO_ClearPinsOutput(BOARD_LED_RED_GPIO, 1U << BOARD_LED_RED_GPIO_PIN) /*!< Turn on target LED_RED */
  72. #define LED_RED_OFF() \
  73. GPIO_SetPinsOutput(BOARD_LED_RED_GPIO, 1U << BOARD_LED_RED_GPIO_PIN) /*!< Turn off target LED_RED */
  74. #define LED_RED_TOGGLE() \
  75. GPIO_TogglePinsOutput(BOARD_LED_RED_GPIO, 1U << BOARD_LED_RED_GPIO_PIN) /*!< Toggle on target LED_RED */
  76. #define LED_GREEN_INIT(output) \
  77. GPIO_PinInit(BOARD_LED_GREEN_GPIO, BOARD_LED_GREEN_GPIO_PIN, \
  78. &(gpio_pin_config_t){kGPIO_DigitalOutput, (output)}) /*!< Enable target LED_GREEN */
  79. #define LED_GREEN_ON() \
  80. GPIO_ClearPinsOutput(BOARD_LED_GREEN_GPIO, 1U << BOARD_LED_GREEN_GPIO_PIN) /*!< Turn on target LED_GREEN */
  81. #define LED_GREEN_OFF() \
  82. GPIO_SetPinsOutput(BOARD_LED_GREEN_GPIO, 1U << BOARD_LED_GREEN_GPIO_PIN) /*!< Turn off target LED_GREEN */
  83. #define LED_GREEN_TOGGLE() \
  84. GPIO_TogglePinsOutput(BOARD_LED_GREEN_GPIO, 1U << BOARD_LED_GREEN_GPIO_PIN) /*!< Toggle on target LED_GREEN */
  85. #define LED_BLUE_INIT(output) \
  86. GPIO_PinInit(BOARD_LED_BLUE_GPIO, BOARD_LED_BLUE_GPIO_PIN, \
  87. &(gpio_pin_config_t){kGPIO_DigitalOutput, (output)}) /*!< Enable target LED_BLUE */
  88. #define LED_BLUE_ON() \
  89. GPIO_ClearPinsOutput(BOARD_LED_BLUE_GPIO, 1U << BOARD_LED_BLUE_GPIO_PIN) /*!< Turn on target LED_BLUE */
  90. #define LED_BLUE_OFF() \
  91. GPIO_SetPinsOutput(BOARD_LED_BLUE_GPIO, 1U << BOARD_LED_BLUE_GPIO_PIN) /*!< Turn off target LED_BLUE */
  92. #define LED_BLUE_TOGGLE() \
  93. GPIO_TogglePinsOutput(BOARD_LED_BLUE_GPIO, 1U << BOARD_LED_BLUE_GPIO_PIN) /*!< Toggle on target LED_BLUE */
  94. #if defined(__cplusplus)
  95. extern "C" {
  96. #endif /* __cplusplus */
  97. /*******************************************************************************
  98. * API
  99. ******************************************************************************/
改写 BOARD_InitPins(void):
  1. #include "fsl_common.h"
  2. #include "fsl_port.h"
  3. #include "pin_mux.h"
  4. /*******************************************************************************
  5. * Code
  6. ******************************************************************************/
  7. void BOARD_InitPins(void)
  8. {
  9. /* Initialize LPUART0 pins below */
  10. /* Ungate the port clock */
  11. CLOCK_EnableClock(kCLOCK_PortC);
  12. CLOCK_EnableClock(kCLOCK_PortA);
  13. CLOCK_EnableClock(kCLOCK_PortB);
  14. /* Affects PORTC_PCR6 register */
  15. PORT_SetPinMux(PORTC, 6U, kPORT_MuxAlt4);
  16. /* Affects PORTC_PCR7 register */
  17. PORT_SetPinMux(PORTC, 7U, kPORT_MuxAlt4);
  18. /* Affects PORTC_PCR4 register */
  19. port_pin_config_t config;
  20. config.pullSelect = kPORT_PullUp;
  21. config.mux = kPORT_MuxAsGpio;
  22. PORT_SetPinConfig(PORTC, 4U, &config); //PTC4设置为上拉
  23. /* LED PIN_MUX Configuration */
  24. PORT_SetPinMux(PORTC, 1U, kPORT_MuxAsGpio);
  25. PORT_SetPinMux(PORTA, 19U, kPORT_MuxAsGpio);
  26. PORT_SetPinMux(PORTB, 0U, kPORT_MuxAsGpio);
  27. }
4.学习总结
经过今天的学习,我基本上了解了GPIO的用法,我所面临的问题主要是:
1) 如何将ADE7758驱动程序移植至KW41Z;
2) 如何将BLE与Thread、串口程序整合到一起。
最后将程序压缩包和GPIO改写后的测试视频上传到论坛,供坛友参考。
此内容由EEWORLD论坛网友传媒学子原创,如需转载或用于商业用途需征得作者同意并注明出处 本帖最后由 传媒学子 于 2017-7-11 00:31 编辑

回复评论 (1)

小伙子写的挺好
点赞  2017-7-11 10:18
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复