关于片上MCU基本外设的使用,可以查看对应的头文件,里面有非常详细的使用说明。
在嵌入式开发中,一个GPIO通常有输入,输出,外部中断和复用功能。但是对于SmartFusion系列FPGA内部的MCU来说,GPIO只有输入输出和外部中断功能,并没有复用功能。上一篇文章,介绍了片上MSS,即ARM MCU的配置,并使用MCU的GPIO外设驱动了LED,本篇文章介绍MSS_GPIO配置成输入模式,直接读取输入和配置成外部中断。
固件库下载地址:Firmware_MSS_GPIO_Driver_v2.0.105 示例工程,可以参考:
所以最终实现的效果是:
GPIO_2输入低电平时,LED0点亮;GPIO_2输入高电平时,LED0熄灭。GPIO_3从高电平变为低电平时,LED1点亮;GPIO_3从低电平变为高电平时,LED1熄灭在进行正式的配置之前,先来了解一下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 0x00000004ULMSS_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文件:
编译,分配管脚,因为我的板子原理图中拨码开关没有接上下拉电阻,拨码开关导通是高电平,所以在管脚分配时,配置成了下拉输入。
编译运行。