硬件中斷方式I2C(CVAVR)
#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標(biāo)準(zhǔn)波特率:
//低速100KHz
//高速400KHz
//I2C狀態(tài)和地址變量
staticvolatileeI2cStateTypeI2cState;
staticunsignedcharI2cDeviceAddrRW;
//發(fā)送緩沖區(qū)
staticunsignedcharI2cSendData[I2C_SEND_DATA_BUFFER_SIZE];
staticunsignedcharI2cSendDataIndex;
staticunsignedcharI2cSendDataLength;
//接收緩沖區(qū)
staticunsignedcharI2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE];
staticunsignedcharI2cReceiveDataIndex;
staticunsignedcharI2cReceiveDataLength;
unsignedcharlocalBuffer[]="!!";
unsignedcharlocalBufferLength=0x20;
//指向接收處理函數(shù)的指針,當(dāng)本機(jī)被選中從接收時調(diào)用函數(shù):I2cSlaveReceive
staticvoid(*i2cSlaveReceive)(unsignedcharreceiveDataLength,unsignedchar*recieveData);
//指向發(fā)送處理函數(shù)的指針,當(dāng)本機(jī)被選中從發(fā)送時調(diào)用函數(shù):II2cSlaveTransmit
staticunsignedchar(*i2cSlaveTransmit)(unsignedchartransmitDataLengthMax,unsignedchar*transmitData);
//設(shè)置總線速率
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)
{
//設(shè)置總線上拉
#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
//清空從發(fā)送和從接受
i2cSlaveReceive=0;
i2cSlaveTransmit=0;
//設(shè)置i2c波特率為100KHz
i2cSetBitrate(100);
//I2C總線使能
TWCR|=1<
I2cState=I2C_IDLE;
//開I2C中斷和回應(yīng)
TWCR|=1<
#asm("sei");
}
voidi2cSetLocalDeviceAddr(unsignedchardeviceAddr,unsignedchargenCallEn)
{
//設(shè)置本機(jī)從地址(從方式時)
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)
{
//發(fā)送停止條件,保持TWEA以便從接收
TWCR=TWCR&TWCR_CMD_MASK|(1<
inlinevoidi2cWaitForComplete(void)
{
//等待i2c總線操作完成
while(!(TWCR&(1<
inlinevoidi2cSendByte(unsignedchardata)
{
//裝載數(shù)據(jù)到TWDR
TWDR=data;
//發(fā)送開始
TWCR=TWCR&TWCR_CMD_MASK|(1<
inlinevoidi2cReceiveByte(unsignedcharackFlag)
{
//開始通過i2c接收
if(ackFlag)
{
//ackFlag=TRUE:數(shù)據(jù)接收后回應(yīng)ACK
TWCR=TWCR&TWCR_CMD_MASK|(1<
else
{
//ackFlag=FALSE:數(shù)據(jù)接收后無回應(yīng)
TWCR=TWCR&TWCR_CMD_MASK|(1<
}
inlineunsignedchari2cGetReceivedByte(void)
{
//返回接收到的數(shù)據(jù)
return(TWDR);
}
inlineunsignedchari2cGetStatus(void)
{
//返回總線狀態(tài)
return(TWSR);
}
voidi2cMasterSend(unsignedchardeviceAddr,unsignedcharlength,unsignedchar*data)
{
unsignedchari;
//等待總線準(zhǔn)備完成
while(I2cState);
//設(shè)置狀態(tài)
I2cState=I2C_MASTER_TX;
//準(zhǔn)備數(shù)據(jù)
I2cDeviceAddrRW=(deviceAddr&0xFE);//RW為0:寫操作
for(i=0;i
I2cSendDataIndex=0;
I2cSendDataLength=length;
//發(fā)送開始條件
i2cSendStart();
}
voidi2cMasterReceive(unsignedchardeviceAddr,unsignedcharlength,unsignedchar*data)
{
unsignedchari;
//等待總線準(zhǔn)備完成
while(I2cState);
//設(shè)置狀態(tài)
I2cState=I2C_MASTER_RX;
//保存數(shù)據(jù)
I2cDeviceAddrRW=(deviceAddr|0x01);//RW為1:讀操作
I2cReceiveDataIndex=0;
I2cReceiveDataLength=length;
//發(fā)送開始條件
i2cSendStart();
//等待數(shù)據(jù)準(zhǔn)備好
while(I2cState);
//取數(shù)據(jù)
for(i=0;i
}
unsignedchari2cMasterSendNI(unsignedchardeviceAddr,unsignedcharlength,unsignedchar*data)
{
unsignedcharretval=I2C_OK;
//關(guān)I2C中斷
TWCR&=~(1<
//發(fā)送開始條件
i2cSendStart();
i2cWaitForComplete();
//發(fā)送器件寫地址
i2cSendByte(deviceAddr&0xFE);
i2cWaitForComplete();
//檢查器件是否可用
if(TWSR==TW_MT_SLA_ACK)
{
//發(fā)送數(shù)據(jù)
while(length)
{
i2cSendByte(*data++);
i2cWaitForComplete();
length--;
}
}
else
{
//如未回應(yīng)器件地址,停止發(fā)送,返回錯誤
retval=I2C_ERROR_NODEV;
}
//發(fā)送停止條件,保持TWEA以便從接收
i2cSendStop();
while(!(TWCR&(1<
//開I2C中斷
TWCR|=(1<
returnretval;
}
unsignedchari2cMasterReceiveNI(unsignedchardeviceAddr,unsignedcharlength,unsignedchar*data)
{
unsignedcharretval=I2C_OK;
//關(guān)I2C中斷
TWCR&=~(1<
//發(fā)送開始條件
i2cSendStart();
i2cWaitForComplete();
//發(fā)送器件讀地址
i2cSendByte(deviceAddr|0x01);
i2cWaitForComplete();
//檢查器件是否可用
if(TWSR==TW_MR_SLA_ACK)
{
//接收數(shù)據(jù)并回應(yīng)
while(length>1)
{
i2cReceiveByte(TRUE);
i2cWaitForComplete();
*data++=i2cGetReceivedByte();
length--;
}
//接收數(shù)據(jù)無回應(yīng)(末位信號)
i2cReceiveByte(FALSE);
i2cWaitForComplete();
*data++=i2cGetReceivedByte();
}
else
{
//如未回應(yīng)器件地址,停止發(fā)送,返回錯誤
retval=I2C_ERROR_NODEV;
}
//發(fā)送停止條件,保持TWEA以便從接收
i2cSendStop();
//開I2C中斷
TWCR|=TWIE;
returnretval;
}
eI2cStateTypei2cGetState(void)
{
returnI2cState;
}
//I2C(TWI)中斷服務(wù)程序
interrupt[TWI]voidtwi_isr(void)
{
//讀狀態(tài)位
unsignedcharstatus;
status=TWSR&TWSR_STATUS_MASK;
switch(status)
{
//主方式
caseTW_START://0x08:START已發(fā)送
caseTW_REP_START://0x10:重復(fù)START已發(fā)送
//發(fā)送器件地址
i2cSendByte(I2cDeviceAddrRW);
break;
//主發(fā)送,主接收狀態(tài)碼
caseTW_MT_SLA_ACK://0x18:SLA+W已發(fā)送;接收到ACK
caseTW_MT_DATA_ACK://0x28:數(shù)據(jù)已發(fā)送;接收到ACK
if(I2cSendDataIndex
//發(fā)送數(shù)據(jù)
i2cSendByte(I2cSendData[I2cSendDataIndex++]);
}
else
{
//發(fā)送停止條件,保持TWEA以便從接收
i2cSendStop();
//設(shè)置狀態(tài)
I2cState=I2C_IDLE;
}
break;
caseTW_MR_DATA_NACK://0x58:接收到數(shù)據(jù);NOTACK已返回
//保存最終數(shù)據(jù)
I2cReceiveData[I2cReceiveDataIndex++]=TWDR;
//繼續(xù)發(fā)送條件
caseTW_MR_SLA_NACK://0x48:SLA+R已發(fā)送,接收到NOTACK
caseTW_MT_SLA_NACK://0x20:SLA+W已發(fā)送,接收到NOTACK
caseTW_MT_DATA_NACK://0x30:數(shù)據(jù)已發(fā)送,接收到NOTACK
//發(fā)送停止條件,保持TWEA以便從接收
i2cSendStop();
//設(shè)置狀態(tài)
I2cState=I2C_IDLE;
break;
caseTW_MT_ARB_LOST://0x38:SLA+W或數(shù)據(jù)的仲裁失敗
//釋放總線
TWCR=TWCR&TWCR_CMD_MASK|(1<
I2cState=I2C_IDLE;
break;
caseTW_MR_DATA_ACK://0x50:接收到數(shù)據(jù),ACK已返回
//保存接收到的數(shù)據(jù)位
I2cReceiveData[I2cReceiveDataIndex++]=TWDR;
//檢查是否接收完
caseTW_MR_SLA_ACK://0x40:SLA+R已發(fā)送,接收到ACK
if(I2cReceiveDataIndex<(I2cReceiveDataLength-1))
//數(shù)據(jù)位將接收,回復(fù)ACK(傳送更多字節(jié))
i2cReceiveByte(TRUE);
else
//數(shù)據(jù)位將接收,回復(fù)NACK(傳送最后字節(jié))
i2cReceiveByte(FALSE);
break;
//從接收狀態(tài)碼
caseTW_SR_SLA_ACK://0x60:自己的SLA+W已經(jīng)被接收,ACK已返回
caseTW_SR_ARB_LOST_SLA_ACK://0x68:SLA+R/W作為主機(jī)的仲裁失??;自己的SLA+W已經(jīng)被接收,ACK已返回
caseTW_SR_GCALL_ACK://0x70:接收到廣播地址,ACK已返回
caseTW_SR_ARB_LOST_GCALL_ACK://0x78:SLA+R/W作為主機(jī)的仲裁失??;接收到廣播地址,ACK已返回
//被選中為從寫入(數(shù)據(jù)將從主機(jī)接收)
//設(shè)置狀態(tài)
I2cState=I2C_SLAVE_RX;
//緩沖準(zhǔn)備
I2cReceiveDataIndex=0;
//接收數(shù)據(jù),回應(yīng)ACK
TWCR=TWCR&TWCR_CMD_MASK|(1<
caseTW_SR_DATA_ACK://0x80:以前以自己的SLA+W被尋址;數(shù)據(jù)已經(jīng)被接收,ACK已返回
caseTW_SR_GCALL_DATA_ACK://0x90:以前以廣播方式被尋址;數(shù)據(jù)已經(jīng)被接收,ACK已返回
I2cReceiveData[I2cReceiveDataIndex++]=TWDR;
//檢查接收緩沖區(qū)狀態(tài)
if(I2cReceiveDataIndex
//接收數(shù)據(jù),回應(yīng)ACK
i2cReceiveByte(TRUE);
}
else
{
//接收數(shù)據(jù),回應(yīng)NACK
i2cReceiveByte(FALSE);
}
break;
caseTW_SR_DATA_NACK://0x88:以前以自己的SLA+W被尋址;數(shù)據(jù)已經(jīng)被接收,NOTACK已返回
caseTW_SR_GCALL_DATA_NACK://0x98:以前以廣播方式被尋址;數(shù)據(jù)已經(jīng)被接收,NOTACK已返回
//接收數(shù)據(jù),回應(yīng)NACK
i2cReceiveByte(FALSE);
break;
caseTW_SR_STOP://0xA0:在以從機(jī)工作時接收到STOP或重復(fù)START
TWCR=TWCR&TWCR_CMD_MASK|(1<
if(i2cSlaveReceive)
i2cSlaveReceive(I2cReceiveDataIndex,I2cReceiveData);
//設(shè)置狀態(tài)
I2cState=I2C_IDLE;
break;
//從發(fā)送
caseTW_ST_SLA_ACK://0xA8:自己的SLA+R已經(jīng)被接收,ACK已返回
caseTW_ST_ARB_LOST_SLA_ACK://0xB0:SLA+R/W作為主機(jī)的仲裁失??;自己的SLA+R已經(jīng)被接收,ACK已返回
//被選中為從讀出(數(shù)據(jù)將從傳回主機(jī))
//設(shè)置狀態(tài)
I2cState=I2C_SLAVE_TX;
//數(shù)據(jù)請求
if(i2cSlaveTransmit)I2cSendDataLength=i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE,I2cSendData);
I2cSendDataIndex=0;
//
caseTW_ST_DATA_ACK://0xB8:TWDR里數(shù)據(jù)已經(jīng)發(fā)送,接收到ACK
//發(fā)送數(shù)據(jù)位
TWDR=I2cSendData[I2cSendDataIndex++];
if(I2cSendDataIndex
TWCR=TWCR&TWCR_CMD_MASK|(1<
//回應(yīng)NACK
TWCR=TWCR&TWCR_CMD_MASK|(1<
caseTW_ST_DATA_NACK://0xC0:TWDR里數(shù)據(jù)已經(jīng)發(fā)送接收到NOTACK
caseTW_ST_LAST_DATA://0xC8:TWDR的一字節(jié)數(shù)據(jù)已經(jīng)發(fā)送(TWAE=“0”);接收到ACK
//全部完成
//從方式開放
TWCR=TWCR&TWCR_CMD_MASK|(1<
I2cState=I2C_IDLE;
break;
caseTW_NO_INFO://0xF8:沒有相關(guān)的狀態(tài)信息;TWINT=“0”
//無操作
break;
caseTW_BUS_ERROR://0x00:由于非法的START或STOP引起的總線錯誤
//內(nèi)部硬件復(fù)位,釋放總線
TWCR=TWCR&TWCR_CMD_MASK|(1<
I2cState=I2C_IDLE;
break;
}
}
//從操作
voidi2cSlaveReceiveService(unsignedcharreceiveDataLength,unsignedchar*receiveData)
{
unsignedchari;
//此函數(shù)在本機(jī)被選中為從寫入時運(yùn)行
//接收到的數(shù)據(jù)存入本地緩沖區(qū)
for(i=0;i
localBuffer[i]=*receiveData++;
}
localBufferLength=receiveDataLength;
}
unsignedchari2cSlaveTransmitService(unsignedchartransmitDataLengthMax,unsignedchar*transmitData)
{
unsignedchari;
//此函數(shù)在本機(jī)被選中為從讀出時運(yùn)行
//要發(fā)送的數(shù)據(jù)存入發(fā)送緩沖區(qū)
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];
//發(fā)送地址和數(shù)據(jù)
i2cMasterSendNI(TARGET_ADDR,18,txdata);
txdata[18]=0;
//發(fā)送地址
i2cMasterSendNI(TARGET_ADDR,2,txdata);
//接收數(shù)據(jù)
i2cMasterReceiveNI(TARGET_ADDR,16,rxdata);
//
rxdata[16]=0;
}
voidmain(void)
{
i2cInit();
//設(shè)置從接收函數(shù)句柄(此函數(shù)在被選中為從接收時執(zhí)行)
i2cSetSlaveReceiveHandler(i2cSlaveReceiveService);
//設(shè)置從發(fā)送函數(shù)句柄(此函數(shù)在被選中為從發(fā)送時執(zhí)行)
i2cSetSlaveTransmitHandler(i2cSlaveTransmitService);
testI2cMemory();
}
評論