查看: 1003|回复: 0
收起左侧

织女星开发板使用RISC-V核驱动GPIO

[复制链接]

  离线 

  • TA的每日心情
    奋斗
    2021-3-3 12:32
  • 签到天数: 10 天

    [LV.3]

    发表于 2020-10-22 21:27:20 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 皋陶 于 2020-10-22 21:25 编辑

    前言
    织女星开发板是OPEN-ISA社区为中国大陆地区定制的一款体积小、功耗超低和功能丰富的 RISC-V评估开发板,基于NXP半导体四核异构RV32M1主控芯片。

    • 两个RISC-V核:RI5CY + ZERO_RISCY。
    • 两个ARM核: Cortex-M4F + Cortex-M0+ 。


    4个核被分为两个子系统,大核CM4F/RI5CY和小核CM0+/ZERO-RISCY,片上集成1.25 MB Flash 、384 KB SRAM,其中1 MB的Flash被大核所使用,起始地址0x0000_0000,另外的256 KB Flash被小核所使用,起始地址0x0100_0000。利用该开发板,用户可以快速建立一个使用 RV32M1 的 RISC-V应用和演示系统。详细的介绍可以参考: 真正的RISC-V开发板——VEGA织女星开发板开箱评测 ,本篇文章介绍如何基于RISC-V RI5CY/ZERO内核来点亮板载的RGB_LED/STS_LED、读取按键输入,演示GPIO的输入输出和外部中断功能。

    准备工作


    在进行以下操作之前,要确保开发环境已经搭建完成,而且能正常下载调试。

    • 织女星开发板RISC-V开发环境:Eclipse + riscv32 工具链 + OpenOCD调试工具
    • 织女星开发板SDK包:rv32m1_sdk_riscv
    • 织女星开发板的原理图
    • RV32M1参考手册


    以上资料的获取、开发环境搭建和启动模式修改等教程,可以到官方中文论坛查找:www.open-isa.cn

    或者是参考我分享的以下文章:



    寄存器简介


    根据RV32M1参考手册GPIO章节的介绍,我们可以获得关于GPIO相关寄存器信息:

    各GPIO组的基地址:
    1. GPIOA——4802_0000h
    2. GPIOB——4802_0040h
    3. GPIOC——4802_0080h
    4. GPIOD——4802_00C0h
    5. GPIOE——4100_F000h
    复制代码

    这是一个32位的寄存器,每一个引脚都有对应的一个PORTx_PCRn,用来配置GPIO的以下功能:

    • 上下拉配置
    • 翻转速率控制
    • 开漏使能
    • 无源输入滤波器
    • 寄存器锁定
    • 复用功能设置


    以PA0控制寄存器,PORTA_PCR0为例:

    国内芯片技术交流-织女星开发板使用RISC-V核驱动GPIOrisc-v单片机中文社区(1)


    通过查看参考手册,可以了解到各Bit的功能:

    • ISF:1位,中断状态标志
    • IRQC:4位,配置中断方式和DMA功能
    • LK:1位,是否锁定PCR寄存
    • MUX:3位,复用功能配置
    • ODE:1位,推挽开漏配置
    • PFE:1位,滤波器配置
    • SRE:1位,翻转速率配置
    • PE:1位,上下拉使能
    • PS:1位,上下拉配置


    详细的配置介绍可以查看参考手册。官方库fsl_port中的
    1. PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_pin_config_t *config)
    2. PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux)
    3. PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config)
    4. PORT_SetPinDriveStrength(PORT_Type* base, uint32_t pin, uint8_t strength)
    复制代码

    这些函数就是控制的这个PCR寄存器。

    GPIO控制寄存器

    主要包括控制GPIO输入输出控制,读取输入,控制输出,方向控制等。

    寄存器描述和地址偏移量:

    国内芯片技术交流-织女星开发板使用RISC-V核驱动GPIOrisc-v单片机中文社区(2)


    RV32M1的GPIO共有6个32位的控制寄存器,从字面意思可以直接知道每个寄存器的功能:

    • PDOR:数据输出寄存器,指定位写入0/1,输出0/1
    • PSOR:端口置位输出寄存器,指定位写1,置位输出1,写0状态不变
    • PCOR:端口复位输出寄存器,指定位写1,复位输出0,写0状态不变
    • PTOR:端口反转输出寄存器,指定位写1,反转输出,写0状态不变
    • PDIR:端口输入寄存器,读取指定位输入状态
    • PDDR:端口方向配置寄存器,指定位写0作为输入,写1作为输出


    官方库中的fsl_gpio文件中实现的函数就是控制的这几个寄存器。
    1. void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
    2. void GPIO_WritePinOutput(GPIO_Type *base, uint32_t pin, uint8_t output)
    3. void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask)
    4. void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask)
    5. void GPIO_TogglePinsOutput(GPIO_Type *base, uint32_t mask)
    复制代码



    库函数简介

    和其他的MCU一样,由于RV32M1的寄存器众多,为了方便使用,增强程序的可读性,官方开发了库函数,来实现对寄存器的控制,本质上还是操作的寄存器。GPIO控制的库主要由fsl_gpio和fsl_port两个文件组成,其中fsl_gpio主要是对GPIO的控制,如读取输入,控制输出,清除中断标志等,而fsl_port主要实现对GPIO工作的模式进行配置,如复用功能,上拉下拉,开漏推挽,中断触发方式,DMA功能等进行设置。

    下面简单介绍几个常用的函数:

    PORT_SetPinConfig

    配置GPIO的复用功能,驱动能力,推挽开漏,上下拉,滤波器,翻转速率等功能,基于PCR寄存器实现。
    1. port_pin_config_t config;

    2. config.driveStrength = kPORT_HighDriveStrength;                //驱动能力配置
    3. config.mux = kPORT_MuxAsGpio;                                                //通用GPIO
    4. config.openDrainEnable = kPORT_OpenDrainDisable;        //推挽
    5. config.passiveFilterEnable = kPORT_PassiveFilterDisable;//滤波器
    6. config.pullSelect = kPORT_PullUp;                                        //上拉
    7. config.slewRate = kPORT_FastSlewRate;                                //翻转速率

    8. PORT_SetPinConfig(PORTA, 22, &config);                                //配置GPIOA22
    复制代码

    PORT_SetPinMux


    配置GPIO的复用功能,基于PCR寄存器实现。
    1. //PA22作为普通GPIO使用
    2. PORT_SetPinMux(PORTA, 22, kPORT_MuxAsGpio);

    3. //PA25作为UART1_RX功能
    4. PORT_SetPinMux(PORTA, 25, kPORT_MuxAlt2);
    复制代码

    具体复用为哪种功能,不同的引脚有不同的复用功能,对应的ALTn,可以查看参考手册RV32M1 Pinout介绍。

    国内芯片技术交流-织女星开发板使用RISC-V核驱动GPIOrisc-v单片机中文社区(3)


    PORT_SetPinConfig已经包含了PORT_SetPinMux的功能,可以只使用PORT_SetPinConfig来GPIO功能的配置。PORT_SetPinMux函数不推荐和PORT_SetPinsConfig函数一起使用:

    This function is NOT recommended to use together with the PORT_SetPinsConfig, because the PORT_SetPinsConfig need to configure the pin mux anyway (Otherwise the pin mux is reset to zero : kPORT_PinDisabledOrAnalog). This function is recommended to use to reset the pin mux


    GPIO_PinInit


    控制GPIO的输入输出方式,及默认输出电平,基于PDDR、PCOR、PSOR寄存器实现。
    1. gpio_pin_config_t io_init;

    2. //配置输出/输出模式
    3. io_init.outputLogic = 0;        //默认输出0
    4. io_init.pinDirection = kGPIO_DigitalOutput;        //数字输出

    5. GPIO_PinInit(LED_RGB_GPIO, LED_RED_Pin, &io_init);        //LED引脚配置
    复制代码



    GPIO_WritePinOutput

    指定引脚输出高低电平,基于PCOR和PSOR寄存器实现。
    1. GPIO_WritePinOutput(GPIOA, 22, 1);        //PA22输出1
    复制代码



    GPIO_TogglePinsOutput

    指定引脚输出翻转,基于PTOR寄存器实现
    1. GPIO_TogglePinsOutput(GPIOA, 1 << 22);        //PA22输出翻转
    复制代码


    GPIO_ReadPinInput

    读取GPIO输入状态,基于PDIR寄存器实现
    1. in = GPIO_ReadPinInput(GPIOA, 22);        //读取PA22输入状态
    复制代码


    GPIO操作的函数还有很多,详细的介绍和实现可以直接查看库函数源码。

    RGB LED的初始化

    从原理图中我们可以得知,织女星开发板上共有4个用户可控制的LED,包括3个RGB LED和1个红色LED,均采用MOS来驱动,引脚输出高电平LED点亮,和GPIO的对应关系如下:

    LED_RED——PTA24
    LED_GREEN——PTA23
    LED_BLUE——PTA22
    LED_STS——PTE0

    国内芯片技术交流-织女星开发板使用RISC-V核驱动GPIOrisc-v单片机中文社区(4)


    所以我们需要配置PTA22/PTA23/PTA24为普通推挽输出方式,然后输出高低电平就可以控制LED闪烁了。

    led_driver.c文件内容
    1. #include "led_driver.h"

    2. void LED_RGB_Init(void)
    3. {
    4.         gpio_pin_config_t io_init;
    5.         port_pin_config_t config;

    6.         //配置输出/输出模式
    7.         io_init.outputLogic  = 0;
    8.         io_init.pinDirection = kGPIO_DigitalOutput;

    9.         config.driveStrength                 = kPORT_HighDriveStrength;         //驱动能力
    10.         config.lockRegister                 = kPORT_LockRegister;                 //PCR寄存器被锁定,不能再次改变
    11.         config.mux                                         = kPORT_MuxAsGpio;                         //通用GPIO
    12.         config.openDrainEnable                 = kPORT_OpenDrainDisable;         //推挽输出
    13.         config.passiveFilterEnable         = kPORT_PassiveFilterDisable;//滤波器
    14.         config.pullSelect                         = kPORT_PullUp;                                 //上拉
    15.         config.slewRate                         = kPORT_FastSlewRate;                 //翻转速率

    16.         CLOCK_EnableClock(LED_RGB_Clk_Name);
    17.         CLOCK_EnableClock(LED_STS_Clk_Name);                //GPIOE时钟必须一直开启
    18.         CLOCK_EnableClock(kCLOCK_Rgpio1);                        //GPIOE配置需要使能这个时钟

    19.         /*以下两个函数都可以配置端口功能*/
    20.         PORT_SetPinConfig(LED_RGB_Port, LED_RED_Pin, &config);                //配置功能更详细
    21.         PORT_SetPinConfig(LED_RGB_Port, LED_GREEN_Pin, &config);
    22.         PORT_SetPinConfig(LED_RGB_Port, LED_BLUE_Pin, &config);
    23.         PORT_SetPinConfig(LED_STS_Port, LED_STS_Pin, &config);

    24. //        PORT_SetPinMux(LED_RGB_Port, LED_RED_Pin, kPORT_MuxAsGpio);        //只能配置是否复用
    25. //        PORT_SetPinMux(LED_RGB_Port, LED_GREEN_Pin, kPORT_MuxAsGpio);
    26. //        PORT_SetPinMux(LED_RGB_Port, LED_BLUE_Pin, kPORT_MuxAsGpio);

    27. //        CLOCK_DisableClock(LED_RGB_Clk_Name);                //可以在配置完成之后关闭时钟,不影响使用

    28.         GPIO_PinInit(LED_RGB_GPIO, LED_RED_Pin, &io_init);
    29.         GPIO_PinInit(LED_RGB_GPIO, LED_GREEN_Pin, &io_init);
    30.         GPIO_PinInit(LED_RGB_GPIO, LED_BLUE_Pin, &io_init);
    31.         GPIO_PinInit(LED_STS_GPIO, LED_STS_Pin, &io_init);
    32. }
    复制代码


    要注意的是,时钟使能要放在GPIO配置之前,否则不能访问GPIO配置寄存器,在配置完成之后可以关闭时钟,也可以一直开启。其中GPIOE非常特殊,要想使用GPIOE,必须使能Rgpio1快速时钟,其他的GPIO配置不需要,这是因为GPIOE属于快速GPIO,和其他几组GPIO不是同一个总线。
    1. CLOCK_EnableClock(kCLOCK_Rgpio1);                        //GPIOE配置需要使能这个时钟
    复制代码



    led_driver.h文件内容
    1. #ifndef __LED_DRIVER_H__
    2. #define __LED_DRIVER_H__

    3. #include "fsl_gpio.h"
    4. #include "fsl_port.h"
    5. #include "fsl_clock.h"


    6. /*
    7. LED_RGB_BLUE          - A22
    8. LED_RGB_GREEN         - A23
    9. LED_RGB_RED         - A24
    10. LED_STS                 - E0
    11. */


    12. #define LED_RED_Pin                24
    13. #define LED_GREEN_Pin        23
    14. #define LED_BLUE_Pin        22

    15. #define LED_RGB_Port                PORTA
    16. #define LED_RGB_GPIO                GPIOA
    17. #define LED_RGB_Clk_Name        kCLOCK_PortA

    18. #define LED_STS_Pin                0
    19. #define LED_STS_Port                PORTE
    20. #define LED_STS_GPIO                GPIOE
    21. #define LED_STS_Clk_Name        kCLOCK_PortE

    22. #define LED_STS_ON                        GPIO_WritePinOutput(LED_STS_GPIO, LED_STS_Pin, 1)
    23. #define LED_STS_OFF                        GPIO_WritePinOutput(LED_STS_GPIO, LED_STS_Pin, 0)
    24. #define LED_STS_TOGGLE                GPIO_TogglePinsOutput(LED_STS_GPIO, 1 << LED_STS_Pin)

    25. #define LED_RED_ON                        GPIO_WritePinOutput(LED_RGB_GPIO, LED_RED_Pin, 1)
    26. #define LED_RED_OFF                        GPIO_WritePinOutput(LED_RGB_GPIO, LED_RED_Pin, 0)
    27. #define LED_RED_TOGGLE                GPIO_TogglePinsOutput(LED_RGB_GPIO, 1 << LED_RED_Pin)

    28. #define LED_GREEN_ON                GPIO_WritePinOutput(LED_RGB_GPIO, LED_GREEN_Pin, 1)
    29. #define LED_GREEN_OFF                GPIO_WritePinOutput(LED_RGB_GPIO, LED_GREEN_Pin, 0)
    30. #define LED_GREEN_TOGGLE         GPIO_TogglePinsOutput(LED_RGB_GPIO, 1 << LED_GREEN_Pin)

    31. #define LED_BLUE_ON                        GPIO_WritePinOutput(LED_RGB_GPIO, LED_BLUE_Pin, 1)
    32. #define LED_BLUE_OFF                GPIO_WritePinOutput(LED_RGB_GPIO, LED_BLUE_Pin, 0)
    33. #define LED_BLUE_TOGGLE                GPIO_TogglePinsOutput(LED_RGB_GPIO, 1 << LED_BLUE_Pin)

    34. void LED_RGB_Init(void);

    35. #endif
    复制代码

    头文件中通过宏定义的方式实现了LED的亮灭和翻转控制。


    板载按键初始化


    按键部分硬件原理图,按下为低电平。
    国内芯片技术交流-织女星开发板使用RISC-V核驱动GPIOrisc-v单片机中文社区(5)


    button_driver.c文件内容
    1. #include "button_driver.h"
    2. #include "delay.h"
    3. #include "led_driver.h"

    4. //按键使用普通输入GPIO方式
    5. void Button_Init(void)
    6. {
    7.         gpio_pin_config_t io_init;
    8.         port_pin_config_t config;

    9.         io_init.outputLogic  = 0;
    10.         io_init.pinDirection = kGPIO_DigitalInput;

    11.         config.mux                                         = kPORT_MuxAsGpio;                                //通用GPIO
    12.         config.lockRegister                 = kPORT_LockRegister;                        //PCR寄存器被锁定,不能再次改变
    13.         config.pullSelect                         = kPORT_PullUp;                                        //上拉
    14.         config.slewRate                         = kPORT_FastSlewRate;                        //翻转速率
    15.         config.lockRegister                 = kPORT_LockRegister;                        //PCR寄存器被锁定,不能再次改变
    16.         config.passiveFilterEnable         = kPORT_PassiveFilterEnable;        //滤波器

    17.         CLOCK_EnableClock(BTN_SW2_Clk_Name);
    18.         CLOCK_EnableClock(BTN_SW3_Clk_Name);
    19. //        CLOCK_EnableClock(BTN_SW4_Clk_Name);
    20. //        CLOCK_EnableClock(BTN_SW5_Clk_Name);
    21.         CLOCK_EnableClock(kCLOCK_Rgpio1);                        //GPIOE配置需要使能这个时钟

    22.         //以下两个函数功能一样
    23.         PORT_SetPinConfig(BTN_SW2_Port, BTN_SW2_Pin, &config);
    24.         PORT_SetPinConfig(BTN_SW3_Port, BTN_SW3_Pin, &config);
    25.         PORT_SetPinConfig(BTN_SW4_Port, BTN_SW4_Pin, &config);
    26.         PORT_SetPinConfig(BTN_SW5_Port, BTN_SW5_Pin, &config);

    27. //        PORT_SetPinMux(BTN_SW2_Port, BTN_SW2_Pin, kPORT_MuxAsGpio);        //设置IO模式为通用GPIO
    28. //        PORT_SetPinMux(BTN_SW3_Port, BTN_SW3_Pin, kPORT_MuxAsGpio);        //设置IO模式为通用GPIO
    29. //        PORT_SetPinMux(BTN_SW4_Port, BTN_SW4_Pin, kPORT_MuxAsGpio);        //设置IO模式为通用GPIO
    30. //        PORT_SetPinMux(BTN_SW5_Port, BTN_SW5_Pin, kPORT_MuxAsGpio);        //设置IO模式为通用GPIO

    31.         GPIO_PinInit(BTN_SW2_GPIO, BTN_SW2_Pin, &io_init);
    32.         GPIO_PinInit(BTN_SW3_GPIO, BTN_SW3_Pin, &io_init);
    33.         GPIO_PinInit(BTN_SW4_GPIO, BTN_SW4_Pin, &io_init);
    34.         GPIO_PinInit(BTN_SW5_GPIO, BTN_SW5_Pin, &io_init);
    35. }

    36. //按键使用外部中断初始化函数
    37. void ButtonInterruptInit(void)
    38. {
    39.         gpio_pin_config_t io_init;
    40.         port_pin_config_t config;

    41.         io_init.outputLogic  = 0;
    42.         io_init.pinDirection = kGPIO_DigitalInput;

    43.         config.mux                                         = kPORT_MuxAsGpio;                                //通用GPIO
    44.         config.lockRegister                 = kPORT_LockRegister;                        //PCR寄存器被锁定,不能再次改变
    45.         config.pullSelect                         = kPORT_PullUp;                                        //上拉
    46.         config.slewRate                         = kPORT_FastSlewRate;                        //翻转速率
    47.         config.lockRegister                 = kPORT_LockRegister;                        //PCR寄存器被锁定,不能再次改变
    48.         config.passiveFilterEnable         = kPORT_PassiveFilterEnable;        //滤波器

    49.         CLOCK_EnableClock(BTN_SW2_Clk_Name);
    50.         CLOCK_EnableClock(BTN_SW3_Clk_Name);
    51. //        CLOCK_EnableClock(BTN_SW4_Clk_Name);
    52. //        CLOCK_EnableClock(BTN_SW5_Clk_Name);

    53.         CLOCK_EnableClock(kCLOCK_Rgpio1);                        //GPIOE配置需要使能这个时钟

    54.         //以下两个函数功能一样
    55.         PORT_SetPinConfig(BTN_SW2_Port, BTN_SW2_Pin, &config);
    56.         PORT_SetPinConfig(BTN_SW3_Port, BTN_SW3_Pin, &config);
    57.         PORT_SetPinConfig(BTN_SW4_Port, BTN_SW4_Pin, &config);
    58.         PORT_SetPinConfig(BTN_SW5_Port, BTN_SW5_Pin, &config);

    59.         //设置中断触发方式
    60.         PORT_SetPinInterruptConfig(BTN_SW2_Port, BTN_SW2_Pin, kPORT_InterruptFallingEdge);        //下降沿触发中断
    61.         PORT_SetPinInterruptConfig(BTN_SW3_Port, BTN_SW3_Pin, kPORT_InterruptFallingEdge);
    62.         PORT_SetPinInterruptConfig(BTN_SW4_Port, BTN_SW4_Pin, kPORT_InterruptFallingEdge);
    63.         PORT_SetPinInterruptConfig(BTN_SW5_Port, BTN_SW5_Pin, kPORT_InterruptFallingEdge);

    64. #if defined(CPU_RV32M1_ri5cy)
    65.         //RI5CY Core GPIOE需要使能以下两个函数, ZERO Core不用
    66.         INTMUX_Init(INTMUX0);
    67.         INTMUX_EnableInterrupt(INTMUX0, 0, PORTE_IRQn);
    68. #endif

    69.         EnableIRQ(BTN_SW2_IRQ);
    70.         EnableIRQ(BTN_SW3_IRQ);
    71. //        EnableIRQ(BTN_SW4_IRQ);
    72. //        EnableIRQ(BTN_SW5_IRQ);

    73.         GPIO_PinInit(BTN_SW2_GPIO, BTN_SW2_Pin, &io_init);
    74.         GPIO_PinInit(BTN_SW3_GPIO, BTN_SW3_Pin, &io_init);
    75.         GPIO_PinInit(BTN_SW4_GPIO, BTN_SW4_Pin, &io_init);
    76.         GPIO_PinInit(BTN_SW5_GPIO, BTN_SW5_Pin, &io_init);
    77. }

    78. void PORTA_IRQHandler(void)
    79. {
    80.     GPIO_ClearPinsInterruptFlags(BTN_SW2_GPIO, 1U << BTN_SW2_Pin);
    81.         LED_STS_TOGGLE;
    82.         LOG("sw2 is pressed \r\n");
    83. }

    84. //GPIOE外部中断函数
    85. void PORTE_IRQHandler(void)
    86. {
    87.         uint32_t flag;

    88.         flag = GPIO_GetPinsInterruptFlags(BTN_SW3_GPIO);

    89.     GPIO_ClearPinsInterruptFlags(BTN_SW3_GPIO, 1U << BTN_SW3_Pin);
    90.     GPIO_ClearPinsInterruptFlags(BTN_SW4_GPIO, 1U << BTN_SW4_Pin);
    91.     GPIO_ClearPinsInterruptFlags(BTN_SW5_GPIO, 1U << BTN_SW5_Pin);

    92.     if(flag & (1 << BTN_SW3_Pin))        //SW3产生中断
    93.     {
    94.             LED_RED_TOGGLE;
    95.             LOG("sw3 is pressed \r\n");
    96.     }
    97.         else if(flag & (1 << BTN_SW4_Pin))
    98.         {
    99.                 LED_GREEN_TOGGLE;
    100.             LOG("sw4 is pressed \r\n");
    101.         }
    102.     else if(flag & (1 << BTN_SW5_Pin))
    103.         {
    104.             LED_BLUE_TOGGLE;
    105.             LOG("sw5 is pressed \r\n");
    106.         }
    107. }

    108. //轮询方式获取按键状态
    109. uint8_t GetKey(void)
    110. {
    111.         uint8_t key = 1;
    112.         //按键按下为0
    113.         if(BTN_SW2_IN && BTN_SW3_IN && BTN_SW4_IN && BTN_SW5_IN)
    114.         {
    115.                 Delay_ms(10);
    116.                 if(!BTN_SW2_IN)
    117.                         key = 2;
    118.                 else if(!BTN_SW3_IN)
    119.                         key = 3;
    120.                 else if(!BTN_SW4_IN)
    121.                         key = 4;
    122.                 else if(!BTN_SW5_IN)
    123.                         key = 5;
    124.                 while(!(BTN_SW2_IN && BTN_SW3_IN && BTN_SW4_IN && BTN_SW5_IN));
    125.         }
    126.         return key;
    127. }
    复制代码

    按键配置为上拉输入模式,同样如果使用GPIOE作为通用GPIO输入,还需要使能Rgpio1时钟
    1.         CLOCK_EnableClock(kCLOCK_Rgpio1);                        //GPIOE配置需要使能这个时钟
    复制代码

    如果使用GPIOE的外部中断功能,还需要使能INTMUX
    1. #if defined(CPU_RV32M1_ri5cy)
    2.         //RI5CY Core GPIOE需要使能以下两个函数, ZERO Core不用
    3.         INTMUX_Init(INTMUX0);
    4.         INTMUX_EnableInterrupt(INTMUX0, 0, PORTE_IRQn);
    5. #endif
    复制代码



    button_driver.h文件内容
    1. #ifndef __BUTTON_DRIVER_H__
    2. #define __BUTTON_DRIVER_H__

    3. #include "fsl_gpio.h"
    4. #include "fsl_port.h"
    5. #include "fsl_intmux.h"

    6. /*
    7. * SW2 - A0
    8. * SW3 - E12
    9. * SW4 - E8
    10. * SW5 - E9
    11. * */

    12. //按下为低电平

    13. #define BTN_SW2_GPIO         GPIOA
    14. #define BTN_SW3_GPIO         GPIOE
    15. #define BTN_SW4_GPIO         GPIOE
    16. #define BTN_SW5_GPIO         GPIOE

    17. #define BTN_SW2_Pin                0
    18. #define BTN_SW3_Pin                12
    19. #define BTN_SW4_Pin                8
    20. #define BTN_SW5_Pin                9

    21. #define BTN_SW2_Port        PORTA
    22. #define BTN_SW3_Port        PORTE
    23. #define BTN_SW4_Port        PORTE
    24. #define BTN_SW5_Port        PORTE

    25. #define BTN_SW2_IRQ                PORTA_IRQn
    26. #define BTN_SW3_IRQ                PORTE_IRQn
    27. #define BTN_SW4_IRQ                PORTE_IRQn
    28. #define BTN_SW5_IRQ                PORTE_IRQn

    29. #define BTN_SW2_Clk_Name        kCLOCK_PortA
    30. #define BTN_SW3_Clk_Name        kCLOCK_PortE
    31. #define BTN_SW4_Clk_Name        kCLOCK_PortE
    32. #define BTN_SW5_Clk_Name        kCLOCK_PortE

    33. #define BTN_SW2_IN        GPIO_ReadPinInput(BTN_SW2_GPIO, BTN_SW2_Pin)
    34. #define BTN_SW3_IN        GPIO_ReadPinInput(BTN_SW3_GPIO, BTN_SW3_Pin)
    35. #define BTN_SW4_IN        GPIO_ReadPinInput(BTN_SW4_GPIO, BTN_SW4_Pin)
    36. #define BTN_SW5_IN        GPIO_ReadPinInput(BTN_SW5_GPIO, BTN_SW5_Pin)

    37. /*
    38. #define BTN_SW2_IN        ReadGPIO(BTN_SW2_GPIO, BTN_SW2_Pin)
    39. #define BTN_SW3_IN        ReadGPIO(BTN_SW3_GPIO, BTN_SW3_Pin)
    40. #define BTN_SW4_IN        ReadGPIO(BTN_SW4_GPIO, BTN_SW4_Pin)
    41. #define BTN_SW5_IN        ReadGPIO(BTN_SW5_GPIO, BTN_SW5_Pin)
    42. */

    43. void Button_Init(void);
    44. uint8_t GetKey(void);
    45. void ButtonInterruptInit(void);

    46. #endif
    复制代码

    通过GPIO读取函数来获取按键输入状态,或者是通过中断标志来判断输入状态。

    主函数应用

    使用外部中断方式读取按键输入状态。
    1. #include "main.h"

    2. extern uint32_t SystemCoreClock;

    3. int main(void)
    4. {
    5.         BOARD_BootClockRUN();        //ϵͳʱ֓Ťփ

    6.         UART0_Init();
    7.         Delay_Init();

    8.         LOG("SystemCoreClock: %ld \r\n", SystemCoreClock);

    9. #if defined(CPU_RV32M1_ri5cy)
    10.         LOG("RV32M1 RISC-V RI5CY Core Demo \r\n");
    11. #elif defined(CPU_RV32M1_zero_riscy)
    12.         LOG("RV32M1 RISC-V ZERO Core Demo \r\n");
    13. #endif

    14.         LED_RGB_Init();
    15. //        Button_Init();
    16.         ButtonInterruptInit();
    17.         // LPMTR2_Init();
    18.         // LPIT1_CH3_Init();

    19.         while (1)
    20.         {

    21.         }
    22. }
    复制代码

    代码下载

    国内芯片技术交流-织女星开发板使用RISC-V核驱动GPIOrisc-v单片机中文社区(6)


    织女星开发板VEGA_Lite支持从4个核启动,所以在进行程序下载之前,要确认当前的启动模式和当前的工程是对应的。如当前工程是使用RISC-V RI5CY核来驱动GPIO,那么就需要配置芯片启动模式为RI5CY核启动。否则会不能下载。关于启动模式的修改可以参考:织女星开发板启动模式修改



    总结


    RV32M1芯片的GPIOE与其他几组GPIO配置方法稍有不同,使用时要特别注意。

    参考资料








    上一篇:RISC-V GNU 工具链:安装与使用
    下一篇:开源硬件3.0时代降临
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-4-19 23:01 , Processed in 1.086568 second(s), 48 queries .

    快速回复 返回顶部 返回列表