/************************************************************************* Send one byte to I2C device Input: byte to be transfered Return: 0 write successful 1 write failed *************************************************************************/ unsigned char lib_i2c_write(unsigned char data) { int i = 8; // transmit byte while (i--) { SCL_L; I2C_delay(); if (data & 0x80) SDA_H; else SDA_L; data <<= 1; I2C_delay(); SCL_H; I2C_delay(); } SCL_L; if (lib_i2c_waitack()) { lib_i2c_stop(); return 1; } return 0; }
uint8_t I2C_gen_start(void) { // Release SCL I2C_PORT |= (1<<I2C_SCL); while(!(I2C_PORT & (1<<I2C_SCL))) ; #ifdef I2C_FAST_MODE I2C_delay(I2C_T2); #else I2C_delay(I2C_T1); #endif // Generate start condition I2C_PORT &= ~(1<<I2C_SDA); I2C_delay(I2C_T2); I2C_PORT &= ~(1<<I2C_SCL); I2C_PORT |= (1<<I2C_SDA); #ifdef SIGNAL_VERIFY // Check that the start condition was detected if (!(USISR & (1<<USISIF))) { I2C_state.errorState = I2C_ERR_MISSING_START_CON; return FALSE; } #endif return TRUE; }
BUS_Status I2C_Start(void) { //before: SCL=H SDA=H,means bus is free SDA_H; //1 SCL_H; //2 I2C_delay(); //3 if(!(SDA_read)) { ERROR_MACRO(IIC_DEV,I2C_Start_ERROR_BUS_BUSY); return BUS_BUSY; } SDA_L; //4 I2C_delay(); //5 // SDA_L; //6 // I2C_delay(); //7 if(SDA_read) { ERROR_MACRO(IIC_DEV,I2C_Start_ERROR_BUS_ERROR); return BUS_ERROR; } SCL_L; //After: SCL=L SDA=L return BUS_READY; }
////////////////////////////////////////////////////////////////////// // Returns 0 for no errors = the ACK bit from the slave unsigned short I2C_Wr(unsigned short data) { unsigned short ret=0,i; // grab the data for(i = 0; i < 8; i++) { I2C_SCL_0; // Clock low if (data & 0x80) I2C_SDA_1; else I2C_SDA_0; // Data output data <<= 1; // Next data bit. I2C_delay(); // low T/2. I2C_SCL_1; // Clock released to high. I2C_delay(); // high T/2. } // get ACK or NACK I2C_SCL_0; I2C_SDA_1; // Release the data line SET_PIN_INPUT(I2C_SDA_PIN); I2C_delay(); // low T/2. I2C_SCL_1; // Sample the ACK ret = I2C_SDA_IN; I2C_delay(); // high T/2. I2C_SCL_0; // Return clock to safe state SET_PIN_OUTPUT(I2C_SDA_PIN); return ret; }
BUS_ACK_Status I2C_WaitAck(void) { //等待ACK应该是在发送完数据之后,所以之前: // SCL=H SDA=DATA unsigned char ucErrTime=0; //SDA_H;SDA_H;SDA_H;I2C_delay(); //初始化数据是NACK,不能拉低! SCL_L; //假设你是从机->SCL=L时更新数据,SDA=H时数据是保持的 I2C_delay(); //保持一下 //while(1); SCL_H; //此时拉高SCL,于是从机的数据应该是保持的 I2C_delay(); //等待数据就位 while(SDA_read)//读到H->NACK,适当等待 { ucErrTime++; if(ucErrTime>=50)//一小段时间后还是NACK->是NACK { //ERROR_MACRO(IIC_DEV,I2C_ERROR_BUS_NACK); printf("NoACK\r\n"); //此时SCL=H SDA =H,直接STOP I2C_Stop(); return BUS_NACK; } } SCL_L; //拉低SCL,保持总线BUSY SDA_H; //更具I2C协议P10SDA应该在SCL变为L之后拉高 I2C_delay(); //SCL=L SDA=ACK/NACK return BUS_ACK; }
unsigned char I2C_ReceiveByte(void) //数据从高位到低位// { unsigned char i=8; unsigned char ReceiveByte=0x00; while(i--) { ReceiveByte<<=1; SCL_L;I2C_delay(); SCL_H;//给出一个上升沿,使设备输出SDA数据 I2C_delay();//保证数据从设备中输出了 if(SDA_read) { ReceiveByte|=0x01; } I2C_delay(); } SCL_L; //SDA_L; //I2/C_delay();I2C_delay();I2C_delay();I2C_delay(); //I2C_delay();I2C_delay();I2C_delay();I2C_delay(); return ReceiveByte; }
// Run the shift register until the counter overflows // Function resets SDA line to output on return uint8_t I2C_byte_xfer(uint8_t reg) { // Preset counter USISR = reg; // Setup control register for clock strobe reg = (1<<USIWM1) | (1<<USICS1) | (1<<USICLK) | (1<<USITC); do { I2C_delay(I2C_T1); // Positive edge USICR = reg; // Wait for clock stretching while (!(I2C_PIN & (1<<I2C_SCL))) ; I2C_delay(I2C_T2); // Negative edge USICR = reg; } while (!(USISR & (1<<USIOIF))); I2C_delay(I2C_T1); // Save shift register reg = USIDR; // Release SDA USIDR = 0xFF; // Set SDA as output I2C_DDR |= (1<<I2C_SDA); return reg; }
//不产生ACK应答 static void IIC_NAck(void) { SDA_OUT(); IIC_SDA(1); IIC_SCL(1); I2C_delay(); IIC_SCL(0); I2C_delay(); }
//产生IIC停止信号 static void IIC_Stop(void) { SDA_OUT();//sda线输出 IIC_SDA(0);//STOP:when CLK is high DATA change form low to high IIC_SCL(1); I2C_delay(); IIC_SDA(1);//发送I2C总线结束信号 I2C_delay(); }
/******************************************************************************* * Function Name : I2C_Stop * Description : None * Input : None * Output : None * Return : None * Attention : None *******************************************************************************/ static void I2C_Stop(void) { SDA_L; I2C_delay(); SCL_H; I2C_delay(); SDA_H; I2C_delay(); }
/************************************************************************* Terminates the data transfer and releases the I2C bus *************************************************************************/ void lib_i2c_stop(void) { SCL_L; I2C_delay(); SDA_L; I2C_delay(); SCL_H; I2C_delay(); SDA_H; I2C_delay(); }
/************************************** * I2Cstop:keep SCL high, SDA low to high * ________________ * SCL: * ______ * SDA: ________/ * 函数返回时:SDA,SCL均为高电平 ***************************************/ void I2C_Stop(void) { SCL_L; I2C_delay(); SDA_L; I2C_delay(); SCL_H; I2C_delay(); SDA_H; }
void I2C_ACK() { SCL_L; I2C_delay(); SDA_L; I2C_delay(); SCL_H; I2C_delay(); SCL_L; I2C_delay(); }
void I2C_STOP() { SCL_L; I2C_delay(); SDA_L; I2C_delay(); SCL_H; I2C_delay(); SDA_H; I2C_delay(); }
unsigned char i2c_read_bit(void) { unsigned char bit; read_SDA(); I2C_delay(); while (read_SCL() == 0); // Clock stretching bit = read_SDA(); I2C_delay(); clear_SCL(); I2C_delay(); return bit; }
/******************************************************************************* * Function Name : I2C_NoAck * Description : Master Send No Acknowledge Single * Input : None * Output : None * Return : None ****************************************************************************** */ void I2C_NoAck(void) { SCL_L; I2C_delay(); SDA_H; I2C_delay(); SCL_H; I2C_delay(); SCL_L; I2C_delay(); }
/* *========================================================= * 函数功能:IIC总线初始化信号 * 参数:无 * 函数返回值:无 * SDA --- * |________ * SCL ---------- * |____ *========================================================= */ void I2C_Start(void) { SCL_L; I2C_delay(); SDA_H; I2C_delay(); SCL_H; I2C_delay(); SDA_L; I2C_delay(); }
/******************************************************************************* * Function Name : I2C_Ack * Description : None * Input : None * Output : None * Return : None * Attention : None *******************************************************************************/ static void I2C_Ack(void) { SCL_L; I2C_delay(); SDA_L; I2C_delay(); SCL_H; I2C_delay(); SCL_L; I2C_delay(); }
//产生IIC起始信号 static bool IIC_Start(void) { SDA_OUT(); //sda线输出 IIC_SDA(1); IIC_SCL(1); I2C_delay(); IIC_SDA(0);//START:when CLK is high,DATA change form high to low I2C_delay(); IIC_SCL(0);//钳住I2C总线,准备发送或接收数据 return TRUE ; }
void i2c_stop(void) { // set SDA to 0 clear_SDA(); I2C_delay(); while (read_SCL() == 0); // Clock stretching I2C_delay(); if (read_SDA() == 0) { arbitration_lost(); } I2C_delay(); started = 0; }
/******************************************************************************* * Function Name : I2C_Start * Description : None * Input : None * Output : None * Return : None * Attention : None *******************************************************************************/ static int I2C_Start(void) { SDA_H; I2C_delay(); SCL_H; I2C_delay(); SDA_L; I2C_delay(); SCL_L; I2C_delay(); return ENABLE; }
////////////////////////////////////////////////////////////////////// // Stop command // // SDA 0-0-1 // SCL 0-1-1 // void I2C_Stop(void) { I2C_SCL_0; // Force to zero as can be sent at any time. I2C_SDA_0; // Clock 1st so do not make a command. I2C_delay(); I2C_SCL_1; I2C_delay(); I2C_SDA_1; I2C_delay(); }
////////////////////////////////////////////////////////////////////// // Start command // // SDA 1-0-0 // SCL 1-1-0 // // Asumptions : coming from bus free state (d=1,ck=1) void I2C_Start(void) { I2C_SDA_1; I2C_SCL_1; I2C_delay(); I2C_SDA_0; I2C_delay(); I2C_SCL_0; I2C_delay(); }
/******************************************************************************* * Function Name : I2C_Start * Description : Master Start Simulation IIC Communication * Input : None * Output : None * Return : Wheather Start ****************************************************************************** */ uint8_t I2C_Start(void) { SDA_H; SCL_H; I2C_delay(); if(!SDA_read)return 0; //SDA线为低电平则总线忙,退出 SDA_L; I2C_delay(); if(SDA_read) return 0; //SDA线为高电平则总线出错,退出 SDA_L; I2C_delay(); return 1; }
void I2C_NAck(void) { SCL_L; //1 首先拉低SCL,开始准备数据 SDA_H; //2 在SCL为低电平是准备数据(ACK=1) I2C_delay(); //3 保持一下 SCL_H; //4 SCL拉高,进行采样 I2C_delay(); //5 保持SCL=1的时间->Note:确保采样时间 SCL_L; //复位SCL->L完成一个clock //结束时,SCL=L SDA=NACK }
/******************************************************************************* * Function Name : I2C_Start * Description : Master Start Simulation IIC Communication * Input : None * Output : None * Return : Wheather Start ****************************************************************************** */ uint16_t I2C_Start(void) { SDA_H; SCL_H; I2C_delay(); if(!SDA_read)return FALSE; //SDA线为低电平则总线忙,退出 SDA_L; I2C_delay(); if(SDA_read) return FALSE; //SDA线为高电平则总线出错,退出 SDA_L; I2C_delay(); return TRUE; }
/************************************** * I2Cstart: keep SCL high, SDA high to low * ___________ * SCL: \_____ * ______ * SDA: \__________ * 函数返回时:SDA,SCL均为低电平 ***************************************/ uint8_t I2C_Start(void) { SDA_H; SCL_H; I2C_delay(); if(!SDA_READ)return FALSE; SDA_L; I2C_delay(); if(SDA_READ)return FALSE; SCL_L; return TRUE; }
void I2C_Release(void) { uint8_t i =9; while(i--) { SCL_H; I2C_delay(); SCL_L; I2C_delay(); } I2C_Stop(); }
// Read a bit from I2C bus bool i2c_read_bit(void) { bool bit; // Let the slave drive data read_SDA(); I2C_delay(); while (read_SCL() == 0) { // Clock stretching // You should add timeout to this loop } // SCL is high, now data is valid bit = read_SDA(); I2C_delay(); clear_SCL(); return bit; }
//IIC发送一个字节 //返回从机有无应答 //1,有应答 //0,无应答 static void IIC_Send_Byte(u8 txd) { u8 t; SDA_OUT(); for(t=0;t<8;t++) { IIC_SDA((txd&0x80)>>7); txd<<=1; IIC_SCL(1); I2C_delay(); IIC_SCL(0); I2C_delay(); } }