天天看點

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

文章目錄

      • 前言
      • 準備工作
      • 寄存器簡介
        • GPIO配置PCR寄存器
        • GPIO控制寄存器
      • 庫函數簡介
        • PORT_SetPinConfig
        • PORT_SetPinMux
        • GPIO_PinInit
        • GPIO_WritePinOutput
        • GPIO_TogglePinsOutput
        • GPIO_ReadPinInput
      • RGB LED的初始化
        • led_driver.c檔案内容
        • led_driver.h檔案内容
      • 闆載按鍵初始化
        • button_driver.c檔案内容
        • button_driver.h檔案内容
      • 主函數應用
      • 代碼下載下傳
      • 總結
      • 參考資料
      • 推薦閱讀

前言

織女星開發闆是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核驅動GPIO

準備工作

在進行以下操作之前,要確定開發環境已經搭建完成,而且能正常下載下傳調試。

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

以上資料的擷取、開發環境搭建和啟動模式修改等教程,可以到官方中文論壇查找:

www.open-isa.cn

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

  • 真正的RISC-V開發闆——VEGA織女星開發闆開箱評測
  • 手把手教你搭建織女星開發闆RISC-V開發環境
  • 織女星開發闆啟動模式修改
  • 織女星開發闆調試器更新為Jlink固件
  • 織女星開發闆RISC-V核心實作微秒級精确延時

寄存器簡介

根據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的以下功能:

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

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

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

通過檢視參考手冊,可以了解到各Bit的功能:

  • 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輸入輸出控制,讀取輸入,控制輸出,方向控制等。

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

織女星開發闆使用RISC-V核驅動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介紹。

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

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_TogglePinsOutput

指定引腳輸出翻轉,基于PTOR寄存器實作

GPIO_ReadPinInput

讀取GPIO輸入狀态,基于PDIR寄存器實作

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核驅動GPIO

是以我們需要配置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的亮滅和翻轉控制。

闆載按鍵初始化

按鍵部分硬體原理圖,按下為低電平。

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

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)
	{

	}
}

           

代碼下載下傳

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

織女星開發闆VEGA_Lite支援從4個核啟動,是以在進行程式下載下傳之前,要确認目前的啟動模式和目前的工程是對應的。如目前工程是使用RISC-V RI5CY核來驅動GPIO,那麼就需要配置晶片啟動模式為RI5CY核啟動。否則會不能下載下傳。關于啟動模式的修改可以參考:織女星開發闆啟動模式修改

  • RI5CY驅動GPIO源碼下載下傳:RI5CY_GPIO_Demo.rar
  • ZERO驅動GPIO源碼下載下傳:ZERO_GPIO_Demo.rar

總結

RV32M1晶片的GPIOE與其他幾組GPIO配置方法稍有不同,使用時要特别注意。

參考資料

  • MCUXpresso SDK API參考手冊
  • RV32M1_Vega_Develop_Environment_Setup.pdf
  • RV32M1資料手冊
  • RV32M1參考手冊
  • 織女星開發闆快速入門指南.pdf

推薦閱讀

  • 真正的RISC-V開發闆——VEGA織女星開發闆開箱評測
  • 手把手教你搭建織女星開發闆RISC-V開發環境
  • 織女星開發闆啟動模式修改
  • 織女星開發闆調試器更新為Jlink固件
  • 織女星開發闆RISC-V核心實作微秒級精确延時
  • 個人部落格:

    www.wangchaochao.top

  • 我的公衆号:

    mcu149

繼續閱讀