关于片上MCU基本外设的使用,可以查看对应的头文件,里面有非常详细的使用说明。
在嵌入式开发中,一个GPIO通常有输入,输出,外部中断和复用功能。但是对于SmartFusion系列FPGA内部的MCU来说,GPIO只有输入输出和外部中断功能,并没有复用功能。上一篇文章,介绍了片上MSS,即ARM MCU的配置,并使用MCU的GPIO外设驱动了LED,本篇文章介绍MSS_GPIO配置成输入模式,直接读取输入和配置成外部中断。
固件库下载地址:Firmware_MSS_GPIO_Driver_v2.0.105
示例工程,可以参考:
所以最终实现的效果是:
在进行正式的配置之前,先来了解一下MSS_GPIO的一些接函数吧。
GPIO的模式,支持以下几种,配置要和FPGA工程中MSS的配置保持一致 :
/* 输入模式 */
#define MSS_GPIO_INPUT_MODE 0x0000000002UL
/* 输出模式 */
#define MSS_GPIO_OUTPUT_MODE 0x0000000005UL
/* 输入输出模式 */
#define MSS_GPIO_INOUT_MODE 0x0000000003UL
中断触发方式支持高电平,低电平,上升沿,下降沿和双边沿触发:
#define MSS_GPIO_IRQ_LEVEL_HIGH 0x0000000000UL
#define MSS_GPIO_IRQ_LEVEL_LOW 0x0000000020UL
#define MSS_GPIO_IRQ_EDGE_POSITIVE 0x0000000040UL
#define MSS_GPIO_IRQ_EDGE_NEGATIVE 0x0000000060UL
#define MSS_GPIO_IRQ_EDGE_BOTH 0x0000000080UL
对于双向GPIO,支持输入、输出和高阻三种状态:
typedef enum mss_gpio_inout_state
{
MSS_GPIO_DRIVE_LOW = 0,
MSS_GPIO_DRIVE_HIGH,
MSS_GPIO_HIGH_Z
} mss_gpio_inout_state_t;
下面来介绍几个常用的函数
/* 设置某一个GPIO的电平 */
void MSS_GPIO_set_output(mss_gpio_id_t port_id, uint8_t value);
/* 设置所有GPIO的电平 */
void MSS_GPIO_set_outputs(uint32_t value);
/* 获取所有GPIO的输入状态 */
uint32_t MSS_GPIO_get_inputs(void)
/* 获取所有GPIO的输出状态 */
uint32_t MSS_GPIO_get_outputs(void);
/* 设置双向GPIO的状态 */
void MSS_GPIO_drive_inout(mss_gpio_id_t port_id, mss_gpio_inout_state_t inout_state);
/* 使能中断 */
void MSS_GPIO_enable_irq(mss_gpio_id_t port_id);
/* 禁止中断 */
void MSS_GPIO_disable_irq(mss_gpio_id_t port_id);
/* 清除中断 */
void MSS_GPIO_clear_irq(mss_gpio_id_t port_id);
这里的模式配置包括两方面,一个是FPGA工程中,MSS的配置,一个是ARM程序中模式的配置。
MSS的配置
ARM程序中的配置:
/* GPIO_0 & GPIO_1 配置成输出模式 */
MSS_GPIO_config(MSS_GPIO_0, MSS_GPIO_OUTPUT_MODE);
MSS_GPIO_config(MSS_GPIO_1, MSS_GPIO_OUTPUT_MODE);
/* GPIO_2配置成输入模式*/
MSS_GPIO_config(MSS_GPIO_2, MSS_GPIO_INPUT_MODE);
/* GPIO_3配置成输入模式,双边沿触发中断 */
MSS_GPIO_config(MSS_GPIO_3, MSS_GPIO_INPUT_MODE| MSS_GPIO_IRQ_EDGE_BOTH);
/* 使能中断 */
MSS_GPIO_enable_irq(MSS_GPIO_3);
MSS_GPIO_2的状态控制GPIO_0上的LED:
while(1)
{
/* 如果GPIO_2输入为0 */
if(MSS_GPIO_get_inputs() & MSS_GPIO_2_MASK)
MSS_GPIO_set_output(MSS_GPIO_0, 0); /* 点亮LED */
else
MSS_GPIO_set_output(MSS_GPIO_0, 1); /* 熄灭LED */
}
其中MSS_GPIO_2_MASK已经在头文件中进行了定义:
#define MSS_GPIO_2_MASK 0x00000004UL
MSS_GPIO_3中断服务函数:
/* MSS_GPIO_3中断服务函数 */
void GPIO3_IRQHandler(void)
{
/* 下降沿 */
if(MSS_GPIO_get_inputs() & MSS_GPIO_3_MASK)
MSS_GPIO_set_output(MSS_GPIO_1, 0); /* 点亮LED */
else /* 上升沿 */
MSS_GPIO_set_output(MSS_GPIO_1, 1); /* 熄灭LED */
MSS_GPIO_clear_irq(MSS_GPIO_3);
}
FPGA工程MSS ENVM加载生成的Hex文件:
编译,分配管脚,因为我的板子原理图中拨码开关没有接上下拉电阻,拨码开关导通是高电平,所以在管脚分配时,配置成了下拉输入。