/*---------------------------------------------------------------- 字节数据传送函数 函数原型: void SendByte(unsigned char c); 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对 此状态位进行操作.(不应答或非应答都使ack=0 假) 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。 ------------------------------------------------------------------*/ void I2C_SendByte(unsigned char c) { unsigned char BitCnt; for(BitCnt = 0; BitCnt < 8; BitCnt++) //要传送的数据长度为8位 { if(( c << BitCnt) & 0x80) //判断发送位 { SDA(1); } else { SDA(0); } _delay_us(10); SCL(1); //置时钟线为高,通知被控器开始接收数据位 _delay_us(15); //保证时钟高电平周期大于4μ SCL(0); } //SDA(1); //8位发送完后释放数据线,准备接收应答位 DDRF &= ~(1 << PF7); // 变为输入 PORTF |= (1 << PF7); _delay_us(30); // without this wait read unstable value. SCL(1); _delay_us(15); if(Read_SDA()) ack = 0; else ack = 1; //判断是否接收到应答信号 SCL(0); SDA(0); // 变为输出 _delay_us(10); }
/*------------------------------------------------ 结束总线 ------------------------------------------------*/ void I2C_Stop(void) { SDA(0); //发送结束条件的数据信号 _delay_us(10); //发送结束条件的时钟信号 SCL(1); //结束条件建立时间大于4μ _delay_us(10); SDA(1); //发送I2C总线结束信号 _delay_us(10); }
/*------------------------------------------------ 启动总线 ------------------------------------------------*/ void I2C_Start(void) { SDA(1); //发送起始条件的数据信号 _delay_us(5); SCL(1); _delay_us(10); //起始条件建立时间大于4.7us,延时 SDA(0); //发送起始信号 _delay_us(10); //起始条件锁定时间大于4μ SCL(0); //钳住I2C总线,准备发送或接收数据 _delay_us(10); }
/*---------------------------------------------------------------- 字节数据传送函数 函数原型: unsigned char I2C_RcvByte(); 功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号), 发完后请用应答函数。 ------------------------------------------------------------------*/ unsigned char I2C_RcvByte(void) { unsigned char retc; unsigned char BitCnt; retc=0; SDA(1); //置数据线为输入方式 for(BitCnt = 0; BitCnt < 8; BitCnt++) { _Nop(); SCL(0); //置时钟线为低,准备接收数据位 _Nop(); _Nop(); //时钟低电平周期大于4.7us _Nop(); _Nop(); _Nop(); SCL(1); //置时钟线为高使数据线上数据有效 _Nop(); _Nop(); retc = retc << 1; if(Read_SDA()) retc = retc + 1; //读数据位,接收的数据位放入retc中 _Nop(); _Nop(); } SCL(0); _Nop(); _Nop(); return(retc); }
static void i2c_soft_stop(void) { SCL1(); waitSomeTimeInUs(2); SDA(1); waitSomeTimeInUs(1); }
static uint8_t i2c_soft_receive_bit(void) { // SDA = 1 // SCL = 1 // wait SCL low // bit = SDA // SCL = 0 uint8_t bit; SDA(1); waitSomeTimeInUs(1); SCL1(); waitSomeTimeInUs(1); while( GET_SCL() == 0); bit = GET_SDA(); SCL0(); SDA_OUTPUT(); waitSomeTimeInUs(1); return bit; }
static void i2c_soft_send_bit(uint8_t bit) { // set bit on SDA // NOP // SCL = 1 // wait SCL low // then SCL = 0 SDA((bit&0x1)); waitSomeTimeInUs(1); SCL1(); waitSomeTimeInUs(2); SCL0(); waitSomeTimeInUs(1); }
/*---------------------------------------------------------------- 非应答子函数 原型: void NoAck_I2c(void); ----------------------------------------------------------------*/ void NoAck_I2c(void) { SDA(1); _Nop(); _Nop(); _Nop(); SCL(1); _Nop(); _Nop(); //时钟低电平周期大于4μ _Nop(); _Nop(); _Nop(); SCL(0); //清时钟线,钳住I2C总线以便继续接收 _Nop(); _Nop(); }
static void i2c_soft_start(void) { SDA(0); SCL0(); waitSomeTimeInUs(1); }
unsigned char read_SDA(void) // Set SDA as input and return current level of line, 0 or 1 { SDA_IN(); return !!SDA(); }