#include "I2C.h"
#include "avr/interrupt.h"
volatile unsigned char I2C_sla; // 从机地址(即器件地址)
volatile unsigned char I2C_suba_1; // 子地址1
volatile unsigned char I2C_suba_2; //子地址2
volatile unsigned char *I2C_buf; // 数据缓冲区指针 (读操作时会被更改)
volatile unsigned char I2C_num; // 操作数据个数 (会被更改)
volatile unsigned char I2C_end; // 操作结束标志,为1时表示操作结束,为0xFF时表示操作失败 (会被设置)
volatile unsigned char I2C_suba_en; // 子地址使能控制,16位读操作时请设置为2,16位地址写操作时请设置为4 (会被更改)
void I2C_Init(void)
{
TWBR=0x72;
TWSR=0xf8; //TWBR=114,TWPS=0,the frequency of the bus=30000HZ
TWCR=0x85; //I2C Enable,clear the int flag and interrupt Enable
}
ISR(TWI_vect)
{
unsigned char sta;
//DispRefresh();
sta = TWSR&0xf8; // 读出I2C状态字
switch(sta)
{ case 0x08: // 己发送起始条件
//DispRefresh();
if(2==I2C_suba_en) TWDR= I2C_sla&0xFE; // 指定子地址读时,先写入地址
else TWDR = I2C_sla; // 否则直接发送从机地址
TWCR=0x85; // SI=0
break;
case 0x10:
TWDR = I2C_sla; // 重启动总线后,发送从地址
TWCR=0x85; // SI=0
break;
case 0x18: // 已发送SLA+W,并已接收应答
if(0==I2C_suba_en) // 无子地址,则直接发送数据
{ if(I2C_num>0)
{ TWDR = *I2C_buf++;
TWCR=0x85;
I2C_num--;
}
else
{
TWCR|=0x90; // 无数据发送,结束总线
I2C_end = 1; // 设置总线操作结束标志
}
break;
}
else if(2==I2C_suba_en) // 发送子地址
{ TWDR = I2C_suba_1;
TWCR=0x85;
}
else if(4==I2C_suba_en)
{ TWDR = I2C_suba_1;
TWCR=0x85;
I2C_suba_en = 3; // 子地址1己处理
}
break;
case 0x28: // 已发送I2C数据,并接收到应答
if(0==I2C_suba_en) // 无子地址,则直接发送数据
{ if(I2C_num>0)
{ TWDR = *I2C_buf++;
TWCR=0x85;
I2C_num--;
}
else
{
TWCR|=0x90; // 无数据发送,结束总线
I2C_end = 1;
}
break;
}
else if(3==I2C_suba_en) //若是指定地址写,继续发送地址2
{
TWDR = I2C_suba_2;
I2C_suba_en=0;
TWCR=0x85;
break;
}
else if(2==I2C_suba_en)
{
TWDR = I2C_suba_2; // 若是指定地址读,继续发送地址2
I2C_suba_en=1;
TWCR=0x85;
break;
}
else if(1==I2C_suba_en) // 完成地址发送2,则重新启动总线
{ //TWCR = 0x25;
TWCR=0xA5;
I2C_suba_en = 0; // 子地址2己处理
break;
}
break;
case 0x20:
case 0x30:
case 0x38:
TWCR=0x85; // 总线进入不可寻址从模式
I2C_end = 0xFF; // 总线出错,设置标志
break;
case 0x40: // 己发送SLA+R,并已接收到应答
if(1==I2C_num) // 最后一字节,接收数据后发送非应答信号
{
TWCR=0x85; // AA=0,接收到数据后产生非应答
}
else // 接收数据并发送应答信号
{ // AA=1,接收到数据后产生应答
TWCR=0xC5;
}
break;
case 0x50:
*I2C_buf++ = TWDR; // 读取数据
I2C_num--;
if(1==I2C_num)
{ TWCR=0x85; // AA=0,接收到数据后产生非应答
}
else
{
TWCR=0xC5; // AA=1,接收到数据后产生应答
}
break;
case 0x58:
*I2C_buf++ = TWDR; // 读取最后一字节数据
TWCR|=0x90; // 结束总线
I2C_end = 1;
break;
case 0x48:
TWCR=0x85; // 总线进入不可寻址从模式
I2C_end = 0xFF;
break;
default:
I2C_end = 0xFF; // 通讯出错
break;
}
// 中断处理结束
}
unsigned char I2C_ht_Send(unsigned char addr,unsigned char sub_addr1,unsigned char sub_addr2,unsigned char *dat,unsigned char num) //eeprom多字节写入驱动
{
I2C_sla = addr; // 写操作的器件地址
I2C_suba_1 = sub_addr1; // 子地址
I2C_suba_2 = sub_addr2; // 子地址
I2C_buf = dat;
I2C_num = num;
I2C_suba_en = 4; // 有子地址写
I2C_end = 0;
TWCR=0xA5; // 设置为主机,并启动总线
while(I2C_end==0);
if(1==I2C_end) return(1);
else return(0);
}
unsigned char I2C_ht_Read(unsigned char addr,unsigned char sub_addr1,unsigned char sub_addr2,unsigned char *dat_re,unsigned char num)
{
I2C_sla = addr+1; // 读操作的器件地址
I2C_suba_1 = sub_addr1; // 子地址
I2C_suba_2 = sub_addr2; // 子地址
I2C_buf = dat_re;
I2C_num = num;
I2C_suba_en = 2; // 有子地址读
I2C_end = 0;
TWCR=0x85;
TWCR=0xA5;// 设置为主机,并启动总线
while(0==I2C_end);
if(1==I2C_end) return(1);
else return(0);
}
评论0