<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

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

          硬件中斷方式I2C(CVAVR)

          作者: 時間:2016-11-18 來源:網(wǎng)絡 收藏
          //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狀態(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ù)的指針,當本機被選中從接收時調(diào)用函數(shù):I2cSlaveReceive
          staticvoid(*i2cSlaveReceive)(unsignedcharreceiveDataLength,unsignedchar*recieveData);
          //指向發(fā)送處理函數(shù)的指針,當本機被選中從發(fā)送時調(diào)用函數(shù):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<TWSR&=~(1<#endif
          //計算分頻
          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
          //清空從發(fā)送和從接受
          i2cSlaveReceive=0;
          i2cSlaveTransmit=0;
          //設置i2c波特率為100KHz
          i2cSetBitrate(100);
          //I2C總線使能
          TWCR|=1<//狀態(tài)設置
          I2cState=I2C_IDLE;
          //開I2C中斷和回應
          TWCR|=1<TWCR|=1<
          #asm("sei");
          }


          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)
          {
          //發(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ù)接收后回應ACK
          TWCR=TWCR&TWCR_CMD_MASK|(1<}
          else
          {
          //ackFlag=FALSE:數(shù)據(jù)接收后無回應
          TWCR=TWCR&TWCR_CMD_MASK|(1<}
          }

          inlineunsignedchari2cGetReceivedByte(void)
          {
          //返回接收到的數(shù)據(jù)
          return(TWDR);
          }

          inlineunsignedchari2cGetStatus(void)
          {
          //返回總線狀態(tài)
          return(TWSR);
          }

          voidi2cMasterSend(unsignedchardeviceAddr,unsignedcharlength,unsignedchar*data)
          {
          unsignedchari;
          //等待總線準備完成
          while(I2cState);
          //設置狀態(tài)
          I2cState=I2C_MASTER_TX;
          //準備數(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;
          //等待總線準備完成
          while(I2cState);
          //設置狀態(tài)
          I2cState=I2C_MASTER_RX;
          //保存數(shù)據(jù)
          I2cDeviceAddrRW=(deviceAddr|0x01);//RW為1:讀操作
          I2cReceiveDataIndex=0;
          I2cReceiveDataLength=length;
          //發(fā)送開始條件
          i2cSendStart();
          //等待數(shù)據(jù)準備好
          while(I2cState);
          //取數(shù)據(jù)
          for(i=0;i*data++=I2cReceiveData[i];
          }

          unsignedchari2cMasterSendNI(unsignedchardeviceAddr,unsignedcharlength,unsignedchar*data)
          {
          unsignedcharretval=I2C_OK;

          //關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
          {
          //如未回應器件地址,停止發(fā)送,返回錯誤

          retval=I2C_ERROR_NODEV;
          }

          //發(fā)送停止條件,保持TWEA以便從接收
          i2cSendStop();
          while(!(TWCR&(1<
          //開I2C中斷
          TWCR|=(1<
          returnretval;
          }

          unsignedchari2cMasterReceiveNI(unsignedchardeviceAddr,unsignedcharlength,unsignedchar*data)
          {
          unsignedcharretval=I2C_OK;

          //關I2C中斷
          TWCR&=~(1<
          //發(fā)送開始條件
          i2cSendStart();
          i2cWaitForComplete();

          //發(fā)送器件讀地址
          i2cSendByte(deviceAddr|0x01);
          i2cWaitForComplete();

          //檢查器件是否可用
          if(TWSR==TW_MR_SLA_ACK)
          {
          //接收數(shù)據(jù)并回應
          while(length>1)
          {
          i2cReceiveByte(TRUE);
          i2cWaitForComplete();
          *data++=i2cGetReceivedByte();
          length--;
          }

          //接收數(shù)據(jù)無回應(末位信號)
          i2cReceiveByte(FALSE);
          i2cWaitForComplete();
          *data++=i2cGetReceivedByte();
          }
          else
          {
          //如未回應器件地址,停止發(fā)送,返回錯誤
          retval=I2C_ERROR_NODEV;
          }

          //發(fā)送停止條件,保持TWEA以便從接收
          i2cSendStop();

          //開I2C中斷
          TWCR|=TWIE;

          returnretval;
          }

          eI2cStateTypei2cGetState(void)
          {
          returnI2cState;
          }

          //I2C(TWI)中斷服務程序
          interrupt[TWI]voidtwi_isr(void)
          {
          //讀狀態(tài)位
          unsignedcharstatus;
          status=TWSR&TWSR_STATUS_MASK;
          switch(status)
          {
          //主方式
          caseTW_START://0x08:START已發(fā)送
          caseTW_REP_START://0x10:重復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();
          //設置狀態(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();
          //設置狀態(tài)
          I2cState=I2C_IDLE;
          break;
          caseTW_MT_ARB_LOST://0x38:SLA+W或數(shù)據(jù)的仲裁失敗


          //釋放總線
          TWCR=TWCR&TWCR_CMD_MASK|(1<//設置狀態(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ù)位將接收,回復ACK(傳送更多字節(jié))
          i2cReceiveByte(TRUE);
          else
          //數(shù)據(jù)位將接收,回復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作為主機的仲裁失敗;自己的SLA+W已經(jīng)被接收,ACK已返回
          caseTW_SR_GCALL_ACK://0x70:接收到廣播地址,ACK已返回
          caseTW_SR_ARB_LOST_GCALL_ACK://0x78:SLA+R/W作為主機的仲裁失?。唤邮盏綇V播地址,ACK已返回

          //被選中為從寫入(數(shù)據(jù)將從主機接收)
          //設置狀態(tài)
          I2cState=I2C_SLAVE_RX;
          //緩沖準備
          I2cReceiveDataIndex=0;
          //接收數(shù)據(jù),回應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ù),回應ACK
          i2cReceiveByte(TRUE);
          }
          else
          {
          //接收數(shù)據(jù),回應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ù),回應NACK
          i2cReceiveByte(FALSE);
          break;
          caseTW_SR_STOP://0xA0:在以從機工作時接收到STOP或重復START
          TWCR=TWCR&TWCR_CMD_MASK|(1<//i2c接收完成
          if(i2cSlaveReceive)
          i2cSlaveReceive(I2cReceiveDataIndex,I2cReceiveData);
          //設置狀態(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作為主機的仲裁失??;自己的SLA+R已經(jīng)被接收,ACK已返回

          //被選中為從讀出(數(shù)據(jù)將從傳回主機)
          //設置狀態(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//回應ACK
          TWCR=TWCR&TWCR_CMD_MASK|(1<else
          //回應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<//設置狀態(tài)
          I2cState=I2C_IDLE;
          break;


          caseTW_NO_INFO://0xF8:沒有相關的狀態(tài)信息;TWINT=“0”
          //無操作

          break;
          caseTW_BUS_ERROR://0x00:由于非法的START或STOP引起的總線錯誤

          //內(nèi)部硬件復位,釋放總線
          TWCR=TWCR&TWCR_CMD_MASK|(1<//設置狀態(tài)
          I2cState=I2C_IDLE;
          break;
          }
          }


          //從操作
          voidi2cSlaveReceiveService(unsignedcharreceiveDataLength,unsignedchar*receiveData)
          {
          unsignedchari;
          //此函數(shù)在本機被選中為從寫入時運行
          //接收到的數(shù)據(jù)存入本地緩沖區(qū)
          for(i=0;i{
          localBuffer[i]=*receiveData++;
          }
          localBufferLength=receiveDataLength;

          }

          unsignedchari2cSlaveTransmitService(unsignedchartransmitDataLengthMax,unsignedchar*transmitData)
          {
          unsignedchari;

          //此函數(shù)在本機被選中為從讀出時運行
          //要發(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ù)在被選中為從接收時執(zhí)行)
          i2cSetSlaveReceiveHandler(i2cSlaveReceiveService);
          //設置從發(fā)送函數(shù)句柄(此函數(shù)在被選中為從發(fā)送時執(zhí)行)
          i2cSetSlaveTransmitHandler(i2cSlaveTransmitService);
          testI2cMemory();

          }


          評論


          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();