//i2c.h
#defineTWPS00
#defineTWPS11
#defineTWEN2
#defineTWIE0
#defineTWEA6
#defineTWINT7
#defineTWSTA5
#defineTWSTO4
//TWSRvalues(notbits)
//Master
#defineTW_START0x08
#defineTW_REP_START0x10
//MasterTransmitter
#defineTW_MT_SLA_ACK0x18
#defineTW_MT_SLA_NACK0x20
#defineTW_MT_DATA_ACK0x28
#defineTW_MT_DATA_NACK0x30
#defineTW_MT_ARB_LOST0x38
//MasterReceiver
#defineTW_MR_ARB_LOST0x38
#defineTW_MR_SLA_ACK0x40
#defineTW_MR_SLA_NACK0x48
#defineTW_MR_DATA_ACK0x50
#defineTW_MR_DATA_NACK0x58
//SlaveTransmitter
#defineTW_ST_SLA_ACK0xA8
#defineTW_ST_ARB_LOST_SLA_ACK0xB0
#defineTW_ST_DATA_ACK0xB8
#defineTW_ST_DATA_NACK0xC0
#defineTW_ST_LAST_DATA0xC8
//SlaveReceiver
#defineTW_SR_SLA_ACK0x60
#defineTW_SR_ARB_LOST_SLA_ACK0x68
#defineTW_SR_GCALL_ACK0x70
#defineTW_SR_ARB_LOST_GCALL_ACK0x78
#defineTW_SR_DATA_ACK0x80
#defineTW_SR_DATA_NACK0x88
#defineTW_SR_GCALL_DATA_ACK0x90
#defineTW_SR_GCALL_DATA_NACK0x98
#defineTW_SR_STOP0xA0
//Misc
#defineTW_NO_INFO0xF8
#defineTW_BUS_ERROR0x00
//definesandconstants
#defineTWCR_CMD_MASK0x0F
#defineTWSR_STATUS_MASK0xF8
//returnvalues
#defineI2C_OK0x00
#defineI2C_ERROR_NODEV0x01
#defineI2C_SEND_DATA_BUFFER_SIZE0x20
#defineI2C_RECEIVE_DATA_BUFFER_SIZE0x20
#defineF_CPU8000000
#defineTRUE1
#defineFALSE0
//types
typedefenum
{
I2C_IDLE=0,I2C_BUSY=1,
I2C_MASTER_TX=2,I2C_MASTER_RX=3,
I2C_SLAVE_TX=4,I2C_SLAVE_RX=5
}eI2cStateType;
//i2c.c
#include
#include”i2c.h”
//I2C规范波特率:
//低速100KHz
//高速400KHz
//I2C状况和地址变量
staticvolatileeI2cStateTypeI2cState;
staticunsignedcharI2cDeviceAddrRW;
//发送缓冲区
staticunsignedcharI2cSendData[I2C_SEND_DATA_BUFFER_SIZE];
staticunsignedcharI2cSendDataIndex;
staticunsignedcharI2cSendDataLength;
//接纳缓冲区
staticunsignedcharI2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE];
staticunsignedcharI2cReceiveDataIndex;
staticunsignedcharI2cReceiveDataLength;
unsignedcharlocalBuffer[]=”!!”;
unsignedcharlocalBufferLength=0x20;
//指向接纳处理函数的指针,当本机被选中从接纳时调用函数:I2cSlaveReceive
staticvoid(*i2cSlaveReceive)(unsignedcharreceiveDataLength,unsignedchar*recieveData);
//指向发送处理函数的指针,当本机被选中从发送时调用函数:II2cSlaveTransmit
staticunsignedchar(*i2cSlaveTransmit)(unsignedchartransmitDataLengthMax,unsignedchar*transmitData);
//设置总线速率
voidi2cSetBitrate(unsignedintbitrateKHz)
{
unsignedcharbitrate_div;
//SCLfreq=F_CPU/(16+2*TWBR))
#ifdefTWPS0
//关于用速率分频的AVR(mega128)
//SCLfreq=F_CPU/(16+2*TWBR*4^TWPS)
//setTWPStozero
TWSR&=~(1<
//核算分频
bitrate_div=((F_CPU/1000l)/bitrateKHz);
if(bitrate_div>=16)
bitrate_div=(bitrate_div-16)/2;
TWBR=bitrate_div;
}
//总线初始化
voidi2cInit(void)
{
//设置总线上拉
#ifdef_MEGA128_INCLUDED_
//#ifdef_MEGA64_INCLUDED_
PORTD.0=1;//i2cSCLonATmega128,64
PORTD.1=1;//i2cSDAonATmega128,64
#else
PORTC.0=1;//i2cSCLonATmega163,323,16,32,等
PORTC.1=1;//i2cSDAonATmega163,323,16,32,等
#endif
//清空从发送和从承受
i2cSlaveReceive=0;
i2cSlaveTransmit=0;
//设置i2c波特率为100KHz
i2cSetBitrate(100);
//I2C总线使能
TWCR|=1<
I2cState=I2C_IDLE;
//开I2C中止和回应
TWCR|=1<
voidi2cSetLocalDeviceAddr(unsignedchardeviceAddr,unsignedchargenCallEn)
{
//设置本机从地址(从方法时)
TWAR=(deviceAddr&0xFE)|(genCallEn?1:0);
}
voidi2cSetSlaveReceiveHandler(void(*i2cSlaveRx_func)(unsignedcharreceiveDataLength,unsignedchar*recieveData))
{
i2cSlaveReceive=i2cSlaveRx_func;
}
voidi2cSetSlaveTransmitHandler(unsignedchar(*i2cSlaveTx_func)(unsignedchartransmitDataLengthMax,unsignedchar*transmitData))
{
i2cSlaveTransmit=i2cSlaveTx_func;
}
inlinevoidi2cSendStart(void)
{
TWCR=TWCR&TWCR_CMD_MASK|(1<
inlinevoidi2cSendStop(void)
{
//发送中止条件,坚持TWEA以便从接纳
TWCR=TWCR&TWCR_CMD_MASK|(1<
inlinevoidi2cWaitForComplete(void)
{
//等候i2c总线操作完结
while(!(TWCR&(1<
inlinevoidi2cSendByte(unsignedchardata)
{
//装载数据到TWDR
TWDR=data;
//发送开端
TWCR=TWCR&TWCR_CMD_MASK|(1<
inlinevoidi2cReceiveByte(unsignedcharackFlag)
{
//开端经过i2c接纳
if(ackFlag)
{
//ackFlag=TRUE:数据接纳后回应ACK
TWCR=TWCR&TWCR_CMD_MASK|(1<
else
{
//ackFlag=FALSE:数据接纳后无回应
TWCR=TWCR&TWCR_CMD_MASK|(1<
}
inlineunsignedchari2cGetReceivedByte(void)
{
//回来接纳到的数据
return(TWDR);
}
inlineunsignedchari2cGetStatus(void)
{
//回来总线状况
return(TWSR);
}
voidi2cMasterSend(unsignedchardeviceAddr,unsignedcharlength,unsignedchar*data)
{
unsignedchari;
//等候总线预备完结
while(I2cState);
//设置状况
I2cState=I2C_MASTER_TX;
//预备数据
I2cDeviceAddrRW=(deviceAddr&0xFE);//RW为0:写操作
for(i=0;i
I2cSendDataIndex=0;
I2cSendDataLength=length;
//发送开端条件
i2cSendStart();
}
voidi2cMasterReceive(unsignedchardeviceAddr,unsignedcharlength,unsignedchar*data)
{
unsignedchari;
//等候总线预备完结
while(I2cState);
//设置状况
I2cState=I2C_MASTER_RX;
//保存数据
I2cDeviceAddrRW=(deviceAddr|0x01);//RW为1:读操作
I2cReceiveDataIndex=0;
I2cReceiveDataLength=length;
//发送开端条件
i2cSendStart();
//等候数据预备好
while(I2cState);
//取数据
for(i=0;i
}
unsignedchari2cMasterSendNI(unsignedchardeviceAddr,unsignedcharlength,unsignedchar*data)
{
unsignedcharretval=I2C_OK;
//关I2C中止
TWCR&=~(1<
i2cWaitForComplete();
//发送器材写地址
i2cSendByte(deviceAddr&0xFE);
i2cWaitForComplete();
//查看器材是否可用
if(TWSR==TW_MT_SLA_ACK)
{
//发送数据
while(length)
{
i2cSendByte(*data++);
i2cWaitForComplete();
length–;
}
}
else
{
//如未回应器材地址,中止发送,回来过错
retval=I2C_ERROR_NODEV;
}
//发送中止条件,坚持TWEA以便从接纳
i2cSendStop();
while(!(TWCR&(1<
unsignedchari2cMasterReceiveNI(unsignedchardeviceAddr,unsignedcharlength,unsignedchar*data)
{
unsignedcharretval=I2C_OK;
//关I2C中止
TWCR&=~(1<
i2cWaitForComplete();
//发送器材读地址
i2cSendByte(deviceAddr|0x01);
i2cWaitForComplete();
//查看器材是否可用
if(TWSR==TW_MR_SLA_ACK)
{
//接纳数据并回应
while(length>1)
{
i2cReceiveByte(TRUE);
i2cWaitForComplete();
*data++=i2cGetReceivedByte();
length–;
}
//接纳数据无回应(末位信号)
i2cReceiveByte(FALSE);
i2cWaitForComplete();
*data++=i2cGetReceivedByte();
}
else
{
//如未回应器材地址,中止发送,回来过错
retval=I2C_ERROR_NODEV;
}
//发送中止条件,坚持TWEA以便从接纳
i2cSendStop();
//开I2C中止
TWCR|=TWIE;
returnretval;
}
eI2cStateTypei2cGetState(void)
{
returnI2cState;
}
//I2C(TWI)中止服务程序
interrupt[TWI]voidtwi_isr(void)
{
//读状况位
unsignedcharstatus;
status=TWSR&TWSR_STATUS_MASK;
switch(status)
{
//主方法
caseTW_START://0x08:START已发送
caseTW_REP_START://0x10:重复START已发送
//发送器材地址
i2cSendByte(I2cDeviceAddrRW);
break;
//主发送,主接纳状况码
caseTW_MT_SLA_ACK://0x18:SLA+W已发送;接纳到ACK
caseTW_MT_DATA_ACK://0x28:数据已发送;接纳到ACK
if(I2cSendDataIndex
//发送数据
i2cSendByte(I2cSendData[I2cSendDataIndex++]);
}
else
{
//发送中止条件,坚持TWEA以便从接纳
i2cSendStop();
//设置状况
I2cState=I2C_IDLE;
}
break;
caseTW_MR_DATA_NACK://0x58:接纳到数据;NOTACK已回来
//保存终究数据
I2cReceiveData[I2cReceiveDataIndex++]=TWDR;
//持续发送条件
caseTW_MR_SLA_NACK://0x48:SLA+R已发送,接纳到NOTACK
caseTW_MT_SLA_NACK://0x20:SLA+W已发送,接纳到NOTACK
caseTW_MT_DATA_NACK://0x30:数据已发送,接纳到NOTACK
//发送中止条件,坚持TWEA以便从接纳
i2cSendStop();
//设置状况
I2cState=I2C_IDLE;
break;
caseTW_MT_ARB_LOST://0x38:SLA+W或数据的裁定失利
//开释总线
TWCR=TWCR&TWCR_CMD_MASK|(1<
I2cState=I2C_IDLE;
break;
caseTW_MR_DATA_ACK://0x50:接纳到数据,ACK已回来
//保存接纳到的数据位
I2cReceiveData[I2cReceiveDataIndex++]=TWDR;
//查看是否接纳完
caseTW_MR_SLA_ACK://0x40:SLA+R已发送,接纳到ACK
if(I2cReceiveDataIndex<(I2cReceiveDataLength-1))
//数据位将接纳,回复ACK(传送更多字节)
i2cReceiveByte(TRUE);
else
//数据位将接纳,回复NACK(传送最终字节)
i2cReceiveByte(FALSE);
break;
//从接纳状况码
caseTW_SR_SLA_ACK://0x60:自己的SLA+W现已被接纳,ACK已回来
caseTW_SR_ARB_LOST_SLA_ACK://0x68:SLA+R/W作为主机的裁定失利;自己的SLA+W现已被接纳,ACK已回来
caseTW_SR_GCALL_ACK://0x70:接纳到播送地址,ACK已回来
caseTW_SR_ARB_LOST_GCALL_ACK://0x78:SLA+R/W作为主机的裁定失利;接纳到播送地址,ACK已回来
//被选中为从写入(数据将从主机接纳)
//设置状况
I2cState=I2C_SLAVE_RX;
//缓冲预备
I2cReceiveDataIndex=0;
//接纳数据,回应ACK
TWCR=TWCR&TWCR_CMD_MASK|(1<
caseTW_SR_DATA_ACK://0x80:曾经以自己的SLA+W被寻址;数据现已被接纳,ACK已回来
caseTW_SR_GCALL_DATA_ACK://0x90:曾经以播送方法被寻址;数据现已被接纳,ACK已回来
I2cReceiveData[I2cReceiveDataIndex++]=TWDR;
//查看接纳缓冲区状况
if(I2cReceiveDataIndex
//接纳数据,回应ACK
i2cReceiveByte(TRUE);
}
else
{
//接纳数据,回应NACK
i2cReceiveByte(FALSE);
}
break;
caseTW_SR_DATA_NACK://0x88:曾经以自己的SLA+W被寻址;数据现已被接纳,NOTACK已回来
caseTW_SR_GCALL_DATA_NACK://0x98:曾经以播送方法被寻址;数据现已被接纳,NOTACK已回来
//接纳数据,回应NACK
i2cReceiveByte(FALSE);
break;
caseTW_SR_STOP://0xA0:在以从机作业时接纳到STOP或重复START
TWCR=TWCR&TWCR_CMD_MASK|(1<
if(i2cSlaveReceive)
i2cSlaveReceive(I2cReceiveDataIndex,I2cReceiveData);
//设置状况
I2cState=I2C_IDLE;
break;
//从发送
caseTW_ST_SLA_ACK://0xA8:自己的SLA+R现已被接纳,ACK已回来
caseTW_ST_ARB_LOST_SLA_ACK://0xB0:SLA+R/W作为主机的裁定失利;自己的SLA+R现已被接纳,ACK已回来
//被选中为从读出(数据将从传回主机)
//设置状况
I2cState=I2C_SLAVE_TX;
//数据恳求
if(i2cSlaveTransmit)I2cSendDataLength=i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE,I2cSendData);
I2cSendDataIndex=0;
//
caseTW_ST_DATA_ACK://0xB8:TWDR里数据现已发送,接纳到ACK
//发送数据位
TWDR=I2cSendData[I2cSendDataIndex++];
if(I2cSendDataIndex
TWCR=TWCR&TWCR_CMD_MASK|(1<
//回应NACK
TWCR=TWCR&TWCR_CMD_MASK|(1<
caseTW_ST_DATA_NACK://0xC0:TWDR里数据现已发送接纳到NOTACK
caseTW_ST_LAST_DATA://0xC8:TWDR的一字节数据现已发送(TWAE=“0”);接纳到ACK
//悉数完结
//从方法敞开
TWCR=TWCR&TWCR_CMD_MASK|(1<
I2cState=I2C_IDLE;
break;
caseTW_NO_INFO://0xF8:没有相关的状况信息;TWINT=“0”
//无操作
break;
caseTW_BUS_ERROR://0x00:因为不合法的START或STOP引起的总线过错
//内部硬件复位,开释总线
TWCR=TWCR&TWCR_CMD_MASK|(1<
I2cState=I2C_IDLE;
break;
}
}
//从操作
voidi2cSlaveReceiveService(unsignedcharreceiveDataLength,unsignedchar*receiveData)
{
unsignedchari;
//此函数在本机被选中为从写入时运转
//接纳到的数据存入本地缓冲区
for(i=0;i
localBuffer[i]=*receiveData++;
}
localBufferLength=receiveDataLength;
}
unsignedchari2cSlaveTransmitService(unsignedchartransmitDataLengthMax,unsignedchar*transmitData)
{
unsignedchari;
//此函数在本机被选中为从读出时运转
//要发送的数据存入发送缓冲区
for(i=0;i
*transmitData++=localBuffer[i];
}
localBuffer[0]++;
returnlocalBufferLength;
}
#defineTARGET_ADDR0xA0
//测验(24xxyy器材)
voidtestI2cMemory(void)
{
unsignedchari;
unsignedchartxdata[66];
unsignedcharrxdata[66];
txdata[0]=0;
txdata[1]=0;
for(i=0;i<16;i++)
txdata[2+i]=localBuffer[i];
//发送地址和数据
i2cMasterSendNI(TARGET_ADDR,18,txdata);
txdata[18]=0;
//发送地址
i2cMasterSendNI(TARGET_ADDR,2,txdata);
//接纳数据
i2cMasterReceiveNI(TARGET_ADDR,16,rxdata);
//
rxdata[16]=0;
}
voidmain(void)
{
i2cInit();
//设置从接纳函数句柄(此函数在被选中为从接纳时履行)
i2cSetSlaveReceiveHandler(i2cSlaveReceiveService);
//设置从发送函数句柄(此函数在被选中为从发送时履行)
i2cSetSlaveTransmitHandler(i2cSlaveTransmitService);
testI2cMemory();
}