#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include <util/delay_basic.h>
void inicializar_puertos(void);
void reset(void);
void i2c_MT(unsigned char direccion, unsigned char dato);
unsigned char i2c_MR(unsigned char direccion);
void i2c_error(void);
volatile unsigned char r_estado;
volatile unsigned char comunicaciones=0;
int main(void)
{
inicializar_puertos();
reset();
while(9)
{
if(comunicaciones != 0)
{
comunicaciones=0;
r_estado=i2c_MR(0xE2);
_delay_us(20);
i2c_MT(0xE2, r_estado);
}
if((r_estado&0x01)!=0)
PORTD |= (1<<PORTD5);
else
PORTD &= ~(1<<PORTD5);
if((r_estado&0x02)!=0)
PORTD |= (1<<PORTD4);
else
PORTD &= ~(1<<PORTD4);
if((r_estado&0x04)!=0)
PORTD |= (1<<PORTD3);
else
PORTD &= ~(1<<PORTD3);
}
}
void reset(void)
{
cli();
PORTD |= ((1<<PORTD3)|(1<<PORTD4)|(1<<PORTD5));
_delay_ms(1000);
PORTD &= ~((1<<PORTD3)|(1<<PORTD4)|(1<<PORTD5));
_delay_ms(1000);
PORTD |= ((1<<PORTD3)|(1<<PORTD4)|(1<<PORTD5));
_delay_ms(1000);
PORTD &= ~((1<<PORTD3)|(1<<PORTD4)|(1<<PORTD5));
_delay_ms(1000);
PORTD |= ((1<<PORTD3)|(1<<PORTD4)|(1<<PORTD5));
_delay_ms(1000);
PORTD &= ~((1<<PORTD3)|(1<<PORTD4)|(1<<PORTD5));
_delay_ms(1000);
sei();
}
void inicializar_puertos(void)
{
DDRD |= ((1<<PD2)|(1<<PD3)|(1<<PD4)|(1<<PD5)); //Salidas
//Configurar Timer2. Tic 5.33 ms.
OCR2 = 0x52;
TCCR2 |=((1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20));
TIMSK |= (1<<OCIE2);
sei();
//Inicializar I2C.
TWBR = 0b10011000; //Período SCL 20 us
}
ISR(TIMER2_COMP_vect)
{
static unsigned char cont;
cont++;
switch(cont)
{
case 1: //Generar señal de control
{
comunicaciones=0;
PORTD |= (1<<PD2);
_delay_ms(3);
PORTD &= ~(1<<PD2);
}break;
case 2: //Comunicaciones
{
comunicaciones=1;
}break;
case 3:
//Leer ADC, Encoders, Errores, Estableces
variable.
{
comunicaciones=0;
cont=0;
}break;
}
TIFR |= (1<<OCF2);
}
void i2c_MT(unsigned char direccion, unsigned char dato)
{
TWCR |=
(1<<TWEA);
//Se enciende el módulo
TWCR &=
~(1<<TWSTO);
//enviar señal de start.
TWCR |= ((1<<TWINT)|(1<<TWSTA)|(1<<TWEN));
while (!(TWCR &
(1<<TWINT)))
//Esperar a TWINT
{
if(comunicaciones!=0)
break;
}
//comprobar resultado de la operación anterior.
if ((TWSR & 0xF8) !=
0x08)
//(xxxxx000) != (0x08 Start)
i2c_error();
TWDR =
((direccion)&(0b11111110));
//Enviar dirección y escritura
TWCR &= ~((1<<TWSTO)|(1<<TWSTA));
TWCR |= ((1<<TWINT)|(1<<TWEN));
while (!(TWCR &
(1<<TWINT)))
//Esperar a TWINT
{
if(comunicaciones!=0)
break;
}
//comprobar condición.
if ((TWSR & 0xF8) !=
0x18)
//(xxxxx000) != (0x18 SLA +W)
i2c_error();
TWDR =
dato;
//Cargar byte a enviar
TWCR &= ~((1<<TWSTO)|(1<<TWSTA));
TWCR |= ((1<<TWINT)|(1<<TWEN));
while (!(TWCR & (1<<TWINT)))
//Esperar a TWINT
{
if(comunicaciones!=0)
break;
}
//comprobar condición.
if ((TWSR & 0xF8) !=
0x28)
//(xxxxx000) != (0x28 dato+ack)
i2c_error();
TWCR &=
~(1<<TWSTA);
//enviar señal de stop.
TWCR |= ((1<<TWINT)|(1<<TWEN)|(1<<TWSTO));
_delay_us(20);
}
unsigned char i2c_MR(unsigned char direccion)
{
unsigned char dato=0;
TWCR |= (1<<TWEA);
TWCR &=
~(1<<TWSTO);
//enviar señal de start.
TWCR |= ((1<<TWINT)|(1<<TWSTA)|(1<<TWEN));
while (!(TWCR & (1<<TWINT))) //Esperar a TWINT
{
if(comunicaciones!=0)
break;
}
//comprobar resultado de la operación
anterior.
if ((TWSR & 0xF8) !=
0x08)
//(xxxxx000) != (0x08 Start)
i2c_error();
//enviar byte.
TWDR = ((direccion)|(0b00000001)); //Cargar byte de dirección
TWCR &= ~((1<<TWSTO)|(1<<TWSTA));
TWCR |= ((1<<TWINT)|(1<<TWEN));
while (!(TWCR & (1<<TWINT))) //Esperar a TWINT
{
if(comunicaciones!=0)
break;
}
//comprobar condición.
if ((TWSR & 0xF8) !=
0x40)
//(xxxxx000) != (0x40 SLA +R)
i2c_error();
TWCR &= ~((1<<TWSTO)|(1<<TWSTA)|(1<<TWEA));//Leer segundo byte NO ACK
TWCR |= ((1<<TWINT)|(1<<TWEN));
while (!(TWCR & (1<<TWINT))) //Esperar a TWINT
{
if(comunicaciones!=0)
break;
}
if ((TWSR & 0xF8) !=
0x58)
//(xxxxx000) != (0x58 dato+ no ack)
i2c_error();
dato=TWDR;
TWCR &=
~(1<<TWSTA);
//enviar señal de stop.
TWCR |= ((1<<TWEA)|(1<<TWINT)|(1<<TWEN)|(1<<TWSTO));
_delay_us(20);
return(dato);
}
void i2c_error(void)
{
}