//Módulo Hexápodo: LCD
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#define Bus_Datos PORTK
#define Bus_Control PORTF
#define RS PORTF5
#define RW PORTF6
#define E PORTF7
//Comandos situar el cursor inicio línea.
#define DDRA_LINEA1 0x80 //1000 0000
#define DDRA_LINEA2 0xC0 //1100 0000
#define DDRA_LINEA3 0x94 //1001 0100
#define DDRA_LINEA4 0xD4 //1101 0100
//Botones del LCD, interrupciones externas.
//#define boton1 PORTD2 //INT2
//#define boton2 PORTD3 //INT3
//#define boton3 PORTE4 //INT4
//#define Potenciometro PORTF0 //ADC0
void lcd_comando(unsigned char comando);
void lcd_escribir_c(char caracter);
void lcd_escribir(char *cadena);
void posicionar_cursor(unsigned char x, unsigned char y) ;
void escribir_valor_decimal(unsigned char registro);
void escribir_registro(unsigned char registro);
void valor_real(unsigned char registro);
void lcd_inicializar();
void inicializar_timer4(void);
//****************** Programas *******************************/
void programa0();
void programa1();
void programa2();
void programa3();
void programa4();
void programa5();
void programa6();
void programa7();
void programa8();
void programa9();
//****************** Variables Globales *********************//
volatile unsigned char estado;
unsigned char copia_estado;
volatile unsigned char cuenta_tecla;
unsigned char copia_cuenta_tecla;
unsigned char ultima_cuenta_tecla;
volatile unsigned char pantalla0=1;
volatile unsigned char pantalla1=1;
volatile unsigned char pantalla2=1;
unsigned char copia_pantalla0=1;
unsigned char copia_pantalla1=1;
unsigned char copia_pantalla2=1;
volatile unsigned char servo_periodo;
//**********************************************/
int main(void)
{
lcd_inicializar(); //Inicializar módulo lcd.
// inicializar_timer4(); //Inicializar timer
char linea1[]="Hexapodo FireFly";
char linea2[]="www.jmnlab.com";
char linea3[]="Pulse el boton1 para";
char linea4[]="comenzar";
posicionar_cursor(1,3);
lcd_escribir(linea1);
posicionar_cursor(2,4);
lcd_escribir(linea2);
posicionar_cursor(3,1);
lcd_escribir(linea3);
posicionar_cursor(4,7);
lcd_escribir(linea4);
while(1)
{
switch(estado)
{
case 0:
{
programa0();
}break;
case 1:
{
programa1();
}break;
case 2:
{
programa2();
}break;
case 3:
{
programa3();
}break;
case 4:
{
programa4();
}break;
case 5:
{
programa5();
}break;
case 6:
{
programa6();
}break;
case 7:
{
programa7();
}break;
case 8:
{
programa8();
}break;
case 9:
{
programa9();
}break;
default:break;
}
}
}
/**********************************************************************************************************************/
/********************************** Configurar y escribir en el LCD ***************************************************/
/**********************************************************************************************************************/
void lcd_comando(unsigned char comando)
{
Bus_Control &= ~(1<<RS); //RS0
Bus_Control &= ~(1<<RW); //RW0
Bus_Datos = comando; //Comando
Bus_Control |= (1<<E);
_delay_ms(5);
Bus_Control &= ~(1<<E);
_delay_ms(5);
}
void lcd_escribir_c(char caracter)
{
Bus_Control |= (1<<RS); //RS1
Bus_Control &= ~(1<<RW); //RS0
Bus_Datos = caracter;
Bus_Control |= (1<<E);
_delay_ms(5);
Bus_Control &= ~(1<<E);
_delay_ms(5);
}
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 = inicio[i];
Bus_Control |= (1<<E);
_delay_ms(5);
Bus_Control &= ~(1<<E);
_delay_ms(5);
}
}
void posicionar_cursor(unsigned char x, unsigned char y) //línea 1 a 4, columna 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);
}
/**********************************************************************************************************************/
/****************************************** ISR's *********************************************************************/
/**********************************************************************************************************************/
ISR(INT2_vect)
{
switch(estado)
{
case 0:
{
cuenta_tecla++;
if(cuenta_tecla>9)
cuenta_tecla=9;
_delay_ms(200); //Rebotes
}break;
case 2:
{
servo_periodo = servo_periodo + 1;
OCR4A = OCR4A + 0x00FA;
if(servo_periodo>50)
servo_periodo=50;
if(OCR4A>0x3A98)
OCR4A=0x3A98;
}break;
default:break;
}
EIFR |=(1<<INT2);
}
ISR(INT3_vect)
{
switch(estado)
{
case 0:
{
cuenta_tecla--;
if(cuenta_tecla<1)
cuenta_tecla=1;
_delay_ms(200); //Rebotes
}
case 2:
{
servo_periodo= servo_periodo -1;
OCR4A = OCR4A - 0x00FA;
if(servo_periodo<4)
servo_periodo=4;
if(OCR4A<0x03E8)
OCR4A=0x03E8;
}break;
default:break;
}
EIFR |=(1<<INT3);
}
ISR(INT4_vect)
{
pantalla0=1;
pantalla1=1;
pantalla2=1;
if (estado==0)
{
estado=cuenta_tecla;
ultima_cuenta_tecla=cuenta_tecla;
}
else
{
estado=0;
cuenta_tecla=ultima_cuenta_tecla;
}
_delay_ms(200); //Rebotes
EIFR |=(1<<INT4);
}
ISR(ADC_vect)
{
}
ISR(TIMER4_COMPA_vect)
{
double copia_ADCH=0;
copia_ADCH=(double)(ADCH*10);
PORTA |=(1<<PORTA7);
_delay_us(copia_ADCH);
PORTA &= ~(1<<PORTA7);
TIFR4 |= (1<<OCF4A);
}
/**********************************************************************************************************************/
/*************************************** Funciones Manipular Registros LCD ********************************************/
/**********************************************************************************************************************/
void escribir_registro(unsigned char registro) //Escribir registro LCD.
{
unsigned char mascara = 0b10000000;
unsigned char cont=0;
for(cont=0;cont<8;cont++)
{
if((registro & mascara)==0)
lcd_escribir_c('0');
else
lcd_escribir_c('1');
// mascara>>1;
mascara = mascara/2;
}
}
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 valor_real(unsigned char registro) //Escribir valor binario a analógico LCD, Vref 5V, 8 bits.
{
unsigned int v_real = (int)registro;
char unidades = 0;
char decimas = 0;
char centesimas = 0;
v_real=v_real*195;
while(v_real>10000)
{
v_real=v_real - 10000;
unidades++;
}
while(v_real>1000)
{
v_real=v_real - 1000;
decimas++;
}
while(v_real>100)
{
v_real=v_real - 100;
centesimas++;
}
lcd_escribir_c(unidades | 0b00110000);
lcd_escribir_c('.');
lcd_escribir_c(decimas | 0b00110000);
lcd_escribir_c(centesimas | 0b00110000);
lcd_escribir_c('V');
}
/**********************************************************************************************************************/
/**************************** Inicializar el Módulo LCD ***************************************************************/
/**********************************************************************************************************************/
void lcd_inicializar()
{
/************************************************************///LCD
DDRK=0xFF; //1111 1111
PORTK=0x00;
DDRF|=((1<<RS)|(1<<RW)|(1<<E)); //1110 0000
PORTF &= ~(1<<E);
_delay_ms(100);
lcd_comando(0x3C); //Function Set RS0 RW0 0011 NF** 0011 1100 C
lcd_comando(0x3C); //Function Set
lcd_comando(0x0C); //Display ON/OFF Control RS0 RW0 00001DCB 0000 1100 c
lcd_comando(0x01); //Display Clear RS0 RW0 00000001
lcd_comando(0x06); //Entry Mode Set RS0 RW0 000001I/DS 0000 0111
/************************************************************///ADC
ADMUX |=(1<<REFS0); //Tensión de referencia AVCC 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); //Apagamos la parte digital del puerto.
ADCSRA |= (1<<ADIE);//Enable ADC Interrupt
ADCSRA |= (1<<ADEN);//Enable ADC
/************************************************************///Botones
//configurar registros interrupciones.
//Tipo de evento que dispará la interrupción, 10, flanco de bajada.
EICRA &= ~(1<<ISC20); //INT2
EICRA |= (1<<ISC21);
EICRA &= ~(1<<ISC30); //INT3
EICRA |= (1<<ISC31);
EICRB &= ~(1<<ISC40); //INT4
EICRB |= (1<<ISC41);
//Habilitar interrupciones externas
EIMSK |= ((1<<INT2)|(1<<INT3)|(1<<INT4));
//Habilitar todas las interrupciones
sei();
}
/**********************************************************************************************************************/
void inicializar_timer4(void) //Configura el timer y la interrupción.
{
DDRA |= (1<<PA7); //Puerto A7 pin osciloscopio
OCR4A= 0x1388; //20 ms
TCCR4B
|=((1<<WGM42)|(1<<CS41)|(1<<CS40));
//Los bits que no se tocan a 0 por defecto
TIMSK4 |= (1<<OCIE4A);
}
/**********************************************************************************************************************/
/**********************************************************************************************************************/
/**********************************************************************************************************************/
/**********************************************************************************************************************/
void programa0()
{
//Selección de programa.
char linea5[]="Seleccione Programa:";
char linea6[]="Leer Potenciometro";
char linea7[]="Servomotor";
char linea8[]="Sensor U. I2C";
char linea9[]="S. Infrarrojo";
char linea10[]="PWM Led RGB";
char linea11[]="Comunicacion PC";
char linea12[]="Comunicacion SPI";
char linea13[]="Controladora 24 S.";
char linea14[]="Control Bateria";
while(estado==0)
{
ADCSRA &= ~(1<<ADEN); //Apagar ADC.
ADCSRA &= ~(1<<ADSC);
TIMSK4 &= ~(1<<OCIE4A); //Deshabilitar interrupción
TCCR4B &= ~(1<<CS41); //Parar timer
TCCR4B &= ~(1<<CS42);
cli();
copia_cuenta_tecla=cuenta_tecla;
copia_pantalla0=pantalla0;
copia_pantalla1=pantalla1;
copia_pantalla2=pantalla2;
sei();
if((copia_cuenta_tecla>0)&&(copia_cuenta_tecla<4)&&(copia_pantalla0==1))
{
lcd_comando(0x01);
lcd_escribir(linea5);
posicionar_cursor(2,2);
lcd_escribir(linea6);
posicionar_cursor(3,2);
lcd_escribir(linea7);
posicionar_cursor(4,2);
lcd_escribir(linea8);
pantalla0=0;
pantalla1=1;
pantalla2=1;
}
if((copia_cuenta_tecla>3)&&(copia_cuenta_tecla<7)&&(copia_pantalla1==1))
{
lcd_comando(0x01);
lcd_escribir(linea5);
posicionar_cursor(2,2);
lcd_escribir(linea9);
posicionar_cursor(3,2);
lcd_escribir(linea10);
posicionar_cursor(4,2);
lcd_escribir(linea11);
pantalla0=1;
pantalla1=0;
pantalla2=1;
}
if((copia_cuenta_tecla>6)&&(copia_cuenta_tecla<10)&&(copia_pantalla2==1))
{
lcd_comando(0x01);
lcd_escribir(linea5);
posicionar_cursor(2,2);
lcd_escribir(linea12);
posicionar_cursor(3,2);
lcd_escribir(linea13);
posicionar_cursor(4,2);
lcd_escribir(linea14);
pantalla0=1;
pantalla1=1;
pantalla2=0;
}
switch(copia_cuenta_tecla)
{
case 1:
{
posicionar_cursor(2,1);
lcd_escribir_c(0b01111110);
posicionar_cursor(3,1);
lcd_escribir_c(' ');
posicionar_cursor(4,1);
lcd_escribir_c(' ');
}break;
case 2:
{
posicionar_cursor(2,1);
lcd_escribir_c(' ');
posicionar_cursor(3,1);
lcd_escribir_c(0b01111110);
posicionar_cursor(4,1);
lcd_escribir_c(' ');
}break;
case 3:
{
posicionar_cursor(2,1);
lcd_escribir_c(' ');
posicionar_cursor(3,1);
lcd_escribir_c(' ');
posicionar_cursor(4,1);
lcd_escribir_c(0b01111110);
}break;
case 4:
{
posicionar_cursor(2,1);
lcd_escribir_c(0b01111110);
posicionar_cursor(3,1);
lcd_escribir_c(' ');
posicionar_cursor(4,1);
lcd_escribir_c(' ');
}break;
case 5:
{
posicionar_cursor(2,1);
lcd_escribir_c(' ');
posicionar_cursor(3,1);
lcd_escribir_c(0b01111110);
posicionar_cursor(4,1);
lcd_escribir_c(' ');
}break;
case 6:
{
posicionar_cursor(2,1);
lcd_escribir_c(' ');
posicionar_cursor(3,1);
lcd_escribir_c(' ');
posicionar_cursor(4,1);
lcd_escribir_c(0b01111110);
}break;
case 7:
{
posicionar_cursor(2,1);
lcd_escribir_c(0b01111110);
posicionar_cursor(3,1);
lcd_escribir_c(' ');
posicionar_cursor(4,1);
lcd_escribir_c(' ');
}break;
case 8:
{
posicionar_cursor(2,1);
lcd_escribir_c(' ');
posicionar_cursor(3,1);
lcd_escribir_c(0b01111110);
posicionar_cursor(4,1);
lcd_escribir_c(' ');
}break;
case 9:
{
posicionar_cursor(2,1);
lcd_escribir_c(' ');
posicionar_cursor(3,1);
lcd_escribir_c(' ');
posicionar_cursor(4,1);
lcd_escribir_c(0b01111110);
}break;
}
}
}
/******************************************************************************************************/
/********************** Programa para Leer el Potenciometro del LCD **********************************/
/******************************************************************************************************/
void programa1()
{
char linea1[]="Reg. ADCH:";
char linea2[]="Caracter LCD:";
char linea3[]="Valor Tension:";
char linea4[]="V. decimal ADCH:";
char linea5[]="Programa para leer";
char linea6[]="un Potenciometro";
char linea7[]="Registro usado ADCH";
unsigned char contador_anim=0;
unsigned char copia_ADCH=ADCH;
// cli();
// copia_pantalla0=pantalla0;
// copia_estado=estado;
// sei();
lcd_comando(0x01);
posicionar_cursor(1,2);
lcd_escribir(linea5);
posicionar_cursor(2,3);
lcd_escribir(linea6);
posicionar_cursor(3,1);
lcd_escribir(linea7);
posicionar_cursor(4,1);
for(contador_anim=0;contador_anim<20;contador_anim++)
{
lcd_escribir_c('.');
_delay_ms(100);
}
ADCSRA &= ~(1<<ADIE); //Sin interrupción
ADCSRA|= (1<<ADEN); //Comenzar conversiones.
ADCSRA|= (1<<ADSC); //Comenzar conversiones.
lcd_comando(0x01);
posicionar_cursor(1,1);
lcd_escribir(linea1);
posicionar_cursor(3,1);
lcd_escribir(linea2);
posicionar_cursor(2,1);
lcd_escribir(linea4);
posicionar_cursor(4,1);
lcd_escribir(linea3);
while(estado==1)
{
copia_ADCH=ADCH;
posicionar_cursor(1,12);
escribir_registro(copia_ADCH);
posicionar_cursor(3,15);
lcd_escribir_c(copia_ADCH);
posicionar_cursor(2,18);
escribir_valor_decimal(copia_ADCH);
posicionar_cursor(4,16);
valor_real(copia_ADCH);
}
}
/******************************************************************************************************/
/***************************** Programa para controlar un servomotor **********************************/
/******************************************************************************************************/
void programa2()
{
// char linea1[]="Control de un";
char linea2[]="Servomotor";
char linea3[]="Periodo:";
char linea4[]="Valor ADCH:";
char linea5[]="Periodo: 4 a 50 ms";
char linea6[]="Pulso: 50 us a 3ms";
unsigned char contador_anim=0;
unsigned char copia_servo_periodo=servo_periodo;
unsigned char copia_ADCH=ADCH;
servo_periodo=20;
inicializar_timer4();
lcd_comando(0x01);
posicionar_cursor(1,6);
lcd_escribir(linea2);
posicionar_cursor(2,1);
lcd_escribir(linea5);
posicionar_cursor(3,1);
lcd_escribir(linea6);
posicionar_cursor(4,1);
for(contador_anim=0;contador_anim<20;contador_anim++)
{
lcd_escribir_c('.');
_delay_ms(140);
}
lcd_comando(0x01);
posicionar_cursor(1,6);
lcd_escribir(linea2);
posicionar_cursor(3,1);
lcd_escribir(linea3);
posicionar_cursor(4,1);
lcd_escribir(linea4);
posicionar_cursor(3,18);
lcd_escribir_c('m');
lcd_escribir_c('s');
// posicionar_cursor(4,17);
// lcd_escribir_c('0');
// posicionar_cursor(4,19);
// lcd_escribir_c(0b11100100);
// lcd_escribir_c('s');
ADCSRA|= (1<<ADEN); //Comenzar conversiones.
ADCSRA|= (1<<ADSC); //Comenzar conversiones.
ADCSRA &= ~(1<<ADIE); //Sin interrupción.
while(estado==2)
{
cli();
copia_servo_periodo = servo_periodo;
copia_ADCH=ADCH;
sei();
posicionar_cursor(3,14);
escribir_valor_decimal(copia_servo_periodo);
posicionar_cursor(4,14);
escribir_valor_decimal(copia_ADCH);
}
}
/******************************************************************************************************/
/***************************** Futuro Programa ********************************************************/
/******************************************************************************************************/
void programa3()
{
char linea[]="Sensor U. I2C";
char linea1[]="No implementado";
cli();
copia_pantalla0=pantalla0;
copia_estado=estado;
sei();
if ((copia_pantalla0==1)&&(copia_estado!=0))
{
lcd_comando(0x01);
posicionar_cursor(1,4);
lcd_escribir(linea);
posicionar_cursor(3,3);
lcd_escribir(linea1);
if(copia_estado==3)
pantalla0=0;
}
}
/******************************************************************************************************/
/***************************** Futuro Programa ********************************************************/
/******************************************************************************************************/
void programa4()
{
char linea[]="S. Infrarrojo";
char linea1[]="No implementado";
cli();
copia_pantalla0=pantalla0;
copia_estado=estado;
sei();
if ((copia_pantalla0==1)&&(copia_estado!=0))
{
lcd_comando(0x01);
posicionar_cursor(1,4);
lcd_escribir(linea);
posicionar_cursor(3,3);
lcd_escribir(linea1);
if(copia_estado==4)
pantalla0=0;
}
}
/******************************************************************************************************/
/***************************** Futuro Programa ********************************************************/
/******************************************************************************************************/
void programa5()
{
char linea[]="PWM Led RGB";
char linea1[]="No implementado";
cli();
copia_pantalla0=pantalla0;
copia_estado=estado;
sei();
if ((copia_pantalla0==1)&&(copia_estado!=0))
{
lcd_comando(0x01);
posicionar_cursor(1,5);
lcd_escribir(linea);
posicionar_cursor(3,3);
lcd_escribir(linea1);
if(copia_estado==5)
pantalla0=0;
}
}
/******************************************************************************************************/
/***************************** Futuro Programa ********************************************************/
/******************************************************************************************************/
void programa6()
{
char linea[]="Comunicacion PC";
char linea1[]="No implementado";
cli();
copia_pantalla0=pantalla0;
copia_estado=estado;
sei();
if ((copia_pantalla0==1)&&(copia_estado!=0))
{
lcd_comando(0x01);
posicionar_cursor(1,3);
lcd_escribir(linea);
posicionar_cursor(3,3);
lcd_escribir(linea1);
if(copia_estado==6)
pantalla0=0;
}
}
/******************************************************************************************************/
/***************************** Futuro Programa ********************************************************/
/******************************************************************************************************/
void programa7()
{
char linea[]="Comunicacion SPI";
char linea1[]="No implementado";
cli();
copia_pantalla0=pantalla0;
copia_estado=estado;
sei();
if ((copia_pantalla0==1)&&(copia_estado!=0))
{
lcd_comando(0x01);
posicionar_cursor(1,3);
lcd_escribir(linea);
posicionar_cursor(3,3);
lcd_escribir(linea1);
if(copia_estado==7)
pantalla0=0;
}
}
/******************************************************************************************************/
/***************************** Futuro Programa ********************************************************/
/******************************************************************************************************/
void programa8()
{
char linea[]="Controladora 24 S.";
char linea1[]="No implementado";
cli();
copia_pantalla0=pantalla0;
copia_estado=estado;
sei();
if ((copia_pantalla0==1)&&(copia_estado!=0))
{
lcd_comando(0x01);
posicionar_cursor(1,2);
lcd_escribir(linea);
posicionar_cursor(3,3);
lcd_escribir(linea1);
if(copia_estado==8)
pantalla0=0;
}
}
/******************************************************************************************************/
/***************************** Futuro Programa ********************************************************/
/******************************************************************************************************/
void programa9()
{
char linea[]="Control Bateria";
char linea1[]="No implementado";
cli();
copia_pantalla0=pantalla0;
copia_estado=estado;
sei();
if ((copia_pantalla0==1)&&(copia_estado!=0))
{
lcd_comando(0x01);
posicionar_cursor(1,3);
lcd_escribir(linea);
posicionar_cursor(3,3);
lcd_escribir(linea1);
if(copia_estado==9)
pantalla0=0;
}
}
/******************************************************************************************************/
/******************************************************************************************************/
/******************************************************************************************************/