XRA1403是一款带有SPI接口的16位GPIO扩展器。上电后,XRA1403在每个I / O引脚上都有内部100K欧姆上拉电阻,可以单独使能。
官网数据下载https://www.alldatasheet.com/datasheetpdf/pdf/839979/EXAR/XRA1403.html
1.封装图
2.引脚功能图
3.硬件设计注意点
IRQ#引脚是开漏,必须接上拉电阻,不然一直为低电平,不能检测中断的到来!
实际使用51K电阻上拉3.3V能正常检测到中断信号。
4.读写命令操作
写命令:
命令格式为16位,前8位是命令,后八位写入数据;
命令如F IGURE 3. SPI W RITE所示,控制命令需要向左移一位(<<1);如写引脚控制状态命令0x06变为0x0c;后面数据如实际情况填写。
读命令:
命令格式为16位,前8位是命令,后八位写入数据;
命令如F IGURE 4. SPI R EAD所示,第一位数据为1,控制命令需要向左移一位(<<1);如读引脚状态命令0x00变为0x80;后面数据如实际情况填写。
命令字节 | 寄存器描述 | 读/写 | 默认数值 |
---|---|---|---|
0x00 0x01 | GSR -GPIO状态 | 只读 | 0xXX |
0x02 0x03 | OCR – 输出控制 | 读/写 | 0xff |
0x04 0x05 | PIR -输入极性反转 | 读/写 | 0x00 |
0x06 0x07 | GCR- GPIO 组态/构造 | 读/写 | 0xFF |
0x08 0x09 | PUR-输入内部上拉电阻启用/禁用 | 读/写 | 0x00 |
0x0a 0x0b | IER-输入中断使能 | 读/写 | 0x00 |
0x0c 0x0d | TSCR - 输出三态控制 | 读/写 | 0x00 |
0x0e 0x0f | ISR -输入中断状态 | 读 | 0x00 |
0x10 0x11 | REIR - 输入上升沿中断使能 | 读/写 | 0x00 |
0x12 0x13 | FEIR - 输入下降沿中断使能 | 读/写 | 0x00 |
0x14 0x15 | IFR - 输入滤波器启用/禁用 | 读/写 | 0xFF |
5.程序
输出、输入、输入上拉等比较简单就直接按照指令操作即可,需要主要引脚状态要使用静态变量,否则下一次使用会覆盖上一次写入的内容。
下面的程序是引脚的配置,实现与主控芯片引脚一样的中断功能,使用的是rt-thread操作系统,其中会涉及到系统定义的相关的结构体和函数调用。
思路:创建一个中断表,把中断注册函数的内容写入表内,当发生中断时,IRQ#引脚低电平,使用主控芯片引脚中断进入扩展IO中断引脚的读取,进入扩展IO中断调用,查找中断引脚的中断服务函数进行调用。
struct rt_pin_irq_hdr ex_pin_irq_hdr_tab[] = //中断表
{
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
{ -1, 0, RT_NULL, RT_NULL},
};
/** \brief xra1403引脚中断注册函数
* \param pin[in] pin 引脚号200-215
* \param mode[in] mode 中断触发模式 上升沿触发,PIN_IRQ_MODE_RISING;下降沿触发,PIN_IRQ_MODE_FALLING;
* \param hdr[in] hdr 引脚中断服务函数
* \param args[in] args 传入数组参数
* \return 错误代码: RT_EOK,成功;否则失败
*
*/
rt_err_t vv_rt_ex_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode,void (*hdr)(void *args), void *args)
{
static int io_irq_mode_rising_0 = 0x00;
static int io_irq_mode_rising_1 = 0x00;
static int io_irq_mode_falling_0 = 0x00;
static int io_irq_mode_falling_1 = 0x00;
rt_uint16_t gpio_pin;
rt_int32_t irqindex = -1;
attach_irq_pin[pin_cnt] = pin;
pin_cnt++;
gpio_pin = pin-200;
irqindex = gpio_pin & 0x00FF;
if (ex_pin_irq_hdr_tab[irqindex].pin == pin &&
ex_pin_irq_hdr_tab[irqindex].hdr == hdr &&
ex_pin_irq_hdr_tab[irqindex].mode == mode &&
ex_pin_irq_hdr_tab[irqindex].args == args)
{
return RT_EOK;
}
if (ex_pin_irq_hdr_tab[irqindex].pin != -1)
{
return RT_EBUSY;
}
ex_pin_irq_hdr_tab[irqindex].pin = pin;
ex_pin_irq_hdr_tab[irqindex].hdr = hdr;
ex_pin_irq_hdr_tab[irqindex].mode = mode;
ex_pin_irq_hdr_tab[irqindex].args = args;
switch (ex_pin_irq_hdr_tab[irqindex].mode)
{
case PIN_IRQ_MODE_RISING:
if(199 < pin&&pin < 208){
io_irq_mode_rising_0 = ex_pin_switch_mode(pin, XRA1403_REIR1, io_irq_mode_rising_0);
}else if(207 < pin&&pin < 216){
io_irq_mode_rising_0 = ex_pin_switch_mode(pin, XRA1403_REIR2, io_irq_mode_rising_1);
}else __nop;
break;
case PIN_IRQ_MODE_FALLING:
if(199 < pin&&pin < 208){
io_irq_mode_falling_0 = ex_pin_switch_mode(pin, XRA1403_FEIR1, io_irq_mode_falling_0);
}else if(207 < pin&&pin < 216){
io_irq_mode_falling_1 = ex_pin_switch_mode(pin, XRA1403_FEIR2, io_irq_mode_falling_1);
}else __nop;
break;
}
return RT_EOK;
}
/** \brief xra1403引脚中断读取
*
* \return IO_interrupt_pin 发生中断引脚号
*
*/
int vv_rt_ex_pin_interrupt_read(void)
{
int IO_interrupt_pin = 0;//发生中断的引脚
int io_cmd1[2] = {XRA1403_ISR1};
int io_cmd2[2] = {XRA1403_ISR2};
int i;
if(io_data_flag == 1){
io_data_flag = 0;
expander_gpio_control(&spi_expander_gpio_device.xra1403_parente,1,io_cmd2);
// rt_kprintf("p1:%x\t\n",io_data);
if(io_data == 0){
expander_gpio_control(&spi_expander_gpio_device.xra1403_parente,1,io_cmd1);
// rt_kprintf("p0:%x\t\n",io_data);
if (((io_data>>7)&0x01) ==1) IO_interrupt_pin=207;
else if(((io_data>>6)&0x01) ==1) IO_interrupt_pin=206;
else if(((io_data>>5)&0x01) ==1) IO_interrupt_pin=205;
else if(((io_data>>4)&0x01) ==1) IO_interrupt_pin=204;
else if(((io_data>>3)&0x01) ==1) IO_interrupt_pin=203;
else if(((io_data>>2)&0x01) ==1) IO_interrupt_pin=202;
else if(((io_data>>1)&0x01) ==1) IO_interrupt_pin=201;
else if((io_data&0x01) == 1) IO_interrupt_pin=200;
else __nop;
}else{
if (((io_data>>7)&0x01) ==1) IO_interrupt_pin=215;
else if(((io_data>>6)&0x01) ==1) IO_interrupt_pin=214;
else if(((io_data>>5)&0x01) ==1) IO_interrupt_pin=213;
else if(((io_data>>4)&0x01) ==1) IO_interrupt_pin=212;
else if(((io_data>>3)&0x01) ==1) IO_interrupt_pin=211;
else if(((io_data>>2)&0x01) ==1) IO_interrupt_pin=210;
else if(((io_data>>1)&0x01) ==1) IO_interrupt_pin=209;
else if((io_data&0x01) == 1) IO_interrupt_pin=208;
else __nop;
}
}
io_data_flag = 1;
for(i=0;i<pin_cnt;i++){
if(IO_interrupt_pin == attach_irq_pin[i] ){
return IO_interrupt_pin;
}
}
return RT_ERROR;
}
/** \brief xra1403引脚中断函数调用
* \param pin[in] pin 引脚号200-215
*
*/
void vv_ex_pin_irq_hdr(uint16_t GPIO_Pin)
{
int16_t ex_irqno;
ex_irqno=GPIO_Pin-200;
if(0<=ex_irqno&&ex_irqno<=15){
if (ex_pin_irq_hdr_tab[ex_irqno].hdr)
{
ex_pin_irq_hdr_tab[ex_irqno].hdr(ex_pin_irq_hdr_tab[ex_irqno].args);
}
}
}
/** \brief xra1403引脚中断函数检测调用
* \param 无
*
*/
void vv_ex_pin_irq_call(void)
{
int io_pin = 0;
if(XRA1403_inter == 1){
io_pin=vv_rt_ex_pin_interrupt_read();
// rt_kprintf("%d\r\n",io_pin);
if(199 < io_pin&&io_pin < 216) vv_ex_pin_irq_hdr(io_pin);
vv_rt_ex_pin_read(202);//清除IC中断标志
vv_rt_ex_pin_read(208);//清除IC中断标志
XRA1403_inter = 0;
}
}