新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 硬件中斷方式I2C(CVAVR)

硬件中斷方式I2C(CVAVR)

作者: 時間:2016-11-18 來源:網(wǎng)絡(luò) 收藏
//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標(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<TWSR&=~(1<#endif
//計算分頻
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<//狀態(tài)設(shè)置
I2cState=I2C_IDLE;
//開I2C中斷和回應(yīng)
TWCR|=1<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;iI2cSendData[i]=*data++;
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*data++=I2cReceiveData[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<//設(shè)置狀態(tài)
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<break;
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<//i2c接收完成
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//回應(yīng)ACK
TWCR=TWCR&TWCR_CMD_MASK|(1<else
//回應(yīng)NACK
TWCR=TWCR&TWCR_CMD_MASK|(1<break;
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<//設(shè)置狀態(tài)
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<//設(shè)置狀態(tài)
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();

}


關(guān)鍵詞: 硬件中斷方式I2CCVAV

評論


技術(shù)專區(qū)

關(guān)閉