//Interfaz MiniZ
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#define Bus_Datos PORTC
#define Bus_Control PORTA
#define RS PORTA5
#define RW PORTA6
#define E PORTA7
#define LED1 PORTL7 //Amarillo
#define LED2 PORTL5 //Rojo
#define LED3 PORTG1 //Verde
//Comandos para situar el cursor en inicio de líneas.
#define DDRA_LINEA1 0x80 //1000 0000
#define DDRA_LINEA2 0xC0 //1100 0000
#define DDRA_LINEA3 0x94 //1001 0100
#define DDRA_LINEA4 0xD4 //1101 0100
void inicializar_puertos(void);
void reseteo(void);
void escribir_valor_decimal(unsigned char registro);
//Funciones para escribir en el LCD
void lcd_inicializar();
void lcd_escribir_c(char caracter);
void lcd_escribir(char *cadena);
void posicionar_cursor(unsigned char x, unsigned char y);
void lcd_comando(char comando);
char lcd_invertir_bits(char caracter);
//Funciones I2C
void i2c_ST(unsigned char dato);
unsigned char i2c_SR(void);
void i2c_error(void);
//Programas
void programa0(void);
void programa1(void);
void programa2(void);
void programa3(void);
//Variables
volatile unsigned char botones;
volatile unsigned char programa;
volatile unsigned char i2c_enviar;
volatile unsigned char i2c_recibido;
volatile unsigned char boton_libre;
volatile unsigned char comunicaciones;
int main(void)
{
inicializar_puertos();
reseteo();
lcd_inicializar();
while(1)
{
switch(programa)
{
case 3:
programa3();
break;
case 2:
programa2();
break;
case 1:
programa1();
break;
case 0:
programa0();
break;
default: break;
}
// unsigned char copia_ADCH;
/* ADMUX &=
~(1<<MUX0);
//Canal 0.
_delay_us(600);
copia_ADCH=ADCH;
posicionar_cursor(3,10);
escribir_valor_decimal(copia_ADCH);
posicionar_cursor(4,10); //Canal 1
ADMUX |= (1<<MUX0);
_delay_us(600);
copia_ADCH=ADCH;
escribir_valor_decimal(copia_ADCH);*/
}
}
void
inicializar_puertos(void)
//Configurar hardware del pic.
{
//Configurar entradas y salidas.
DDRC=0xFF; //1111 1111
PORTC=0x00;
DDRA|=((1<<RS)|(1<<RW)|(1<<E)); //1110 0000
PORTA &= ~(1<<E);
DDRL= 0xA0; //1010 0000
PORTL=0x00;
DDRG =0x02; //0000 0010
PORTG=0x00;
//Configurar interrupciones externas.
PCICR |= (1<<PCINT2);
PCMSK2 |= 0xFE;
sei();
//Configurar ADC
ADMUX
|=(1<<REFS0);
//Tensión de referencia 5 voltios.
ADMUX
|=(1<<ADLAR);
//8 bits de resolución.
//Canal ADC por defecto ADC0, no tenemos que cambiarlo.
ADCSRA
|=(1<<ADATE);
//Habilitamos el Free Running Mode, por defecto seleccionado
ADCSRA |=((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)); //Prescaler 128, Fadc 125 KHz @ 16MHz.
DIDR0 |=
((1<<ADC0D)|(1<<ADC1D));
//Apagamos la parte digital del puerto.
ADCSRA |=
(1<<ADEN);
//Encendemos ADC
ADCSRA|= (1<<ADSC);
//Comenzar conversiones.
//Configurar I2C
TWAR = 0xE2;
//Dirección de
esclavo en el bus I2C.
TWCR |= ((1<<TWEA)|(1<<TWEN)|(1<<TWIE));
}
void lcd_inicializar() //Se mandan los comandos de configuración según el datasheet.
{
_delay_ms(100);
lcd_comando(0x3C); //Function Set RS0 RW0 0011NF** 0011 1100
lcd_comando(0x3C); //Function Set
lcd_comando(0x0C); //Display ON/OFF Control RS0 RW0 00001DCB 0000 1100
lcd_comando(0x01); //Display Clear RS0 RW0 00000001
lcd_comando(0x06); //Entry Mode Set RS0 RW0 000001I/DS 0000 0110
}
void lcd_escribir_c(char caracter)
{
Bus_Control |= (1<<RS); //RS1 Dato
Bus_Control &= ~(1<<RW); //RS0
Bus_Datos = lcd_invertir_bits(caracter);
Bus_Control |= (1<<E);
_delay_us(100);
Bus_Control &= ~(1<<E);
_delay_ms(1);
}
void lcd_comando(char comando)
{
Bus_Control &= ~(1<<RS); //RS0 Comando
Bus_Control &= ~(1<<RW); //RW0
Bus_Datos = lcd_invertir_bits(comando); //Comando
Bus_Control |= (1<<E);
_delay_us(100);
Bus_Control &= ~(1<<E);
_delay_ms(2);
}
void lcd_escribir(char *cadena)
{
char *inicio = cadena;
unsigned char i=0;
for(i=0;((inicio[i]!='\0')&&(i<20));i++)
{
Bus_Control |= (1<<RS); //RS0 RW0 caracter
Bus_Control &= ~(1<<RW);
Bus_Datos = lcd_invertir_bits(inicio[i]);
Bus_Control |= (1<<E);
_delay_us(100);
Bus_Control &= ~(1<<E);
_delay_ms(1);
}
}
void posicionar_cursor(unsigned char x, unsigned char y) //línea x 1 a 4, carácter y de 1 a 20.
{
unsigned char comando=DDRA_LINEA1;
switch(x)
{
case 1:
{
comando=DDRA_LINEA1+y-1;
}break;
case 2:
{
comando=DDRA_LINEA2+y-1;
}break;
case 3:
{
comando=DDRA_LINEA3+y-1;
}break;
case 4:
{
comando=DDRA_LINEA4+y-1;
}break;
default:break;
}
lcd_comando(comando);
}
char lcd_invertir_bits(char caracter)
{
char copia_caracter=caracter;
char caracter_cambiado=0x00;
caracter_cambiado |= (((copia_caracter)&(0x80))>>7);
copia_caracter=caracter;
caracter_cambiado |= (((copia_caracter)&(0x40))>>5);
copia_caracter=caracter;
caracter_cambiado |= (((copia_caracter)&(0x20))>>3);
copia_caracter=caracter;
caracter_cambiado |= (((copia_caracter)&(0x10))>>1);
copia_caracter=caracter;
caracter_cambiado |= (((copia_caracter)&(0x08))<<1);
copia_caracter=caracter;
caracter_cambiado |= (((copia_caracter)&(0x04))<<3);
copia_caracter=caracter;
caracter_cambiado |= (((copia_caracter)&(0x02))<<5);
copia_caracter=caracter;
caracter_cambiado |= (((copia_caracter)&(0x01))<<7);
return(caracter_cambiado);
}
void reseteo(void)
{
PORTL |= ((1<<LED1)|(1<<LED2));
PORTG |= (1<<LED3);
_delay_ms(500);
PORTL &= ~((1<<LED1)|(1<<LED2));
PORTG &= ~(1<<LED3);
_delay_ms(500);
PORTL |= ((1<<LED1)|(1<<LED2));
PORTG |= (1<<LED3);
_delay_ms(500);
PORTL &= ~((1<<LED1)|(1<<LED2));
PORTG &= ~(1<<LED3);
_delay_ms(500);
PORTL |= ((1<<LED1)|(1<<LED2));
PORTG |= (1<<LED3);
_delay_ms(500);
PORTL &= ~((1<<LED1)|(1<<LED2));
PORTG &= ~(1<<LED3);
}
ISR(PCINT2_vect)
{
if ((PINK&(1<<PINK1))==0)
{
botones=7;
boton_libre=0;
}
else if ((PINK&(1<<PINK2))==0)
{
botones=6;
boton_libre=0;
}
else if ((PINK&(1<<PINK3))==0)
{
botones=5;
boton_libre=0;
}
else if ((PINK&(1<<PINK4))==0)
{
botones=4;
boton_libre=0;
}
else if ((PINK&(1<<PINK5))==0)
{
botones=3;
boton_libre=0;
}
else if ((PINK&(1<<PINK6))==0)
{
botones=2;
boton_libre=0;
}
else if ((PINK&(1<<PINK7))==0)
{
botones=1;
boton_libre=0;
}
PCIFR |=(1<<PCIF2);
}
void escribir_valor_decimal(unsigned char registro) //Escribir binario a decimal.
{
char centenas = 0;
char decenas = 0;
char unidades = 0;
while(registro>=100)
{
registro= registro -100;
centenas++;
}
while(registro>=10)
{
registro=registro -10;
decenas++;
}
while(registro>0)
{
registro=registro-1;
unidades++;
}
lcd_escribir_c(centenas | 0b00110000);
lcd_escribir_c(decenas | 0b00110000);
lcd_escribir_c(unidades | 0b00110000);
}
/************************************************************************************/
void programa0()
{
char linea1[]="Interfaz MiniZ";
char linea2[]="con Arduino MeGa";
char linea3[]="www.jmnlab.com";
PORTL &= ~((1<<LED1)|(1<<LED2));
PORTG &= ~(1<<LED3);
lcd_comando(0x01);
posicionar_cursor(1,4);
lcd_escribir(linea1);
posicionar_cursor(2,3);
lcd_escribir(linea2);
posicionar_cursor(4,4);
lcd_escribir(linea3);
while(programa==0)
{
switch(botones)
{
case 7:
break;
case 6:
break;
case 5:
break;
case 4:
programa=0;
break;
case 3:
programa=3;
break;
case 2:
programa=2;
break;
case 1:
programa=1;
break;
default: break;
}
PORTG |= (1<<LED3);
PORTL |= (1<<LED1);
PORTL |= (1<<LED2);
_delay_ms(400);
PORTL &= ~((1<<LED1)|(1<<LED2));
PORTG &= ~(1<<LED3);
_delay_ms(400);
}
}
void programa1()
{
// unsigned int tdir=0;
// unsigned int tvel=0;
// unsigned int direccion=0;
// unsigned char velocidad=0;
// unsigned int sensores=0;
lcd_comando(0x01);
PORTL &= ~((1<<LED1)|(1<<LED2));
PORTG |= (1<<LED3);
lcd_escribir_c('D');
lcd_escribir_c('.');
posicionar_cursor(1,10);
lcd_escribir_c('m');
lcd_escribir_c('s');
lcd_escribir_c(' ');
lcd_escribir_c('R');
lcd_escribir_c(':');
posicionar_cursor(2,1);
lcd_escribir_c('V');
lcd_escribir_c('.');
posicionar_cursor(2,10);
lcd_escribir_c('m');
lcd_escribir_c('s');
posicionar_cursor(3,1);
lcd_escribir_c('E');
lcd_escribir_c('.');
lcd_escribir_c('D');
lcd_escribir_c(':');
posicionar_cursor(3,10);
lcd_escribir_c('E');
lcd_escribir_c('.');
lcd_escribir_c('I');
lcd_escribir_c(':');
posicionar_cursor(4,1);
lcd_escribir_c('S');
lcd_escribir_c(':');
posicionar_cursor(4,16);
lcd_escribir_c('B');
lcd_escribir_c(':');
while(programa==1)
{
switch(botones)
{
case 7:
break;
case 6:
break;
case 5:
break;
case 4:
programa=0;
break;
case 3:
programa=3;
break;
case 2:
programa=2;
break;
case 1:
programa=1;
break;
default: break;
}
}
}
void programa2()
{
static unsigned char copia_i2c_enviar=0;
static unsigned char copia_i2c_recibido=0;
lcd_comando(0x01);
PORTL &= ~(1<<LED2);
PORTG &= ~(1<<LED3);
PORTL |= (1<<LED1);
lcd_escribir("Prueba conexion I2C.");
posicionar_cursor(2,1);
lcd_escribir("Led V I: C:");
posicionar_cursor(3,1);
lcd_escribir("Led A I: C:");
posicionar_cursor(4,1);
lcd_escribir("Led R I: C:");
while(programa==2)
{
switch(botones)
{
case 7:
if(boton_libre==0)
{
boton_libre=1;
i2c_enviar ^=0x02;
}
break;
case 6:
if(boton_libre==0)
{
boton_libre=1;
i2c_enviar ^=0x01;
}
break;
case 5:
if(boton_libre==0)
{
boton_libre=1;
i2c_enviar ^=0x04;
}
break;
case 4:
programa=0;
break;
case 3:
programa=3;
break;
case 2:
programa=2;
break;
case 1:
programa=1;
break;
default: break;
}
copia_i2c_enviar=i2c_enviar;
copia_i2c_recibido=i2c_recibido;
if(((copia_i2c_enviar)&(0x01))!=0)
{
posicionar_cursor(2,10);
lcd_escribir_c('O');
lcd_escribir_c('N');
lcd_escribir_c(' ');
}
else
{
posicionar_cursor(2,10);
lcd_escribir_c('O');
lcd_escribir_c('F');
lcd_escribir_c('F');
}
copia_i2c_enviar=i2c_enviar;
if(((copia_i2c_enviar)&(0x02))!=0)
{
posicionar_cursor(3,10);
lcd_escribir_c('O');
lcd_escribir_c('N');
lcd_escribir_c(' ');
}
else
{
posicionar_cursor(3,10);
lcd_escribir_c('O');
lcd_escribir_c('F');
lcd_escribir_c('F');
}
copia_i2c_enviar=i2c_enviar;
if(((copia_i2c_enviar)&(0x04))!=0)
{
posicionar_cursor(4,10);
lcd_escribir_c('O');
lcd_escribir_c('N');
lcd_escribir_c(' ');
}
else
{
posicionar_cursor(4,10);
lcd_escribir_c('O');
lcd_escribir_c('F');
lcd_escribir_c('F');
}
if(((copia_i2c_recibido)&(0x01))!=0)
{
posicionar_cursor(2,17);
lcd_escribir_c('O');
lcd_escribir_c('N');
lcd_escribir_c(' ');
}
else
{
posicionar_cursor(2,17);
lcd_escribir_c('O');
lcd_escribir_c('F');
lcd_escribir_c('F');
}
copia_i2c_recibido=i2c_recibido;
if(((copia_i2c_recibido)&(0x02))!=0)
{
posicionar_cursor(3,17);
lcd_escribir_c('O');
lcd_escribir_c('N');
lcd_escribir_c(' ');
}
else
{
posicionar_cursor(3,17);
lcd_escribir_c('O');
lcd_escribir_c('F');
lcd_escribir_c('F');
}
copia_i2c_recibido=i2c_recibido;
if(((copia_i2c_recibido)&(0x04))!=0)
{
posicionar_cursor(4,17);
lcd_escribir_c('O');
lcd_escribir_c('N');
lcd_escribir_c(' ');
}
else
{
posicionar_cursor(4,17);
lcd_escribir_c('O');
lcd_escribir_c('F');
lcd_escribir_c('F');
}
}
}
void programa3()
{
lcd_comando(0x01);
PORTL &= ~(1<<LED1);
PORTG &= ~(1<<LED3);
PORTL |= (1<<LED2);
posicionar_cursor(2,3);
lcd_escribir("No Implementado");
while(programa==3)
{
switch(botones)
{
case 7:
break;
case 6:
break;
case 5:
break;
case 4:
programa=0;
break;
case 3:
programa=3;
break;
case 2:
programa=2;
break;
case 1:
programa=1;
break;
default: break;
}
}
}
ISR(TWI_vect)
{
if(programa==2)
{
if((TWSR & 0xF8) == 0x60)
i2c_recibido=i2c_SR();
else if((TWSR & 0xF8) == 0xA8)
i2c_ST(i2c_enviar);
else
i2c_error();
}
TWCR |= (1<<TWINT);
}
void i2c_ST(unsigned char dato)
{
TWDR=dato;
//Cargar el dato a enviar.
TWCR &= ~((1<<TWSTO)|(1<<TWEA));
TWCR |= (1<<TWINT);
//Enviar
dato.
while (!(TWCR & (1<<TWINT))) //Esperar a TWINT
{
}
if((TWSR & 0xF8) != 0xC8); //Dato enviado, no esperamos ACK.
i2c_error();
TWCR &= ~((1<<TWSTO)|(1<<TWSTA));//Dejamos el módulo preparado.
TWCR |= ((1<<TWINT)|(1<<TWEA));
}
unsigned char i2c_SR(void)
{
unsigned char dato=0;
TWCR &= ~(1<<TWSTO);
//Preparados para recibir dato y devolver ACK
TWCR |= ((1<<TWINT)|(1<<TWEA));
while (!(TWCR & (1<<TWINT))) //Esperar a TWINT
{
}
if((TWSR & 0xF8) != 0x80);
//Hemos recibido dato y
generado ACK.
i2c_error();
dato=TWDR;
//Almacenamos dato recibido.
TWCR &= ~(1<<TWSTO);
//Preparados para recibir STOP
TWCR |= ((1<<TWINT)|(1<<TWEA));
while (!(TWCR & (1<<TWINT))) //Esperar a TWINT
{
}
if((TWSR & 0xF8) != 0xA0); //STOP
i2c_error();
TWCR &= ~((1<<TWSTO)|(1<<TWSTA)); //Dejamos el módulo preparado.
TWCR |= ((1<<TWINT)|(1<<TWEA));
return(dato);
}
void i2c_error(void)
{
}