硬件中断方式I2C(CVAVR)
时间:11-18
来源:互联网
点击:
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 break;
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 //i2c接收完成
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 //回应ACK
TWCR=TWCR&TWCR_CMD_MASK|(1 else
//回应NACK
TWCR=TWCR&TWCR_CMD_MASK|(1 break;
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();
}
{
//读状态位
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();
}
硬件中断方式I2CCVAV 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
