//---------------------------------------------------------------------------------- char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode) //---------------------------------------------------------------------------------- // makes a measurement (humidity/temperature) with checksum { unsigned char error=0; unsigned int i; s_transstart(); //transmission start //发送测量命令 switch(mode){ //send command to sensor case TEMP : error+=s_write_byte(MEASURE_TEMP); break; case HUMI : error+=s_write_byte(MEASURE_HUMI); break; default : break; } //读数 for (i=0;i<60000;i++) if(SDA_READ()==0) break; //wait until sensor has finished the measurement if(SDA_READ()) error+=1; // or timeout (~2 sec.) is reached *(p_value+1) =s_read_byte(ACK); //read the first byte (MSB) // printf("p_value is %x",*p_value); *(p_value)=s_read_byte(ACK); // printf("p_value+1 is %x",*(p_value+1)); //read the second byte (LSB) *p_checksum =s_read_byte(noACK); //read checksum return error; // } }
uint8_t ICACHE_FLASH_ATTR twi_readFrom(uint8_t address, uint8_t *buf, unsigned int len, uint8_t sendStop) { unsigned int i; if (!twi_write_start()) { serial_print("I2C: bus busy\r\n"); return 4; } if (!twi_write_byte(((address << 1) | 1) & 0xFF)) { if (sendStop) twi_write_stop(); serial_print("I2C: received NACK on transmit of address\r\n"); return 2; } for (i = 0; i < (len - 1); i++) buf[i] = twi_read_byte(false); buf[len - 1] = twi_read_byte(true); if (sendStop) twi_write_stop(); i = 0; while (SDA_READ() == 0 && (i++) < 10) { SCL_LOW(); twi_delay(twi_dcount); SCL_HIGH(); twi_delay(twi_dcount); } return 0; }
uint8_t ICACHE_FLASH_ATTR twi_writeTo(uint8_t address, uint8_t *buf, unsigned int len, uint8_t sendStop) { unsigned int i; if (!twi_write_start()) { serial_print("I2C: bus busy\r\n"); return 4; } if (!twi_write_byte(((address << 1) | 0) & 0xFF)) { if (sendStop) twi_write_stop(); serial_print("I2C: received NACK on transmit of address\r\n"); return 2; } for (i = 0; i < len; i++) { if (!twi_write_byte(buf[i])) { if (sendStop) twi_write_stop(); serial_print("I2C: received NACK on transmit of data\r\n"); return 3; } } if (sendStop) twi_write_stop(); i = 0; while (SDA_READ() == 0 && (i++) < 10) { SCL_LOW(); twi_delay(twi_dcount); SCL_HIGH(); twi_delay(twi_dcount); } return 0; }
uint8_t twi_status() { if (SCL_READ() == 0) return I2C_SCL_HELD_LOW; // SCL held low by another device, no procedure available to recover int clockCount = 20; while (SDA_READ() == 0 && clockCount-- > 0) { // if SDA low, read the bits slaves have to sent to a max twi_read_bit(); if (SCL_READ() == 0) { return I2C_SCL_HELD_LOW_AFTER_READ; // I2C bus error. SCL held low beyond slave clock stretch time } } if (SDA_READ() == 0) return I2C_SDA_HELD_LOW; // I2C bus error. SDA line held low by slave/another_master after n bits. if (!twi_write_start()) return I2C_SDA_HELD_LOW_AFTER_INIT; // line busy. SDA again held low by another device. 2nd master? return I2C_OK; }
static bool twi_read_bit(void) { uint32_t i = 0; SCL_LOW(); SDA_HIGH(); twi_delay(twi_dcount+2); SCL_HIGH(); while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);// Clock stretching bool bit = SDA_READ(); twi_delay(twi_dcount); return bit; }
static bool twi_write_start(void) { SCL_HIGH(); SDA_HIGH(); if (SDA_READ() == 0) { return false; } twi_delay(twi_dcount); SDA_LOW(); twi_delay(twi_dcount); return true; }
static bool ICACHE_FLASH_ATTR twi_read_bit() { unsigned int i = 0; SCL_LOW(); SDA_HIGH(); twi_delay(twi_dcount + 2); SCL_HIGH(); while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit); // Clock stretching bool bit = SDA_READ(); twi_delay(twi_dcount); return bit; }
static bool ICACHE_FLASH_ATTR twi_write_start(void) { SCL_HIGH(); SDA_HIGH(); if (SDA_READ() == 0) { serial_printf("twi write start sda read false\r\n"); return false; } twi_delay(twi_dcount); SDA_LOW(); twi_delay(twi_dcount); return true; }
unsigned char twi_readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop){ unsigned int i; if(!twi_write_start()) return 4;//line busy if(!twi_write_byte(((address << 1) | 1) & 0xFF)) { if (sendStop) twi_write_stop(); return 2;//received NACK on transmit of address } for(i=0; i<(len-1); i++) buf[i] = twi_read_byte(false); buf[len-1] = twi_read_byte(true); if(sendStop) twi_write_stop(); i = 0; while(SDA_READ() == 0 && (i++) < 10){ SCL_LOW(); twi_delay(twi_dcount); SCL_HIGH(); unsigned int t=0; while(SCL_READ()==0 && (t++)<twi_clockStretchLimit); // twi_clockStretchLimit twi_delay(twi_dcount); } return 0; }
//---------------------------------------------------------------------------------- char s_read_byte(unsigned char ack) //---------------------------------------------------------------------------------- // reads a byte form the Sensibus and gives an acknowledge in case of "ack=1" { unsigned char i,val=0; SDA_OUT(1); //release DATA-line for (i=0x80;i>0;i=i>>1) //shift bit for masking { SCL_OUT(1); //clk for SENSI-BUS if (SDA_READ()) val=(val | i); //read bit SCL_OUT(0); } SDA_OUT(!ack); //in case of "ack==1" pull down DATA-Line delay_us(2); //observe setup time SCL_OUT(1); //clk #9 for ack delay_us(6); //pulswith approx. 5 us SCL_OUT(0); delay_us(2); //observe hold time SDA_OUT(1); //release DATA-line return val; }
bool i2c_write(alt_u32 clk_base, alt_u32 data_base, alt_u8 Data){ // return true if device response ack alt_u8 Mask = 0x80; bool bAck; int i; // assume, SCL = 0 SDA_DIR_OUT(data_base); // data write mode for(i=0;i<8;i++){ SCL_LOW(clk_base); // new, make sure data change at clk low // output data on bus if (Data & Mask){ // there is a delay in this command SDA_HIGH(data_base); }else{ SDA_LOW(data_base); } Mask >>= 1; // there is a delay in this command // clock high SCL_HIGH(clk_base); SCL_DELAY; SCL_LOW(clk_base); SCL_DELAY; } //===== get ack SDA_DIR_IN(data_base); // data read mode //SCL_DELAY; // clock high SCL_HIGH(clk_base); // clock high SCL_DELAY; // clock high delay bAck = SDA_READ(data_base)?FALSE:TRUE; // get ack //SCL_DELAY; //SDA_DIR_OUT; SCL_LOW(clk_base); // clock low SCL_DELAY; // clock low delay return bAck; }
//---------------------------------------------------------------------------------- char s_write_byte(unsigned char value) //---------------------------------------------------------------------------------- // writes a byte on the Sensibus and checks the acknowledge { unsigned char i,error=0; for (i=0x80;i>0;i/=2) //shift bit for masking { if (i & value) SDA_OUT(1); //masking value with i , write to SENSI-BUS else SDA_OUT(0); delay_us(2); //observe setup time SCL_OUT(1); //clk for SENSI-BUS delay_us(6); //pulswith approx. 5 us SCL_OUT(0); delay_us(2); //observe hold time } SDA_OUT(1); //release DATA-line delay_us(2); //observe setup time SCL_OUT(1); //clk #9 for ack error=SDA_READ(); //check ack (DATA will be pulled down by SHT11) SCL_OUT(0); return error; //error=1 in case of no acknowledge }
void i2c_read(alt_u32 clk_base, alt_u32 data_base, alt_u8 *pData, bool bAck){ // return true if device response ack alt_u8 Data=0; int i; // assume SCL = low SDA_DIR_IN(data_base); // set data read mode SCL_LOW(clk_base); // clock low SCL_DELAY; // clock low delay for(i=0;i<8;i++){ Data <<= 1; SCL_HIGH(clk_base); // clock high SCL_DELAY; if (SDA_READ(data_base)) // read data Data |= 0x01; SCL_LOW(clk_base); // clock log SCL_DELAY; } // send ACK SCL_LOW(clk_base); // new, make sure data change at clk low SDA_DIR_OUT(data_base); // set data write mode if (bAck) SDA_LOW(data_base); else SDA_HIGH(data_base); SCL_HIGH(clk_base); // clock high SCL_DELAY; // clock high delay SCL_LOW(clk_base); // clock low SCL_DELAY; // clock low delay SDA_LOW(data_base); // data low SCL_DELAY; // data low delay // SDA_DIR_IN; // set data read mode *pData = Data; }
unsigned char twi_writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop){ unsigned int i; if(!twi_write_start()) return 4;//line busy if(!twi_write_byte(((address << 1) | 0) & 0xFF)) { if (sendStop) twi_write_stop(); return 2; //received NACK on transmit of address } for(i=0; i<len; i++) { if(!twi_write_byte(buf[i])) { if (sendStop) twi_write_stop(); return 3;//received NACK on transmit of data } } if(sendStop) twi_write_stop(); i = 0; while(SDA_READ() == 0 && (i++) < 10){ SCL_LOW(); twi_delay(twi_dcount); SCL_HIGH(); unsigned int t=0; while(SCL_READ()==0 && (t++)<twi_clockStretchLimit); // twi_clockStretchLimit twi_delay(twi_dcount); } return 0; }
void ICACHE_RAM_ATTR onSdaChange(void) { static uint8_t sda; static uint8_t scl; sda = SDA_READ(); scl = SCL_READ(); switch (twip_state) { case TWIP_IDLE: if (!scl) { // DATA - ignore } else if (sda) { // STOP - ignore } else { // START bitCount = 8; twip_state = TWIP_START; ets_timer_arm_new(&timer, twi_timeout_ms, false, true); // Once, ms } break; case TWIP_START: case TWIP_REP_START: case TWIP_SEND_ACK: case TWIP_WAIT_ACK: case TWIP_SLA_R: case TWIP_REC_ACK: case TWIP_READ_ACK: case TWIP_RWAIT_ACK: case TWIP_WRITE: if (!scl) { // DATA - ignore } else { // START or STOP SDA_HIGH(); // Should not be necessary twip_status = TW_BUS_ERROR; twi_onTwipEvent(twip_status); twip_mode = TWIPM_WAIT; twip_state = TWIP_BUS_ERR; } break; case TWIP_WAIT_STOP: case TWIP_BUS_ERR: if (!scl) { // DATA - ignore } else { if (sda) { // STOP SCL_LOW(); // clock stretching ets_timer_disarm(&timer); twip_state = TWIP_IDLE; twip_mode = TWIPM_IDLE; SCL_HIGH(); } else { // START if (twip_state == TWIP_BUS_ERR) { // ignore } else { bitCount = 8; twip_state = TWIP_REP_START; ets_timer_arm_new(&timer, twi_timeout_ms, false, true); // Once, ms } } } break; case TWIP_SLA_W: case TWIP_READ: if (!scl) { // DATA - ignore } else { // START or STOP if (bitCount != 7) { // inside byte transfer - error twip_status = TW_BUS_ERROR; twi_onTwipEvent(twip_status); twip_mode = TWIPM_WAIT; twip_state = TWIP_BUS_ERR; } else { // during first bit in byte transfer - ok SCL_LOW(); // clock stretching twip_status = TW_SR_STOP; twi_onTwipEvent(twip_status); if (sda) { // STOP ets_timer_disarm(&timer); twip_state = TWIP_IDLE; twip_mode = TWIPM_IDLE; } else { // START bitCount = 8; ets_timer_arm_new(&timer, twi_timeout_ms, false, true); // Once, ms twip_state = TWIP_REP_START; twip_mode = TWIPM_IDLE; } } } break; default: break; } }
void ICACHE_RAM_ATTR onSclChange(void) { static uint8_t sda; static uint8_t scl; sda = SDA_READ(); scl = SCL_READ(); twip_status = 0xF8; // reset TWI status switch (twip_state) { case TWIP_IDLE: case TWIP_WAIT_STOP: case TWIP_BUS_ERR: // ignore break; case TWIP_START: case TWIP_REP_START: case TWIP_SLA_W: case TWIP_READ: if (!scl) { // ignore } else { bitCount--; twi_data <<= 1; twi_data |= sda; if (bitCount != 0) { // continue } else { twip_state = TWIP_SEND_ACK; } } break; case TWIP_SEND_ACK: if (scl) { // ignore } else { if (twip_mode == TWIPM_IDLE) { if ((twi_data & 0xFE) != twi_addr) { // ignore } else { SDA_LOW(); } } else { if (!twi_ack) { // ignore } else { SDA_LOW(); } } twip_state = TWIP_WAIT_ACK; } break; case TWIP_WAIT_ACK: if (scl) { // ignore } else { if (twip_mode == TWIPM_IDLE) { if ((twi_data & 0xFE) != twi_addr) { SDA_HIGH(); twip_state = TWIP_WAIT_STOP; } else { SCL_LOW(); // clock stretching SDA_HIGH(); twip_mode = TWIPM_ADDRESSED; if (!(twi_data & 0x01)) { twip_status = TW_SR_SLA_ACK; twi_onTwipEvent(twip_status); bitCount = 8; twip_state = TWIP_SLA_W; } else { twip_status = TW_ST_SLA_ACK; twi_onTwipEvent(twip_status); twip_state = TWIP_SLA_R; } } } else { SCL_LOW(); // clock stretching SDA_HIGH(); if (!twi_ack) { twip_status = TW_SR_DATA_NACK; twi_onTwipEvent(twip_status); twip_mode = TWIPM_WAIT; twip_state = TWIP_WAIT_STOP; } else { twip_status = TW_SR_DATA_ACK; twi_onTwipEvent(twip_status); bitCount = 8; twip_state = TWIP_READ; } } } break; case TWIP_SLA_R: case TWIP_WRITE: if (scl) { // ignore } else { bitCount--; (twi_data & 0x80) ? SDA_HIGH() : SDA_LOW(); twi_data <<= 1; if (bitCount != 0) { // continue } else { twip_state = TWIP_REC_ACK; } } break; case TWIP_REC_ACK: if (scl) { // ignore } else { SDA_HIGH(); twip_state = TWIP_READ_ACK; } break; case TWIP_READ_ACK: if (!scl) { // ignore } else { twi_ack_rec = !sda; twip_state = TWIP_RWAIT_ACK; } break; case TWIP_RWAIT_ACK: if (scl) { // ignore } else { SCL_LOW(); // clock stretching if (twi_ack && twi_ack_rec) { twip_status = TW_ST_DATA_ACK; twi_onTwipEvent(twip_status); twip_state = TWIP_WRITE; } else { // we have no more data to send and/or the master doesn't want anymore twip_status = twi_ack_rec ? TW_ST_LAST_DATA : TW_ST_DATA_NACK; twi_onTwipEvent(twip_status); twip_mode = TWIPM_WAIT; twip_state = TWIP_WAIT_STOP; } } break; default: break; } }