/* Light_Sensor_ISL29020.c * Lichtmessung (alle 200ms) und Ausgabe der Lichtstärke in Lux in der Variablen "lux_value" * Ein möglicher Übertragungsfehler (ERROR) wird durch eine LED an PB1 angezeigt * CPU: ATmega88, FCPU = 8MHz * I²C CLK Frequency = 62,5kHz, --> CLK Frequency = FCPU/(16 + 2*(TWBR)*Prescaler Value) */ #include <avr/io.h> #include <util/delay.h> #define START 0x08 // A START condition has been transmitted #define R_START 0x10 // A REPEATED START condition has been transmitted #define SLA_W 0x88 // Slave Address & Write 1000 1000 #define SLA_R 0x89 // Slave Address & Read 1000 1001 #define MT_SLA_ACK 0x18 // Master Transmit SLA + W has been transmitted & ACK has been received #define MT_DATA_ACK 0x28 // Master Transmit Data byte has been transmitted & ACK has been received #define MR_SLA_ACK 0x40 // Master Receive SLA + R has been transmitted & ACK has been received #define MR_SLA_NACK 0x48 // Master Receive SLA + R has been transmitted & ACK has been received #define MR_DATA_ACK 0x50 // Master Receive Data byte has been transmitted & ACK has been returned #define MR_DATA_NACK 0x58 // Master Receive Data byte has been transmitted & NACK has been returned #define BIT_RATE 56 // Set value for the bit rate register TWBR void ERROR(void); // Prototyping of function "ERROR" /*** Function to send a START Condition ***/ void TWI_START(void) { // Send a START condition TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // Wait for TWINT Flag set. This indicates that the START condition has been transmitted while (!(TWCR & (1<<TWINT))); // Check value of TWI statusregister. Mask prescaler bits. If status different from START go to ERROR if ((TWSR & 0xF8) != START) ERROR(); } /*** Function to send the Slave Address with ACK in Master Transmit Mode ***/ void TWI_MT_SLA_ACK(void) { // Load Slave Address + Write into TWDR Register TWDR = SLA_W; // Clear TWINT bit in TWCR to start transmission TWCR = (1<<TWINT) | (1<<TWEN); // Wait for TWINT Flag set. This indicates that the SLA+W has been transmitted, and ACK/NACK has been received. while (!(TWCR & (1<<TWINT))); // Check value of TWI status register. Mask prescaler bits. If status different from MT_SLA_ACK go to ERROR if ((TWSR & 0xF8) != MT_SLA_ACK) ERROR(); } /*** Function to send 8Bit of data with ACK in Master Transmit Mode **/ void TWI_MT_DATA_ACK(uint8_t data) { // Load DATA into TWDR register TWDR = data; // Clear TWINT bit in TWCR to start transmission TWCR = (1<<TWINT) | (1<<TWEN); // Wait for TWINT flag set. This indicates that the DATA has been transmitted, and ACK/NACK has been received. while (!(TWCR & (1<<TWINT))); // Check value of TWI status register. Mask prescaler bits. If status different from MT_DATA_ACK go to ERROR if ((TWSR & 0xF8) != MT_DATA_ACK) ERROR(); } /*** Function to send a REPEATED START condition **/ void TWI_R_START(void) { // Send a START condition TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // Wait for TWINT Flag set. This indicates that the START condition has been transmitted while (!(TWCR & (1<<TWINT))); // Check value of TWI statusregister. Mask prescaler bits. If status different from R_START go to ER-ROR if ((TWSR & 0xF8) != R_START) ERROR(); } /*** Function to send the Slave Address in Master Receive Mode with Acknowledge **/ void TWI_MR_SLA_ACK(void) { // Load Slave Address + Read into TWDR Register TWDR = SLA_R; // Clear TWINT bit in TWCR to start transmission TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); // Wait for TWINT Flag set. This indicates that the SLA+W has been transmitted, and ACK/NACK has been received. while (!(TWCR & (1<<TWINT))); // Check value of TWI status register. Mask prescaler bits. If status different from MR_SLA_ACK go to ERROR if ((TWSR & 0xF8) != MR_SLA_ACK) ERROR(); } /*** Function to send the Slave Address in Master Receive Mode without Acknowledge **/ void TWI_MR_SLA_NACK(void) { // Load Slave Address + Read into TWDR Register TWDR = SLA_R; // Clear TWINT bit in TWCR to start transmission TWCR = (1<<TWINT) | (1<<TWEN); // Wait for TWINT Flag set. This indicates that the SLA+W has been transmitted, and ACK/NACK has been received. while (!(TWCR & (1<<TWINT))); // Check value of TWI status register. Mask prescaler bits. If status different from MR_SLA_NACK go to ERROR if ((TWSR & 0xF8) != MR_SLA_NACK) ERROR(); } /*** Function to read one Databyte in Master Receive Mode and send NACK ***/ uint8_t TWI_READ_DATABYTE_NACK(void) { // Clear TWINT bit in TWCR to start transmission with NACK TWCR = (1<<TWINT) | (1<<TWEN); // Wait for TWINT flag set. This indicates that the DATA has been received while (!(TWCR & (1<<TWINT))); // Check value of TWI status register. Mask prescaler bits. If status different from MR_SLA_NACK go to ERROR if ((TWSR & 0xF8) != MR_DATA_NACK) ERROR(); return TWDR; // Return the value of data register } /*** Function to read one Databyte in Master Receive Mode and send ACK ***/ uint8_t TWI_READ_DATABYTE_ACK(void) { // Clear TWINT bit in TWCR to start transmission with ACK TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); // Wait for TWINT flag set. This indicates that the DATA has been received while (!(TWCR & (1<<TWINT))); // Check value of TWI status register. Mask prescaler bits. If status different from MR_SLA_ACK go to ERROR if ((TWSR & 0xF8) != MR_DATA_ACK) ERROR(); return TWDR; // Return the value of data register } /*** function to send a STOP condition ***/ void TWI_STOP(void) { TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); // Transmit STOP condition } /*** function to show a bus error ***/ void ERROR(void) { PORTB |= (1<<PB1); // ERROR LED ON } uint8_t LSByte, MSByte; uint16_t data_16bit, lux_value, high_byte, low_byte; int main(void) { DDRD = 0xFF; // PORTD = output DDRC = 0x3F; // PC0 ... PC5 = output DDRB = 0x03; // PB0 and PB1 = output TWBR = BIT_RATE; // Set the TWI clock-frequency in bit rate register TWI_START(); // Send START condition TWI_MT_SLA_ACK(); // Master Transmit Slave Address with Acknowledge TWI_MT_DATA_ACK(0x00); // Transmit 0x00 for Register Command with Acknowledge TWI_MT_DATA_ACK(0xC3); // Transmit 0xC3 (1100 0011) EN, Mode=1, Range4 TWI_STOP(); // Send STOP condition _delay_ms(10); // Delaytime between STOP and next START contition while(1) { TWI_START(); // Send START condition TWI_MT_SLA_ACK(); // Master Transmit Slave Address with ACK TWI_MT_DATA_ACK(0x01); // Transmit 0x01 to start with Register 0x01 with ACK TWI_R_START(); // Send REPEATED START condition TWI_MR_SLA_ACK(); // Send the Slave Address in Master Receive Mode with ACK /* Read 2 Databytes in Burst Read Sequence */ // Read one Databyte with ACK (tells the receiver more data will be received) LSByte = TWI_READ_DATABYTE_ACK(); // Read one Databyte with NACK (tells the receiver no further data will be received) MSByte = TWI_READ_DATABYTE_NACK(); TWI_STOP(); // Send STOP condition low_byte = LSByte; // Store LSByte in low_byte high_byte = MSByte << 8; // Shift MSByte 8 digits to left and store in high_byte lux_value = low_byte + high_byte; // Store 16bit-result in lux_value _delay_ms(200); // wait 200ms for new readout } }