⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2cslave.c

📁 MCU控制程序
💻 C
字号:
//i2c.c 
#include <iom16v.h> 
#include <eeprom.h>
#include "i2c.h" 


// I2C标准波特率: 
// 低速 100KHz  
// 高速 400KHz  

unsigned char localBuffer[] = "!!"; 
unsigned char localBufferLength = 0x20; 
unsigned char i2csendmax;


unsigned char I2cSendData[I2C_SEND_DATA_BUFFER_SIZE]; 
unsigned char I2cSendDataIndex; 
unsigned char I2cSendDataLength;

unsigned char I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE]; 
unsigned char I2cReceiveDataIndex; 
unsigned char I2cReceiveDataLength;

unsigned char i2creceive_b;  //接收到命令
unsigned char i2creadtime_b; //


// 指向接收处理函数的指针,当本机被选中从接收时调用函数:I2cSlaveReceive 
void (*i2cSlaveReceive)(unsigned char receiveDataLength, unsigned char* recieveData); 
// 指向发送处理函数的指针,当本机被选中从发送时调用函数:I2cSlaveTransmit  
unsigned char (*i2cSlaveTransmit)(unsigned char transmitDataLengthMax, unsigned char* transmitData); 

//设置总线速率 
/******************************************
void i2cSetBitrate(unsigned int  bitrateKHz) 
{ 
   unsigned char bitrate_div; 
   // SCL freq = F_CPU/(16+2*TWBR)) 
   #ifdef TWPS0 
      // 对于用速率分频的AVR (mega128) 
      // SCL freq = F_CPU/(16+2*TWBR*4^TWPS) 
      // set TWPS to zero 
      TWSR&=~(1<<TWPS0);
      TWSR&=~(1<<TWPS1); 
   #endif 
   // 计算分频   CPU=7.3728M
   bitrate_div = ((F_CPU/1000l)/bitrateKHz); 
   if(bitrate_div >= 16) 
      bitrate_div = (bitrate_div-16)/2; 
	    //UDR=bitrate_div;
          TWBR = bitrate_div; 
		  UDR=TWBR;
} **********/

void i2cSetBitrate(void) 
{ 
      TWSR&=~(1<<TWPS0);
      TWSR&=~(1<<TWPS1); 
} 

//总线初始化 
void i2cInit(void) 
{ 
   //设置总线上拉 
 //  #ifdef _MEGA128_INCLUDED_  
   //#ifdef _MEGA64_INCLUDED_  
 //  PORTD.0=1;   // i2c SCL on ATmega128,64 
 //  PORTD.1=1;   // i2c SDA on ATmega128,64 
 // #else  
  PORTC|=(1<<0);   // i2c SCL on ATmega163,323,16,32,等 
  PORTC|=(1<<1);   // i2c SDA on ATmega163,323,16,32,等 
 // #endif 
   // 清空从发送和从接受 
   i2cSlaveReceive = 0; 
   i2cSlaveTransmit = 0; 
   // 设置 i2c 波特率为 100KHz 
   i2cSetBitrate();// 从机模式不需要设置
   // I2C总线使能 
   TWCR|=1<<TWEN; //中断使能
   // 状态设置 
   I2cState = I2C_IDLE; 
   // 开I2C中断和回应 
          TWCR|=1<<TWIE; 
          TWCR|=1<<TWEA; 
    
  // asm("sei"); 
   i2cSetLocalDeviceAddr(I2C_ADDR);//设置从地址
} 
void i2cSetLocalDeviceAddr(unsigned char deviceAddr) 
{ 
 // 设置本机从地址 (从方式时) 需根据实际修改  末位强制为0,非广播方式
   //TWAR=(deviceAddr&0xFE)|(genCallEn?1:0);
    TWAR=deviceAddr&0xFE;         //地址不需要右移
}
/*****************
void i2cSetLocalDeviceAddr(unsigned char deviceAddr, unsigned char genCallEn) 
{ 
 // 设置本机从地址 (从方式时) 需根据实际修改  末位强制为0,非广播方式
   //TWAR=(deviceAddr&0xFE)|(genCallEn?1:0);
    TWAR=deviceAddr&0xFE
} ****************/

void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(unsigned char receiveDataLength, unsigned char* recieveData)) 
{ 
   i2cSlaveReceive = i2cSlaveRx_func; 
} 

void i2cSetSlaveTransmitHandler(unsigned char (*i2cSlaveTx_func)(unsigned char transmitDataLengthMax, unsigned char* transmitData)) 
{ 
   i2cSlaveTransmit = i2cSlaveTx_func; 
} 

void i2cSendStart(void) 
{ 
    
  TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWSTA); 
} 

void i2cSendStop(void) 
{ 
   // 发送停止条件,保持TWEA以便从接收 
   TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO); 
} 

void i2cWaitForComplete(void) 
{ 
   // 等待i2c 总线操作完成 
   while( !(TWCR&(1<<TWINT)) ); 
} 

void i2cSendByte(unsigned char data) 
{ 
   // 装载数据到 TWDR 
          TWDR=data; 
   // 发送开始 
          TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT); 
} 

void i2cReceiveByte(unsigned char ackFlag) 
{ 
   //开始通过 i2c 接收 
   if( ackFlag ) 
   { 
      // ackFlag = TRUE: 数据接收后回应ACK  
       TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWEA); 
   } 
   else 
   { 
      // ackFlag = FALSE: 数据接收后无回应 
       TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT); 
   } 
} 

unsigned char i2cGetReceivedByte(void) 
{ 
   // 返回接收到的数据 
   return( TWDR ); 
} 

unsigned char i2cGetStatus(void) 
{ 
   // 返回总线状态 
   return(TWSR); 
} 
// 从操作 
void i2cSlaveReceiveService(unsigned char receiveDataLength, unsigned char* receiveData) 
{ 
   unsigned char i; 
  //此函数在本机被选中为从写入时运行 
   // 接收到的数据存入本地缓冲区 
   for(i=0; i<receiveDataLength; i++) 
   { 
      localBuffer[i] = *receiveData++; 
   } 
   localBufferLength = receiveDataLength; //接收的数据个数

} 

unsigned char i2cSlaveTransmitService(unsigned char transmitDataLengthMax, unsigned char* transmitData) 
{ 
   unsigned char i; 

   //此函数在本机被选中为从读出时运行 
   //要发送的数据存入发送缓冲区 
   for(i=0; i<localBufferLength; i++) 
   { 
      *transmitData++ = localBuffer[i]; 
   } 

   localBuffer[0]++; 

   return localBufferLength; 
} 

/**********************************************/
eI2cStateType i2cGetState(void) 
{ 
   return I2cState; 
}  

// I2C (TWI) 中断服务程序 
//interrupt [TWI] void twi_isr(void) 
#pragma interrupt_handler twi_isr:18
void twi_isr(void)
{ 
   //读状态位 
   unsigned char status; 
          status = TWSR & TWSR_STATUS_MASK; 
   switch(status) 
   { 
   
/********************************************/
   // 从接收状态码 
   case TW_SR_SLA_ACK:               // 0x60: 自己的SLA+W 已经被接收,ACK 已返回 
   case TW_SR_ARB_LOST_SLA_ACK:// 0x68: SLA+R/W 作为主机的仲裁失败;自己的SLA+W 已经被接收,ACK 已返回 
   case TW_SR_GCALL_ACK:            // 0x70: 接收到广播地址,ACK 已返回 
   case TW_SR_ARB_LOST_GCALL_ACK: // 0x78: SLA+R/W 作为主机的仲裁失败;接收到广播地址,ACK 已返回 
    
      // 被选中为从写入 (数据将从主机接收) 
      // 设置状态 
      //UDR=0x66;
      I2cState = I2C_SLAVE_RX; 
      // 缓冲准备 
      I2cReceiveDataIndex = 0; 
	  // 接收数据,回应 ACK 
      TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWEA); 
      break; 
//----------------------------读取数据,有应答位-----------------------	  
   case TW_SR_DATA_ACK:            // 0x80: 以前以自己的 SLA+W 被寻址;数据已经被接收,ACK 已返回 
//   case TW_SR_GCALL_DATA_ACK:   // 0x90: 以前以广播方式被寻址;数据已经被接收,ACK 已返回 
       
       
      I2cReceiveData[I2cReceiveDataIndex++] = TWDR;
	  //UDR=I2cReceiveData[I2cReceiveDataIndex-1];
	
      //检查接收缓冲区状态 是否溢出
      if(I2cReceiveDataIndex < 7)// 
      { 
         // 接收数据,回应 ACK 
         i2cReceiveByte(TRUE); 
		 
      } 
      else 
      { 
         // 接收数据,回应 NACK 
         i2cReceiveByte(FALSE); 
		 
      } 
      break; 
//########################################################################	  
   case TW_SR_DATA_NACK:            // 0x88: 以前以自己的 SLA+W 被寻址;数据已经被接收,NOT ACK 已返回 
//   case TW_SR_GCALL_DATA_NACK:   // 0x98: 以前以广播方式被寻址;数据已经被接收,NOT ACK 已返回 
    
      // 接收数据,回应 NACK 
      i2cReceiveByte(FALSE); 
      break; 
//---------------------无应答位------------------------------------------	  
   case TW_SR_STOP:               // 0xA0: 在以从机工作时接收到STOP或重复START 
    TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWEA); 
      // i2c 接收完成 
//      if(i2cSlaveReceive)  
//                    i2cSlaveReceive(I2cReceiveDataIndex, I2cReceiveData); 
      // 设置状态 
      I2cState = I2C_IDLE;           //i2c接受结束,可以处理数据
	  i2creceive_b=1;                //i2c命令处理申请
	  break; 

   // ---------------------从发送------------------------------------ 
   case TW_ST_SLA_ACK:               // 0xA8: 自己的SLA+R 已经被接收,ACK 已返回 
   case TW_ST_ARB_LOST_SLA_ACK:// 0xB0: SLA+R/W 作为主机的仲裁失败;自己的SLA+R 已经被接收,ACK 已返回 
    
      // 被选中为从读出 (数据将从传回主机) 
      // 设置状态 
	  //UDR=0x65;
      I2cState = I2C_SLAVE_TX;
	 /* if(catt[0]==catt[1])
	  {
	    I2cReceiveData[0]=catt[0];
	  }
	  else if(catt[0]==catt[2])
	  {I2cReceiveData[0]=catt[0];
	  }
	  else if(catt[1]==catt[2])
	  {I2cReceiveData[0]=catt[2];
	  }*/ 
	  // I2cSendData[0]=catt;
      // 数据请求 需要发送的字节长度
     // if(i2cSlaveTransmit) I2cSendDataLength = i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE, I2cSendData); //更改发送数据长度
      I2cSendDataIndex = 0;
	  if(i2creadtime_b)
			{
			  i2csendmax=7; //发送时间数据7字节
			}
	  else  {
	          i2csendmax=3;//正常发送3字节
		    }	
	//  I2cSendData[0]=EEPROMread(0xff);
   case TW_ST_DATA_ACK:            // 0xB8: TWDR 里数据已经发送,接收到ACK 
    
      // 发送数据位 
	         TWDR=I2cSendData[I2cSendDataIndex++];
			// UDR=I2cSendData[I2cSendDataIndex-1];
			// if(I2cSendDataIndex==1) 
			 //{
			  //I2cSendData[0]=catt;
			 // UDR=0x55;//}
	  PORTA|=0x80;//PA7置高,取消申请
	  if(I2cSendDataIndex <  i2csendmax) //发送字节
         // 回应 ACK 
                TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWEA); 
      else 
         // 回应 NACK 
                TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT);
				i2creadtime_b=0; 
      break; 
	//##################################################################  
   case TW_ST_DATA_NACK:            // 0xC0: TWDR 里数据已经发送接收到NOT ACK 
   case TW_ST_LAST_DATA:            // 0xC8: TWDR 的一字节数据已经发送(TWAE = “0”);接收到ACK 
       
      // 全部完成 
      // 从方式开放 
	  //UDR=0xff;
      TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWEA); 
      // 设置状态 
      I2cState = I2C_IDLE; 
	  //i2creceive_b=1;
	  //UDR=0x55;
	  i2creadtime_b=0; 
	
      break; 


   case TW_NO_INFO:                 // 0xF8: 没有相关的状态信息;TWINT = “0” 
      // 无操作 
       
      break; 
   case TW_BUS_ERROR:               // 0x00: 由于非法的START 或STOP 引起的总线错误 
    
      // 内部硬件复位,释放总线 
      TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWSTO)|(1<<TWEA); 
      // 设置状态 
      I2cState = I2C_IDLE; 
	  //i2creceive_b=1;
      break; 
   } 
} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -