I'm using Arduino mega 2560 and light sensor BH1750FVI. to show result i'm using minicom, work on Ubuntu 16.04 LTS
I write code and it's work and send me data result reading from light sensor, i can read info only once. I don't understand how i make it work through interrupts (TWI_vect) and display the results every time using my uart.
#include "my_header.h"
#define I2C_STATUS_MASK 0xF8
#define START_COND_TRANSMITTED 0x08
#define REPEATED_START_COND_TRANSMITTED 0x10
#define SLA_W_TRANSMITTED_ACK_RECEIVED 0x18
#define DATA_TRANSMITTED_ACK_RECEIVED 0x28
#define SLA_R_TRANSMITTED_ACK_RECEIVED 0x40
#define DATA_RECEIVED_ACK_RETURNED 0x50
#define DATA_RECEIVED_NACK_RETURNED 0x58
volatile int light_intensity = 0; // var for read data from sensor
ISR(USART0_UDRE_vect) {
if (!bufferIsEmpty(&buffer)) //if we have something to read do it
UDR0 = popFromBuff(&buffer);
else
UCSR0B &= ~_BV(UDRIE0); //disallow interrupts
}
int main(void) {
cli();
init_port(); //initialize my port
init_buffer(&buffer, BUFF_SIZE); //init ring_buffer for uart
init_uart();
TWI_init();
sei();
TWI_start(); //send start
TWI_send_SLA(WRITE); //send SLA+W to light sensor
TWI_sendData(0b00010000); //opecode for Measurement
TWI_stop(); //stop
TWI_start(); //send start
TWI_send_SLA(READ); // send SLA+R to sensor
TWI_readData(); // read data from it light_intensity = TWDR
TWI_stop(); // stop
u_printnumbers(light_intensity); /*my func that send data to ring_buffer and later
*using interrupts send it form buffer to UDR
*/
u_print("\n");
while (1) {
if (!bufferIsEmpty(&buffer)) /*if buffer is not empty allow interrupts for uart*/
UCSR0B |= _BV(UDRIE0);
}
}
So this code work and i receive data from sensor and all fine. But i want using it with interrupts (TWI_vect) and receive data all the time from sensor like in while(). i read a lot of info but don't understand how it should look. Can you show me the right way using my code with interrupts (TWI_vect) some little example. Thx for help!
To use the Two-Wirte interface (I²C; TWI) interrupt-driven, you will have to implement some sort of state machine inside the TWI ISR.
Atmel Application Note AVR135 give a slight idea how this can be done. You will have to have buffers ready and abstract transactions into a struct of some sort. For example, you can have a
struct i2c_transfer {
uint8_t i2c_sla; /* slave address */
const uint8_t *txbuf;
size_t txbytes;
uint8_t *rxbuf;
size_t rxbytes;
}
That you set up, then have a function start transmitting I2C and check if you're done via checking if txbytes == 0 && rxbytes == 0
or an error occurred. Your ISR would then need to check its state and act appropriately depending on the number of bytes it's supposed to write and read.