織女星開發板使用RISC-V核驅動GPIO

前言

織女星開發板是OPEN-ISA社區爲中國大陸地區定製的一款體積小、功耗超低和功能豐富的 RISC-V評估開發板,基於NXP半導體四核異構RV32M1主控芯片。html

  • 兩個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的輸入輸出和外部中斷功能。git

準備工做

在進行如下操做以前,要確保開發環境已經搭建完成,並且能正常下載調試。github

  • 織女星開發板RISC-V開發環境:Eclipse + riscv32 工具鏈 + OpenOCD調試工具
  • 織女星開發板SDK包:rv32m1_sdk_riscv
  • 織女星開發板的原理圖
  • RV32M1參考手冊

以上資料的獲取、開發環境搭建和啓動模式修改等教程,能夠到官方中文論壇查找:www.open-isa.cnapi

或者是參考我分享的如下文章:ide

寄存器簡介

根據RV32M1參考手冊GPIO章節的介紹,咱們能夠得到關於GPIO相關寄存器信息:函數

各GPIO組的基地址:工具

GPIOA——4802_0000h
GPIOB——4802_0040h
GPIOC——4802_0080h
GPIOD——4802_00C0h
GPIOE——4100_F000h

GPIO配置PCR寄存器

這是一個32位的寄存器,每個引腳都有對應的一個PORTx_PCRn,用來配置GPIO的如下功能:ui

  • 上下拉配置
  • 翻轉速率控制
  • 開漏使能
  • 無源輸入濾波器
  • 寄存器鎖定
  • 複用功能設置

以PA0控制寄存器,PORTA_PCR0爲例:調試

經過查看參考手冊,能夠了解到各Bit的功能:code

  • ISF:1位,中斷狀態標誌
  • IRQC:4位,配置中斷方式和DMA功能
  • LK:1位,是否鎖定PCR寄存
  • MUX:3位,複用功能配置
  • ODE:1位,推輓開漏配置
  • PFE:1位,濾波器配置
  • SRE:1位,翻轉速率配置
  • PE:1位,上下拉使能
  • PS:1位,上下拉配置

詳細的配置介紹能夠查看參考手冊。官方庫fsl_port中的

PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_pin_config_t *config)
PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux)
PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config)
PORT_SetPinDriveStrength(PORT_Type* base, uint32_t pin, uint8_t strength)

這些函數就是控制的這個PCR寄存器。

GPIO控制寄存器

主要包括控制GPIO輸入輸出控制,讀取輸入,控制輸出,方向控制等。

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

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文件中實現的函數就是控制的這幾個寄存器。

void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
void GPIO_WritePinOutput(GPIO_Type *base, uint32_t pin, uint8_t output)
void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask)
void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask)
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寄存器實現。

port_pin_config_t config;

config.driveStrength = kPORT_HighDriveStrength;     //驅動能力配置
config.mux = kPORT_MuxAsGpio;                       //通用GPIO
config.openDrainEnable = kPORT_OpenDrainDisable;    //推輓
config.passiveFilterEnable = kPORT_PassiveFilterDisable;//濾波器
config.pullSelect = kPORT_PullUp;                   //上拉
config.slewRate = kPORT_FastSlewRate;               //翻轉速率

PORT_SetPinConfig(PORTA, 22, &config);              //配置GPIOA22

PORT_SetPinMux

配置GPIO的複用功能,基於PCR寄存器實現。

//PA22做爲普通GPIO使用
PORT_SetPinMux(PORTA, 22, kPORT_MuxAsGpio);

//PA25做爲UART1_RX功能
PORT_SetPinMux(PORTA, 25, kPORT_MuxAlt2);

具體複用爲哪一種功能,不一樣的引腳有不一樣的複用功能,對應的ALTn,能夠查看參考手冊RV32M1 Pinout介紹。

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寄存器實現。

gpio_pin_config_t io_init;

//配置輸出/輸出模式
io_init.outputLogic = 0;    //默認輸出0
io_init.pinDirection = kGPIO_DigitalOutput; //數字輸出

GPIO_PinInit(LED_RGB_GPIO, LED_RED_Pin, &io_init);  //LED引腳配置

GPIO_WritePinOutput

指定引腳輸出高低電平,基於PCOR和PSOR寄存器實現。

GPIO_WritePinOutput(GPIOA, 22, 1);  //PA22輸出1

GPIO_TogglePinsOutput

指定引腳輸出翻轉,基於PTOR寄存器實現

GPIO_TogglePinsOutput(GPIOA, 1 << 22);  //PA22輸出翻轉

GPIO_ReadPinInput

讀取GPIO輸入狀態,基於PDIR寄存器實現

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

因此咱們須要配置PTA22/PTA23/PTA24爲普通推輓輸出方式,而後輸出高低電平就能夠控制LED閃爍了。

led_driver.c文件內容

#include "led_driver.h"

void LED_RGB_Init(void)
{
    gpio_pin_config_t io_init;
    port_pin_config_t config;

    //配置輸出/輸出模式
    io_init.outputLogic  = 0;
    io_init.pinDirection = kGPIO_DigitalOutput;

    config.driveStrength        = kPORT_HighDriveStrength;   //驅動能力
    config.lockRegister         = kPORT_LockRegister;        //PCR寄存器被鎖定,不能再次改變
    config.mux                  = kPORT_MuxAsGpio;           //通用GPIO
    config.openDrainEnable      = kPORT_OpenDrainDisable;    //推輓輸出
    config.passiveFilterEnable  = kPORT_PassiveFilterDisable;//濾波器
    config.pullSelect           = kPORT_PullUp;              //上拉
    config.slewRate             = kPORT_FastSlewRate;        //翻轉速率

    CLOCK_EnableClock(LED_RGB_Clk_Name);
    CLOCK_EnableClock(LED_STS_Clk_Name);        //GPIOE時鐘必須一直開啓
    CLOCK_EnableClock(kCLOCK_Rgpio1);           //GPIOE配置須要使能這個時鐘

    /*如下兩個函數均可以配置端口功能*/
    PORT_SetPinConfig(LED_RGB_Port, LED_RED_Pin, &config);      //配置功能更詳細
    PORT_SetPinConfig(LED_RGB_Port, LED_GREEN_Pin, &config);
    PORT_SetPinConfig(LED_RGB_Port, LED_BLUE_Pin, &config);
    PORT_SetPinConfig(LED_STS_Port, LED_STS_Pin, &config);

//  PORT_SetPinMux(LED_RGB_Port, LED_RED_Pin, kPORT_MuxAsGpio); //只能配置是否複用
//  PORT_SetPinMux(LED_RGB_Port, LED_GREEN_Pin, kPORT_MuxAsGpio);
//  PORT_SetPinMux(LED_RGB_Port, LED_BLUE_Pin, kPORT_MuxAsGpio);

//  CLOCK_DisableClock(LED_RGB_Clk_Name);       //能夠在配置完成以後關閉時鐘,不影響使用

    GPIO_PinInit(LED_RGB_GPIO, LED_RED_Pin, &io_init);
    GPIO_PinInit(LED_RGB_GPIO, LED_GREEN_Pin, &io_init);
    GPIO_PinInit(LED_RGB_GPIO, LED_BLUE_Pin, &io_init);
    GPIO_PinInit(LED_STS_GPIO, LED_STS_Pin, &io_init);
}

要注意的是,時鐘使能要放在GPIO配置以前,不然不能訪問GPIO配置寄存器,在配置完成以後能夠關閉時鐘,也能夠一直開啓。其中GPIOE很是特殊,要想使用GPIOE,必須使能Rgpio1快速時鐘,其餘的GPIO配置不須要,這是由於GPIOE屬於快速GPIO,和其餘幾組GPIO不是同一個總線。

CLOCK_EnableClock(kCLOCK_Rgpio1);           //GPIOE配置須要使能這個時鐘

led_driver.h文件內容

#ifndef __LED_DRIVER_H__
#define __LED_DRIVER_H__

#include "fsl_gpio.h"
#include "fsl_port.h"
#include "fsl_clock.h"


/*
LED_RGB_BLUE    - A22
LED_RGB_GREEN   - A23
LED_RGB_RED     - A24
LED_STS         - E0
*/


#define LED_RED_Pin     24
#define LED_GREEN_Pin   23
#define LED_BLUE_Pin    22

#define LED_RGB_Port        PORTA
#define LED_RGB_GPIO        GPIOA
#define LED_RGB_Clk_Name    kCLOCK_PortA

#define LED_STS_Pin     0
#define LED_STS_Port        PORTE
#define LED_STS_GPIO        GPIOE
#define LED_STS_Clk_Name    kCLOCK_PortE

#define LED_STS_ON          GPIO_WritePinOutput(LED_STS_GPIO, LED_STS_Pin, 1)
#define LED_STS_OFF         GPIO_WritePinOutput(LED_STS_GPIO, LED_STS_Pin, 0)
#define LED_STS_TOGGLE      GPIO_TogglePinsOutput(LED_STS_GPIO, 1 << LED_STS_Pin)

#define LED_RED_ON          GPIO_WritePinOutput(LED_RGB_GPIO, LED_RED_Pin, 1)
#define LED_RED_OFF         GPIO_WritePinOutput(LED_RGB_GPIO, LED_RED_Pin, 0)
#define LED_RED_TOGGLE      GPIO_TogglePinsOutput(LED_RGB_GPIO, 1 << LED_RED_Pin)

#define LED_GREEN_ON        GPIO_WritePinOutput(LED_RGB_GPIO, LED_GREEN_Pin, 1)
#define LED_GREEN_OFF       GPIO_WritePinOutput(LED_RGB_GPIO, LED_GREEN_Pin, 0)
#define LED_GREEN_TOGGLE    GPIO_TogglePinsOutput(LED_RGB_GPIO, 1 << LED_GREEN_Pin)

#define LED_BLUE_ON         GPIO_WritePinOutput(LED_RGB_GPIO, LED_BLUE_Pin, 1)
#define LED_BLUE_OFF        GPIO_WritePinOutput(LED_RGB_GPIO, LED_BLUE_Pin, 0)
#define LED_BLUE_TOGGLE     GPIO_TogglePinsOutput(LED_RGB_GPIO, 1 << LED_BLUE_Pin)

void LED_RGB_Init(void);

#endif

頭文件中經過宏定義的方式實現了LED的亮滅和翻轉控制。

板載按鍵初始化

按鍵部分硬件原理圖,按下爲低電平。

button_driver.c文件內容

#include "button_driver.h"
#include "delay.h"
#include "led_driver.h"

//按鍵使用普通輸入GPIO方式
void Button_Init(void)
{
    gpio_pin_config_t io_init;
    port_pin_config_t config;

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

    config.mux                  = kPORT_MuxAsGpio;              //通用GPIO
    config.lockRegister         = kPORT_LockRegister;           //PCR寄存器被鎖定,不能再次改變
    config.pullSelect           = kPORT_PullUp;                 //上拉
    config.slewRate             = kPORT_FastSlewRate;           //翻轉速率
    config.lockRegister         = kPORT_LockRegister;           //PCR寄存器被鎖定,不能再次改變
    config.passiveFilterEnable  = kPORT_PassiveFilterEnable;    //濾波器

    CLOCK_EnableClock(BTN_SW2_Clk_Name);
    CLOCK_EnableClock(BTN_SW3_Clk_Name);
//  CLOCK_EnableClock(BTN_SW4_Clk_Name);
//  CLOCK_EnableClock(BTN_SW5_Clk_Name);
    CLOCK_EnableClock(kCLOCK_Rgpio1);           //GPIOE配置須要使能這個時鐘

    //如下兩個函數功能同樣
    PORT_SetPinConfig(BTN_SW2_Port, BTN_SW2_Pin, &config);
    PORT_SetPinConfig(BTN_SW3_Port, BTN_SW3_Pin, &config);
    PORT_SetPinConfig(BTN_SW4_Port, BTN_SW4_Pin, &config);
    PORT_SetPinConfig(BTN_SW5_Port, BTN_SW5_Pin, &config);

//  PORT_SetPinMux(BTN_SW2_Port, BTN_SW2_Pin, kPORT_MuxAsGpio); //設置IO模式爲通用GPIO
//  PORT_SetPinMux(BTN_SW3_Port, BTN_SW3_Pin, kPORT_MuxAsGpio); //設置IO模式爲通用GPIO
//  PORT_SetPinMux(BTN_SW4_Port, BTN_SW4_Pin, kPORT_MuxAsGpio); //設置IO模式爲通用GPIO
//  PORT_SetPinMux(BTN_SW5_Port, BTN_SW5_Pin, kPORT_MuxAsGpio); //設置IO模式爲通用GPIO

    GPIO_PinInit(BTN_SW2_GPIO, BTN_SW2_Pin, &io_init);
    GPIO_PinInit(BTN_SW3_GPIO, BTN_SW3_Pin, &io_init);
    GPIO_PinInit(BTN_SW4_GPIO, BTN_SW4_Pin, &io_init);
    GPIO_PinInit(BTN_SW5_GPIO, BTN_SW5_Pin, &io_init);
}

//按鍵使用外部中斷初始化函數
void ButtonInterruptInit(void)
{
    gpio_pin_config_t io_init;
    port_pin_config_t config;

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

    config.mux                  = kPORT_MuxAsGpio;              //通用GPIO
    config.lockRegister         = kPORT_LockRegister;           //PCR寄存器被鎖定,不能再次改變
    config.pullSelect           = kPORT_PullUp;                 //上拉
    config.slewRate             = kPORT_FastSlewRate;           //翻轉速率
    config.lockRegister         = kPORT_LockRegister;           //PCR寄存器被鎖定,不能再次改變
    config.passiveFilterEnable  = kPORT_PassiveFilterEnable;    //濾波器

    CLOCK_EnableClock(BTN_SW2_Clk_Name);
    CLOCK_EnableClock(BTN_SW3_Clk_Name);
//  CLOCK_EnableClock(BTN_SW4_Clk_Name);
//  CLOCK_EnableClock(BTN_SW5_Clk_Name);

    CLOCK_EnableClock(kCLOCK_Rgpio1);           //GPIOE配置須要使能這個時鐘

    //如下兩個函數功能同樣
    PORT_SetPinConfig(BTN_SW2_Port, BTN_SW2_Pin, &config);
    PORT_SetPinConfig(BTN_SW3_Port, BTN_SW3_Pin, &config);
    PORT_SetPinConfig(BTN_SW4_Port, BTN_SW4_Pin, &config);
    PORT_SetPinConfig(BTN_SW5_Port, BTN_SW5_Pin, &config);

    //設置中斷觸發方式
    PORT_SetPinInterruptConfig(BTN_SW2_Port, BTN_SW2_Pin, kPORT_InterruptFallingEdge);  //降低沿觸發中斷
    PORT_SetPinInterruptConfig(BTN_SW3_Port, BTN_SW3_Pin, kPORT_InterruptFallingEdge);
    PORT_SetPinInterruptConfig(BTN_SW4_Port, BTN_SW4_Pin, kPORT_InterruptFallingEdge);
    PORT_SetPinInterruptConfig(BTN_SW5_Port, BTN_SW5_Pin, kPORT_InterruptFallingEdge);

#if defined(CPU_RV32M1_ri5cy)
    //RI5CY Core GPIOE須要使能如下兩個函數, ZERO Core不用
    INTMUX_Init(INTMUX0);
    INTMUX_EnableInterrupt(INTMUX0, 0, PORTE_IRQn);
#endif

    EnableIRQ(BTN_SW2_IRQ);
    EnableIRQ(BTN_SW3_IRQ);
//  EnableIRQ(BTN_SW4_IRQ);
//  EnableIRQ(BTN_SW5_IRQ);

    GPIO_PinInit(BTN_SW2_GPIO, BTN_SW2_Pin, &io_init);
    GPIO_PinInit(BTN_SW3_GPIO, BTN_SW3_Pin, &io_init);
    GPIO_PinInit(BTN_SW4_GPIO, BTN_SW4_Pin, &io_init);
    GPIO_PinInit(BTN_SW5_GPIO, BTN_SW5_Pin, &io_init);
}

void PORTA_IRQHandler(void)
{
    GPIO_ClearPinsInterruptFlags(BTN_SW2_GPIO, 1U << BTN_SW2_Pin);
    LED_STS_TOGGLE;
    LOG("sw2 is pressed \r\n");
}

//GPIOE外部中斷函數
void PORTE_IRQHandler(void)
{
    uint32_t flag;

    flag = GPIO_GetPinsInterruptFlags(BTN_SW3_GPIO);

    GPIO_ClearPinsInterruptFlags(BTN_SW3_GPIO, 1U << BTN_SW3_Pin);
    GPIO_ClearPinsInterruptFlags(BTN_SW4_GPIO, 1U << BTN_SW4_Pin);
    GPIO_ClearPinsInterruptFlags(BTN_SW5_GPIO, 1U << BTN_SW5_Pin);

    if(flag & (1 << BTN_SW3_Pin))   //SW3產生中斷
    {
        LED_RED_TOGGLE;
        LOG("sw3 is pressed \r\n");
    }
    else if(flag & (1 << BTN_SW4_Pin))
    {
        LED_GREEN_TOGGLE;
        LOG("sw4 is pressed \r\n");
    }
    else if(flag & (1 << BTN_SW5_Pin))
    {
        LED_BLUE_TOGGLE;
        LOG("sw5 is pressed \r\n");
    }
}

//輪詢方式獲取按鍵狀態
uint8_t GetKey(void)
{
    uint8_t key = 1;
    //按鍵按下爲0
    if(BTN_SW2_IN && BTN_SW3_IN && BTN_SW4_IN && BTN_SW5_IN)
    {
        Delay_ms(10);
        if(!BTN_SW2_IN)
            key = 2;
        else if(!BTN_SW3_IN)
            key = 3;
        else if(!BTN_SW4_IN)
            key = 4;
        else if(!BTN_SW5_IN)
            key = 5;
        while(!(BTN_SW2_IN && BTN_SW3_IN && BTN_SW4_IN && BTN_SW5_IN));
    }
    return key;
}

按鍵配置爲上拉輸入模式,一樣若是使用GPIOE做爲通用GPIO輸入,還須要使能Rgpio1時鐘

CLOCK_EnableClock(kCLOCK_Rgpio1);           //GPIOE配置須要使能這個時鐘

若是使用GPIOE的外部中斷功能,還須要使能INTMUX

#if defined(CPU_RV32M1_ri5cy)
    //RI5CY Core GPIOE須要使能如下兩個函數, ZERO Core不用
    INTMUX_Init(INTMUX0);
    INTMUX_EnableInterrupt(INTMUX0, 0, PORTE_IRQn);
#endif

button_driver.h文件內容

#ifndef __BUTTON_DRIVER_H__
#define __BUTTON_DRIVER_H__

#include "fsl_gpio.h"
#include "fsl_port.h"
#include "fsl_intmux.h"

/*
 * SW2 - A0
 * SW3 - E12
 * SW4 - E8
 * SW5 - E9
 * */

//按下爲低電平

#define BTN_SW2_GPIO    GPIOA
#define BTN_SW3_GPIO    GPIOE
#define BTN_SW4_GPIO    GPIOE
#define BTN_SW5_GPIO    GPIOE

#define BTN_SW2_Pin     0
#define BTN_SW3_Pin     12
#define BTN_SW4_Pin     8
#define BTN_SW5_Pin     9

#define BTN_SW2_Port    PORTA
#define BTN_SW3_Port    PORTE
#define BTN_SW4_Port    PORTE
#define BTN_SW5_Port    PORTE

#define BTN_SW2_IRQ     PORTA_IRQn
#define BTN_SW3_IRQ     PORTE_IRQn
#define BTN_SW4_IRQ     PORTE_IRQn
#define BTN_SW5_IRQ     PORTE_IRQn

#define BTN_SW2_Clk_Name    kCLOCK_PortA
#define BTN_SW3_Clk_Name    kCLOCK_PortE
#define BTN_SW4_Clk_Name    kCLOCK_PortE
#define BTN_SW5_Clk_Name    kCLOCK_PortE

#define BTN_SW2_IN  GPIO_ReadPinInput(BTN_SW2_GPIO, BTN_SW2_Pin)
#define BTN_SW3_IN  GPIO_ReadPinInput(BTN_SW3_GPIO, BTN_SW3_Pin)
#define BTN_SW4_IN  GPIO_ReadPinInput(BTN_SW4_GPIO, BTN_SW4_Pin)
#define BTN_SW5_IN  GPIO_ReadPinInput(BTN_SW5_GPIO, BTN_SW5_Pin)

/*
#define BTN_SW2_IN  ReadGPIO(BTN_SW2_GPIO, BTN_SW2_Pin)
#define BTN_SW3_IN  ReadGPIO(BTN_SW3_GPIO, BTN_SW3_Pin)
#define BTN_SW4_IN  ReadGPIO(BTN_SW4_GPIO, BTN_SW4_Pin)
#define BTN_SW5_IN  ReadGPIO(BTN_SW5_GPIO, BTN_SW5_Pin)
*/

void Button_Init(void);
uint8_t GetKey(void);
void ButtonInterruptInit(void);

#endif

經過GPIO讀取函數來獲取按鍵輸入狀態,或者是經過中斷標誌來判斷輸入狀態。

主函數應用

使用外部中斷方式讀取按鍵輸入狀態。

#include "main.h"

extern uint32_t SystemCoreClock;

int main(void)
{
    BOARD_BootClockRUN();   //ϵͳʱ֓Ťփ

    UART0_Init();
    Delay_Init();

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

#if defined(CPU_RV32M1_ri5cy)
    LOG("RV32M1 RISC-V RI5CY Core Demo \r\n");
#elif defined(CPU_RV32M1_zero_riscy)
    LOG("RV32M1 RISC-V ZERO Core Demo \r\n");
#endif

    LED_RGB_Init();
//  Button_Init();
    ButtonInterruptInit();
    // LPMTR2_Init();
    // LPIT1_CH3_Init();

    while (1)
    {

    }
}

代碼下載

織女星開發板VEGA_Lite支持從4個核啓動,因此在進行程序下載以前,要確認當前的啓動模式和當前的工程是對應的。如當前工程是使用RISC-V RI5CY核來驅動GPIO,那麼就須要配置芯片啓動模式爲RI5CY核啓動。不然會不能下載。關於啓動模式的修改能夠參考:織女星開發板啓動模式修改

總結

RV32M1芯片的GPIOE與其餘幾組GPIO配置方法稍有不一樣,使用時要特別注意。

參考資料

推薦閱讀


  • 我的博客:www.wangchaochao.top
  • 個人公衆號:mcu149
相關文章
相關標籤/搜索