Как прочитать данные результата с датчика освещенности, используя прерывания

Я использую Arduino Mega 2560 и датчик освещенности BH1750FVI. чтобы показать результат я использую миником, работаю на Ubuntu 16.04 LTS

Я пишу код, и он работает, и отправляю мне результаты считывания с датчика освещенности, я могу прочитать информацию только один раз. Я не понимаю, как заставить это работать через прерывания (TWI_vect) и отображать результаты каждый раз, используя мой 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);
  }
}

Так что этот код работает, и я получаю данные от датчика и все в порядке. Но я хочу использовать его с прерываниями (TWI_vect) и постоянно получать данные от датчика, как в while(). Я читаю много информации, но не понимаю, как она должна выглядеть. Можете ли вы показать мне правильный путь, используя мой код с прерываниями (TWI_vect), небольшой пример. Спасибо за помощь!

1 ответ

Решение

Чтобы использовать управляемый прерываниями интерфейс Two-Wirte (I²C; TWI), вам нужно реализовать какой-то конечный автомат внутри TWI ISR.

Замечания по применению Atmel AVR135 дают небольшое представление о том, как это можно сделать. Вам нужно будет иметь готовые буферы и абстрактные транзакции в какую-то структуру. Например, вы можете иметь

struct i2c_transfer {
    uint8_t        i2c_sla; /* slave address */
    const uint8_t *txbuf;
    size_t         txbytes;
    uint8_t       *rxbuf;
    size_t         rxbytes;
}

Что вы установили, затем пусть функция начинает передачу I2C и проверяет, что вы сделали, проверяя, txbytes == 0 && rxbytes == 0 или произошла ошибка. Ваш ISR должен затем проверить свое состояние и действовать соответствующим образом в зависимости от количества байтов, которые он должен записывать и читать.

Другие вопросы по тегам