lpc221x在其开发板上带的源码里面是不支持2bytes的子地址,只有单字节,所以是不能接像AT24C256 多字节子地址的器件,必顺跟据I2C的状态表来修改中断程序和传输函数.
第一步,修改中断函数:原函数如下,
/****************************************************************************
* 名称:IRQ_I2C()
* 功能:I2C中断,通过判断I2C状态字进行相应的操作。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void __irq IRQ_I2C(void)
{ uint8 sta;
sta = I2STAT; // 读出I2C状态字
switch(sta)
{ case 0x08: // 己发送起始条件
if(1==I2C_suba_en) I2DAT = I2C_sla&0xFE; // 指定子地址读时,先写入地址
else I2DAT = I2C_sla; // 否则直接发送从机地址
I2CONCLR = 0x28; // SI="0"
break;
case 0x10:
I2DAT = I2C_sla; // 重启动总线后,发送从地址
I2CONCLR = 0x28; // SI="0"
break;
case 0x18: // 已发送SLA+W,并已接收应答
if(0==I2C_suba_en) // 无子地址,则直接发送数据
{ if(I2C_num>0)
{ I2DAT = *I2C_buf++;
I2CONCLR = 0x28;
I2C_num--;
}
else
{ I2CONSET = 0x10; // 无数据发送,结束总线
I2CONCLR = 0x28;
I2C_end = 1; // 设置总线操作结束标志
}
break;
}
if(1==I2C_suba_en) // 发送子地址
{ I2DAT = I2C_suba;
I2CONCLR = 0x28;
}
if(2==I2C_suba_en)
{ I2DAT = I2C_suba;
I2CONCLR = 0x28;
I2C_suba_en = 0; // 子地址己处理
}
break;
case 0x28: // 已发送I2C数据,并接收到应答
if(0==I2C_suba_en) // 无子地址,则直接发送数据
{ if(I2C_num>0)
{ I2DAT = *I2C_buf++;
I2CONCLR = 0x28;
I2C_num--;
}
else
{ I2CONSET = 0x10; // 无数据发送,结束总线
I2CONCLR = 0x28;
I2C_end = 1;
}
break;
}
if(1==I2C_suba_en) // 若是指定地址读,则重新启动总线
{ I2CONSET = 0x20;
I2CONCLR = 0x08;
I2C_suba_en = 0; // 子地址己处理
}
break;
case 0x20:
case 0x30:
case 0x38:
I2CONCLR = 0x28; // 总线进入不可寻址从模式
I2C_end = 0xFF; // 总线出错,设置标志
break;
case 0x40: // 己发送SLA+R,并已接收到应答
if(1==I2C_num) // 最后一字节,接收数据后发送非应答信号
{ I2CONCLR = 0x2C; // AA="0",接收到数据后产生非应答
}
else // 接收数据并发送应答信号
{ I2CONSET = 0x04; // AA="1",接收到数据后产生应答
I2CONCLR = 0x28;
}
break;
case 0x50:
*I2C_buf++ = I2DAT; // 读取数据
I2C_num--;
if(1==I2C_num)
{ I2CONCLR = 0x2C; // AA="0",接收到数据后产生非应答
}
else
{ I2CONSET = 0x04; // AA="1",接收到数据后产生应答
I2CONCLR = 0x28;
}
break;
case 0x58:
*I2C_buf++ = I2DAT; // 读取最后一字节数据
I2CONSET = 0x10; // 结束总线
I2CONCLR = 0x28;
I2C_end = 1;
break;
case 0x48:
I2CONCLR = 0x28; // 总线进入不可寻址从模式
I2C_end = 0xFF;
break;
default:
break;
}
VICVectAddr = 0x00; // 中断处理结束
}
状态的意义详情请参考“80C51系列派生器件8XC552/562概述”数据手册中的表4,数据手册可通过下面的地址从网上下载:http://www.semiconductors.philips.com/acrobat/various/8XC552_562OVERVIEW_2.pdf
其中case 0x08: 的状态是A START condition has been transmitted 接下发送子地址,因此,if(1==I2C_suba_en) I2DAT = I2C_sla&0xFE; // 指定子地址读时,先写入地址
else I2DAT = I2C_sla; // 否则直接发送从机地址
I2CONCLR = 0x28; // SI="0"
break;
要改成,
if(I2C_suba_en != 0)
{I2DAT = I2C_sla&0xFE; // 指定子地址读时,先写入地址
I2C_suba_en--;}
else I2DAT = I2C_sla; // 否则直接发送从机地址
I2CONCLR = 0x28; // SI="0"
break;
这样可以在读重启动之前写入子地址,接下来就会进入case 18
case 0x18: // 已发送SLA+W,并已接收应答
if(0==I2C_suba_en) // 无子地址,则直接发送数据
{ if(I2C_num>0)
{ I2DAT = *I2C_buf++;
I2CONCLR = 0x28;
I2C_num--;
}
else
{ I2CONSET = 0x10; // 无数据发送,结束总线
I2CONCLR = 0x28;
I2C_end = 1; // 设置总线操作结束标志
}
break;
}
if(I2C_suba_en!= 0) // 发送子地址
{ I2DAT = I2C_suba[I2C_suba_en];
I2C_suba_en--;
I2CONCLR = 0x28;
}
break;
因此还需要全局建立一个子地址数组,高位在高下标
接下进入case 0x10 发送读与器件地址,这里不用改,
再进入case 50 收数据,这里也不用改,
再进入case 58 收完最后结束
以上是读取数据,另外写数据不用变,在case 18里面可以接着地址写。
到此中断改造完毕,
其它函数如 uint8 ISendStr(uint8 sla, uint8 suba, uint8 *s, uint8 no)
双字节地址改成 uint8 ISendStr(uint8 sla, uint16 xsuba, uint8 *s, uint8 no)
这里需要把xsuba付给全局建立一个子地址数组。
文章评论(0条评论)
登录后参与讨论