/*********************************************************************************************************
**文件名称:I2CINT.c
**功能说明:硬件I2C中断方式软件包。
**使用说明:软件包采用中断方式进行操作。
********************************************************************************************************/
#include "config1.h"
/*定义用于和I2C中断传送信息的全局变量*/
volatile uint8 slarv; //子地址接收标志,为1时表示已接收从机子地址
volatile uint32 adrpoint; //定义从机缓冲区读写操作指针
volatile uint8 I2C_n; //I2C器件顺序号
volatile uint8 I2C_sla; //I2C器件从地址
volatile uint32 I2C_suba; //I2C器件的内部子地址
volatile uint8 I2C_suba_num; //I2C子地址字节数
volatile uint8 *I2C_buf; //I2C数据缓冲区指针,
//如果要将I2C接口设置为从机模式,
//那么,在调用软件包前要设置I2C数据缓冲区指针 I2C_buf
volatile uint32 I2C_num; //要读取/写入的数据个数
volatile uint8 I2C_end; //I2C总线结束标志:结束总线时置1
volatile uint8 I2C_suba_en; /* 子地址控制
0-子地址已经处理或者不需要子地址
1-读取操作
2-写操作
*/
/*********************************************************************************************************
**函数名称:IRQ_I2C()
**函数功能:硬件I2C服务程序
**入口参数:无
**出口参数:无
**说明:注意处理子地址为2字节的情况
********************************************************************************************************/
void IRQ_I2C(void)
{
/* 读取I2C状态寄存器I2STAT
按照全局变量的设置进行操作及设置软件标志
清除中断逻辑,中断返回
*/
uint8 stat; //用来读取I2C状态寄存器I2STAT
stat = *((volatile uint32 *)(&I2C0STAT) + (I2C_n*0x10000)); //读取I2STAT,I2STAT=0xE001C004
switch(stat & 0xF8)
{
/*根据状态码进行相应的处理*/
case 0x08: /*已发送起始条件*/ //主发送和主接收都有
/*装入SLA+W或者SLA+R*/
if(I2C_suba_en == 1) /*SLA+R*/ //指定子地址读
{
*((volatile uint32 *)(&I2DAT) + (I2C_n*0x10000)) = I2C_sla &0xfe; //先写入地址
}
else /*SLA+W*/
{
*((volatile uint32 *)(&I2DAT) + (I2C_n*0x10000)) = I2C_sla &0xfe; //直接发送从机地址
}
/*清零SI位*/
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = (1<<3)| //SI
(1<<5); //STA
break;
case 0x10: /*已发送重复起始条件*/ //主发送和主接收都有
/*装入SLA+W或者SLA+R*/
*((volatile uint32 *)(&I2DAT) + (I2C_n*0x10000)) = I2C_sla; //重起总线后,重发从地址
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000))= 0x28; //清零SI,STA
break;
case 0x18:
case 0x28: /*已发送I2DAT中的数据,已接收ACK*/
if(I2C_suba_en == 0)
{
if(I2C_num > 0) //如果还有数据需要读取
{
*((volatile uint32 *)(&I2DAT) + (I2C_n*0x10000)) = *I2C_buf++; //读取数据
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x28; //清零SI,STA
I2C_num--; //字节数减1
}
else /*没有数据发送了*/
{
/*停止总线*/
*((volatile uint32 *)(&I2CONSET) + (I2C_n*0x10000)) = (1<<4); //STO
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x28; //清零SI,STA
I2C_end = 1; //总线已经停止
}
}
if(I2C_suba_en == 1) /*若是指定地址读,则重新启动总线*/
{
if(I2C_suba_num == 2) //如果是双字节子地址
{
*((volatile uint32 *)(&I2DAT) + (I2C_n*0x10000)) = ((I2C_suba>>8) & 0xff); //先发送地址字节
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x28; //清零SI,STA
I2C_suba_num--; //子地址字节数减1
break;
}
if(I2C_suba_num == 1) //如果是双字节子地址
{
*((volatile uint32 *)(&I2DAT) + (I2C_n*0x10000)) = (I2C_suba & 0xff); //发送子地址低字节或单字节子地址
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x28; //清零SI,STA
I2C_suba_num--;
break;
}
if(I2C_suba_num == 0)
{
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x08; //清零SI
*((volatile uint32 *)(&I2CONSET) + (I2C_n*0x10000)) = 0x20; //置位STA
I2C_suba_en = 0; //子地址已经处理
break;
}
}
if(I2C_suba_en == 2) /*指定子地址写,子地址尚未指定,则发送子地址*/
{
if(I2C_suba_num > 0)
{
if(I2C_suba_num == 2) //如果是双字节子地址
{
*((volatile uint32 *)(&I2DAT) + (I2C_n*0x10000)) =((I2C_suba>>8) & 0xff); //先发送子地址高字节
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) =0x28; //清零SI,STA
I2C_suba_num--; //子地址字节数减1
break;
}
if(I2C_suba_num == 1) //如果是双字节子地址
{
*((volatile uint32 *)(&I2DAT) + (I2C_n*0x10000)) =(I2C_suba & 0xff); //发送子地址低字节或单字节子地址
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) =0x28; //清零SI,STA
I2C_suba_num--;
I2C_suba_en = 0;
break;
}
}
}
break;
case 0x40: /*已发送SLA+R,已接收ACK*/
if(I2C_num <= 1) /*如果是最后一个字节*/
{
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) =1<<2; //下次发送非应答信号
}
else
{
*((volatile uint32 *)(&I2CONSET) + (I2C_n*0x10000)) = 1<<2; //下次发送应答信号
}
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x28; //清零SI,SLA
break;
case 0x20: /*已发送SLA+W,已接收非应答*/
case 0x30: /*已发送I2DAT中的数据,已接收非应答*/
case 0x38: /*在SLA+R/W或数据字节中丢失仲裁*/
case 0x48: /*已发送SLA+R,已接收非应答*/
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x28;
I2C_end = 0xff; //总线出错
break;
case 0x50: /*已接收数据字节,已返回ACK*/
*I2C_buf++ = *((volatile uint32 *)(&I2DAT) + (I2C_n*0x10000));
I2C_num--;
if(I2C_num == 1) /*接收最后一个字节*/
{
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x2c; //STA,SI,AA=0
}
else
{
*((volatile uint32 *)(&I2CONSET) + (I2C_n*0x10000)) = 0x04; //AA=1
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x28;
}
break;
case 0x58: /*已接收数据字节,已返回非应答*/
*I2C_buf++ = *((volatile uint32 *)(&I2DAT) + ((I2C_n*0x40000)/4)); //读取最后一字节数据
*((volatile uint32 *)(&I2CONSET) + (I2C_n*0x10000)) = 0x10; //结束总线
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x28;
I2C_end = 1;
break;
/////////以下为从机模式所对应的状态信息/////////
case 0x60: //接收到自身SLA+W
case 0x68:
slarv = 0;
*((volatile uint32 *)(&I2CONSET) + (I2C_n*0x10000)) = 0x04;
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x38; //清除I2C标志位,STA、STO、SI
break;
case 0xa8: //接收到SLA+R,或已经发送数据并接收到ACK位
case 0xb0:
case 0xb8:
*((volatile uint32 *)(&I2DAT) + (I2C_n*0x10000)) = *(I2C_buf+adrpoint); //将对应地址处的数据放入I2DAT中
adrpoint++;
*((volatile uint32 *)(&I2CONSET) + (I2C_n*0x10000)) = 0x04;
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x38; //清除I2C标志位,STA、STO、SI
break;
case 0x80: //接收到数据
if(slarv==0)
{
adrpoint = *((volatile uint32 *)(&I2DAT) + (I2C_n*0x10000));
slarv = 1;
}
else
{
*(I2C_buf+adrpoint) = *((volatile uint32 *)(&I2DAT) + (I2C_n*0x10000));
adrpoint++;
}
*((volatile uint32 *)(&I2CONSET) + (I2C_n*0x10000)) = 0x04;
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x38; //清除I2C标志位,STA、STO、SI
break;
case 0xc0: //总线结束,或总线重新启动
default: //其它状态
*((volatile uint32 *)(&I2CONSET) + (I2C_n*0x10000)) = 0x04;
*((volatile uint32 *)(&I2CONCLR) + (I2C_n*0x10000)) = 0x38; //清除I2C标志位,STA、STO、SI
break;
}
VICVectAddr = 0x00; //中断处理结束
}
/*********************************************************************************************************
**函数名称:uint8 I2C_Init(uint8 n,uint8 MODE,uint32 Fi2c,uint8 Adr,uint8 slot)
**函数功能:初始化I2C接口
**入口参数:n :I2C接口号,0--I2C0,1--I2C1
** MODE :工作模式,0--从模式,1--主模式
** Fi2c :I2C通信速率,0~400K,如果超过400K,则会强制设置为400KHz,如果设置为从机
评论0