Para el manejo de los datos,una forma muy práctica puede ser usando esta estructura:
Codigo:
///////////////////////////////////// PREPROCESADO ///////////////////////////////////
#include <16F84.h>
#use delay(clock=10000000)
#fuses HS,NOWDT,NOPUT
#define use_portb_lcd TRUE
#include "lcd.c"
//////////////////////////////////////// TIPOS ///////////////////////////////////////
typedef enum Trango {manual,automatico};
typedef struct Tconfiguracion {
Trango rango;
int ajuste_fino;
int t_integracion;
int limite;
int compensacion;
int amperaje;
int sensibilidad;
boolean autocalibracion;
};
/////////////////////////////////////// GLOBALES /////////////////////////////////////
struct Tconfiguracion configuracion;
////////////////////////////////////// PRINCIPAL /////////////////////////////////////
void main()
{
lcd_init();
configuracion.rango = manual;
configuracion.ajuste_fino = 0;
configuracion.autocalibracion = TRUE;
// etc...
for(;;) {}
}
Para evitarte los rebotes,en tu rutina de interrupción puedes llamar a una rutina que tuviese esta forma:
Codigo:
// Estamos suponiendo que loa pulsadores van a ser activos a nivel alto.
void antirebote()
{
delay_ms(30);
while(PORTB != 0) {} // No progresamos hasta que ningún pulsador esté activo
delay_ms(30);
}
Te explico.
La metodología que he seguido para hallar las funciones es la misma que se usa para diseñar máquinas de estados finitos con biestables,es decir con dispositivos físicos.
Partimos de la cantidad de estados que va a tener la máquina,en nuestro caso 3,por lo que podemos codificarlos con 2 bits:
MENU -> le damos la codificación 00 (q0,q1)
Submenu 1 -> 01 (q0,q1)
Submenu 2 -> 11 (q0,q1)
Bien,a partir de esto,tenemos las variables q0 y q1,que dependiendo del valor que tengan,estaremos en un estado u otro.
También tenemos las entradas,que son dos (me y av),correspondientes a cada uno de los pulsadores.
Pues ya tenemos las 4 variables que determinarán el funcionamiento de la máquina.La transición de un estado actual a un posible próximo estado no dependerá sólo de las variables de entrada,si no también de las variables q0 y q1,es decir,de cúal sea el estado actual.Esto se hace patente si imaginamos que la máquina se encuentra en el estado (q0=0,q1=0)->(MENU->00) y pulsamos la tecla "avanzar"(av=1).No ocurre nada(o mejor dicho,hace una transición al mismo estado).Pero si se da esa misma entrada en un momento en en el que la máquina se encuentra en el estado (q0=0,q1=1)->(Submenu 1->01),se producirá una transición al estado Submenu 2 (11).
Lo que hay que buscar son las funciones que modificarán los valores de las variables de estado (q0,q1,q2,q3,...qn),en función de ellas mismas y de las variables de entrada.
Lo primero sería hacer un diagrama de estados,con todos los estados,unidos entre sí por todas las posibles transiciones que se puedan dar(flechas) cada una de las cuales etiquetada con la entrada que provoca dicha transición.Después se pasa todo eso a una tabla:
Codigo:
MENU = 00
Submenu1 = 01
Submenu2 = 11
___________________________
|ESTADO | ENTRADAS(me,av) |
| q0,q1 | 00 | 01 | 11 | 10 |
|_______|____|____|____|____|
| | | | | |
MENU | 0 0 | -- | 01 | 00 | 00 |
|_______|____|____|____|____|
| | | | | |
Submenu1 | 0 1 | -- | 00 | 01 | 11 |
|_______|____|____|____|____|
| | | | | |
Submenu2 | 1 1 | -- | 00 | 11 | 01 |
|_______|____|____|____|____|
Las casillas de la izquierda representan el estado actual,y las demás representan el estado siguiente que se dará a partir de ese estado actual si se dan las entradas según la tabla.
A partir de aquí se construyen los mapas de karnaugh,uno para cada variable de estado,es decir,uno para q0 y otro para q1.Estos mapas se rellenan con el bit correspondiente a la función que estamos calculando,es decir,si estamos haciendo el mapa de q0,cogeremos de la tabla anterior los valores de q0:
Codigo:
me,av
00 01 11 10
q0,q1 \_________________
| | | | |
00 | X | 0 | 0 | 0 |
|___|___|___|___|
| | | | |
01 | X | 0 | 0 | 1 |
|___|___|___|___|
| | | | |
11 | X | 0 | 1 | 0 |
|___|___|___|___|
| | | | |
10 | X | X | X | X |
|___|___|___|___|
q0 = ((!q0) & q1 & (!av)) | q0 & me & av;
Y lo mismo para q1:
Codigo:
me,av
00 01 11 10
q0,q1 \_________________
| | | | |
00 | X | 1 | 0 | 0 |
|___|___|___|___|
| | | | |
01 | X | 0 | 1 | 1 |
|___|___|___|___|
| | | | |
11 | X | 0 | 1 | 1 |
|___|___|___|___|
| | | | |
10 | X | X | X | X |
|___|___|___|___|
q1 = ((!q1) | me | (!av)) & ((!me) | q1);
Por si aún os sigue interesando, he vuelto a realizar el ejemplo con los menús que había hecho anteriormente. Bueno, no está tan "currado" como el otro que tenía, pero ilustra muy bien, el funcionamiento que yo os había comentado.
Antes de nada, comentar que quizás no es la mejor forma de hacer un codigo muy optimizado (por el uso de globales, etc...) pero yo recuerdo haberlo hecho así por que se me imponía la codicion de usar las interrupciones en el portb. También se puede optimizar más escribiendo solo el asterisco en lugar de todas los strings, pero como ejemplo sirve....
No está muy comentado, pero creo que se entiende muy bien.
Otra cosilla, los menus no es que tengan mucho sentido (jejej) solo es un ejemplo.....
Está compilado con la version 3.206 y ocupa un 12%rom y 9%ram, para un 16f876a, creo que con un 18 apenas ocuparía....
Si queréis también tengo el fichero para simularlo en Proteus, aunque no lo subo al almacen porque no tengo nivel para subirlo, si queréis os lo paso, aunque es un esquema muy sencillo (lcd, pic y 4 pulsadores).
****************************************************
Codigo:
#include <16F876A.h>
#use delay(clock=4000000)
#include <lcd_modificado_trelles.c>
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD
#byte port_b=6
static int tecla;
////////////////////////////////////////////////////////////////////////////////
// Prototipos de las funciones
//
////////////////////////////////////////////////////////////////////////////////
void submenu(void);
void configuracion(void);
void visualizacion(void);
///////////////////////////////////////////////////////////////////////////////
// RUTINA DE INTERRUPCION POR TECLADO EN PINES RB4 A RB7
// DETECTAMOS TECLA PULSADA
///////////////////////////////////////////////////////////////////////////////
#INT_RB
void tecla_pulsada(void)
{
delay_ms(20); //esperamos para evitar rebotes
if(!(port_b^0xF0))
return; //si se produce al soltar la tecla salimos de la interrupcion
//asignacion de tecla pulsada
if((!input(PIN_B7)))
{
tecla=7; //tecla enter asignamos un numero cualquiera p.e.=7
return;
}
if((!input(PIN_B6)))
{
tecla=6; //tecla flecha abajo
return;
}
if((!input(PIN_B5)))
{
tecla=5; //tecla flecha arriba
return;
}
if((!input(PIN_B4)))
{
tecla=4; //tecla menu
return;
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//CUERPO PRINCIPAL DEL PROGRAMA:
//
////////////////////////////////////////////////////////////////////////////////
void main(void)
{
//habilitar interrupciones
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
port_b_pullups(TRUE); //pull-ups activadas en puerto B
lcd_init(); //inicializacion del lcd
while(1)
{
if(tecla==4) //si se pulsa la tecla 4, vamos a los menus
submenu();
lcd_putc("f");
lcd_putc("Esperando..."); //sino se pulsa, seguimos esperando....
delay_ms(800);
}
}
////////////////////////////////////////////////////////////////////////////////
// Tratamiento de los menus....
// Hubiera sido preferible usar la funcion lcd_getc() para detectar
// que opcion está seleccionada, pero ignoro porque no me funciono, en lugar
// de eso uso una variable llamada flagi
////////////////////////////////////////////////////////////////////////////////
void submenu(void)
{
int1 flagi=0;
tecla=0;
//imprimimos la pantalla inicial
lcd_gotoxy(1,1);
lcd_putc("* Configuracion");
lcd_gotoxy(1,2);
lcd_putc(" Visualización");
//escaneamos la pulsacion de las teclas...
while(TRUE)
{
if(tecla==6)
{
tecla=0;
flagi=1;
lcd_putc("f");
lcd_gotoxy(1,1);
lcd_putc(" Configuracion");
lcd_gotoxy(1,2);
lcd_putc("* Visualización");
}
if(tecla==5)
{
tecla=0;
flagi=0;
lcd_putc("f");
lcd_gotoxy(1,1);
lcd_putc("* Configuracion");
lcd_gotoxy(1,2);
lcd_putc(" Visualización");
}
if(tecla==7)
{
tecla=0;
if(flagi==0)
configuracion(); //segun la opcion seleccionada (flagi) accedemos a uno u otro submenu....
else
visualizacion();
}
if(tecla==4)
{
tecla=0; //si se pulsa de nuevo la tecla menu, se vuelve a la pantalla principal...
return;
}
};
}
////////////////////////////////////////////////////////////////////////////////
// Submenu de configuracion
//
///////////////////////////////////////////////////////////////////////////////
void configuracion(void)
{
tecla=0;
lcd_putc("f");
lcd_gotoxy(1,1);
lcd_putc("* Reloj");
lcd_gotoxy(1,2);
lcd_putc(" Sensor");
while(tecla!=4)
{
if(tecla==6)
{
tecla=0;
lcd_putc("f");
lcd_gotoxy(1,1);
lcd_putc(" Reloj");
lcd_gotoxy(1,2);
lcd_putc("* Sensor");
}
if(tecla==5)
{
tecla=0;
lcd_putc("f");
lcd_gotoxy(1,1);
lcd_putc("* Reloj");
lcd_gotoxy(1,2);
lcd_putc(" Sensor");
}
};
tecla=5; //tecla=5 se vuelve al menú superior.....
return;
}
void visualizacion(void)
{
tecla=0;
lcd_putc("f");
lcd_gotoxy(1,1);
lcd_putc("* Weee");
lcd_gotoxy(1,2);
lcd_putc(" Wooo");
while(tecla!=4)
{
if(tecla==6)
{
tecla=0;
lcd_putc("f");
lcd_gotoxy(1,1);
lcd_putc(" Weee");
lcd_gotoxy(1,2);
lcd_putc("* Wooo");
}
if(tecla==5)
{
tecla=0;
lcd_putc("f");
lcd_gotoxy(1,1);
lcd_putc("* Weee");
lcd_gotoxy(1,2);
lcd_putc(" Wooo");
}
};
tecla=5; //tecla=5 se vuelve al menú superior.....
return;
}
Saludos.
Apartir del modelo de oshow y con alguna que otra modificacion, por finnn!!! he conseguido un menú mas menos para lo que necesito, aquí os dejo la idea, aunq aún le falta un poco por hacer como vereis... :P
menu.h
Codigo:
void menu(void);
void op1(void);
void op2(void);
void menu_ajustar_rtc(void);
void menu_ajustar_temporizador(void);
void menu_ajustar_max_y_min(void);
static unsigned int testado;
void menu(void)
{
testado=0;
delay_ms(100);
op1();
op2();
}
void op1(void)
{
lcd_gotoxy(1,1);
lcd_putc("1 Ajustar RTC");
lcd_gotoxy(1,2);
lcd_putc("2 Ajustar T.ON T.OFF");
lcd_gotoxy(1,3);
lcd_putc("3 Ajustar Max y Min ");
lcd_gotoxy(1,4);
lcd_putc("OPCION : ");
}
void op2(void)
{
char i;
for (i=0;i!=255;i++)
{
delay_ms(40);
if (!t_mas){delay_ms(100); testado++; if (testado>3){testado=0;};}
else if (!t_mns){delay_ms(100); testado--; if (testado<0|testado==255){testado=3;};}
lcd_gotoxy(11,4);
printf(lcd_putc,"%u",testado);
if (!t_ok)
{
if (testado==0){return;}
else if (testado==1){lcd_putc("f"); menu_ajustar_rtc();}
else if (testado==2){lcd_putc("f"); menu_ajustar_temporizador();}
else if (testado==3){lcd_putc("f"); menu_ajustar_max_y_min();}
}
if (!t_menu){delay_ms(300);return;}
};
}
void menu_ajustar_rtc(void)
{
testado=0;
lcd_putc("f");
lcd_gotoxy(1,1);
lcd_putc("ajustar RTC");
delay_ms(1000);
op1();
}
void menu_ajustar_temporizador(void)
{
testado=0;
lcd_putc("f");
lcd_gotoxy(1,1);
lcd_putc("ajustar TEMPO");
delay_ms(1000);
op1();
}
void menu_ajustar_max_y_min(void)
{
testado=0;
lcd_putc("f");
lcd_gotoxy(1,1);
lcd_putc("ajustar MAx y Min");
delay_ms(1000);
op1();
}
programa principal
Codigo:
#include <16F876A.h>
#use delay(clock=4000000)
#include <lcd20x4.c>
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD
#use fast_io(B)
#zero_ram
#byte pb =0xF06
#bit t_menu =pb.4 // RB4, pin25
#bit t_mas =pb.5 // RB5, pin26
#bit t_mns =pb.6 // RB6, pin27
#bit t_ok =pb.7 // RB7, pin28
void tecla_sel(void);
#include <menu.h>
void main()
{
// enable_interrupts(INT_RB); //habilitar interrupciones
// enable_interrupts(GLOBAL);
port_b_pullups(TRUE); //pull-ups activadas en puerto B
lcd_init(); //inicializacion del lcd
lcd_putc("f");
lcd_gotoxy(1,1);
lcd_putc("Prueba de MENU");
lcd_gotoxy(1,2);
lcd_putc("PFC Terrario");
delay_ms(500);
while(1)
{
lcd_putc("f");
if(!t_menu)menu();
}
}
Os pongo también una modificacion que he hecho de la libreria lcd.c bueno, la modificacion de trelles... para que funcione con un LCD de 20x4
Codigo:
////////////////////////////////////////////////////////////////////////////
//// LCD_MOD.C ////
//// Driver para módulos LCD microcontrolados ////
//// ////
//// Inspirado en librería CCS ////
//// Adaptado por Fernando Nuño García y Miguel Ángel José Prieto para ////
//// funcionamiento con el LCD integrado en la placa PICDEM-2-PLUS. ////
//// Adaptado por Jaime Fernández-Caro para usar LCD de 20x4 ////
//// ////
//// Funciones definidas ////
//// ////
//// lcd_init() Inicialización,llamar antes de cualquier otra función////
//// ////
//// lcd_putc(c) Muestra c en la posicion siguiente del LCD. ////
//// Caracteres de control: ////
//// f Borra display ////
////
Sitúa cursor al comienzo de la línea 2 ////
//// Retrocede el cursor una posición ////
//// Avanza el cursor una posición ////
//// Retrocede una posición la pantalla visible ////
//// v Avanza una posición la pantalla visible ////
//// ////
//// ////
//// lcd_gotoxy(x,y) Sitúa escritura en posición del LCD ////
//// (posición 1,1: arriba a la izquierda) ////
//// ////
//// lcd_getc(x,y) Devuelve carácter en posición x,y del LCD ////
//// ////
////////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,1997 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
////////////////////////////////////////////////////////////////////////////
// Conexión a 7 pines del MCU: 3 de control / interface de datos de 4 bits:
//
// Líneas de control asignadas
// RC0 enable
// RC1 rw
// RC2 rs
//
// Líneas de Datos
// RB0 D4
// RB1 D5
// RB2 D6
// RB3 D7
//
//
struct lcd_pines_control { // Estructura que se define para facilitar acceso
boolean enable; // y asociarlos a los 3 bits más bajos del PORTC
boolean rw; // asignamos luego a esta estructura el PORTC
boolean rs; // rs (1º) corresponde al menos significativo
boolean nada; // a los pines de control del LCD
int otros:4;
} lcd_control;
struct lcd_pines_datos { // Hacemos lo mismo con esta estructura para el PORTD
int datos:4; // los 4 bits más bajos son los de datos
int no_usados:4;
} lcd_datos;
#byte lcd_control = 7 // Ponemos la estructura entera en el PORTC (registro 7)
#byte trisc = 0x87 // Registro de dirección de datos
#byte lcd_datos = 6 // Lo mismo para los datos, en el PORTD (registro 6)
#byte trisb = 0x86 // Registro de dirección de datos
//Prototipos de las funciones posteriores
void lcd_init();
byte lcd_read_byte();
void lcd_send_nibble(byte n);
void lcd_send_byte(byte address, byte n);
void lcd_gotoxy(byte x, byte y);
void lcd_putc(char c);
char lcd_getc(byte x, byte y);
void lcd_clr_line(char fila);
///////////////////////////////////////////////////////////////////////////////////////////
/// Función que inicializa el LCD, se deberían cambiar bits para cambiar configuracion
///////////////////////////////////////////////////////////////////////////////////////////
void lcd_init() {
byte i;
trisc&=0b11111000; // Asignamos salidas en RC0, RC1 y RC2, resto puerto como estaba
trisb&=0b11110000; // Lo mismo para RB0 a RB3
lcd_control.rs = 0;
lcd_control.rw = 0;
lcd_control.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
lcd_send_byte(0,0b00101000); ///Se envía Function set 0 0 1 DL N F - -
lcd_send_byte(0,0b00001100); ///Se envía Display on/off 0 0 0 0 1 D C B
lcd_send_byte(0,0b00000001); //Se envía Clear Display
lcd_send_byte(0,0b00000110); //Se envía Entry Mode set 0 0 0 0 0 1 I/D S//
// DL: datos 4 bits(0); 8 bits (1) / N: 2 líneas (1); 1 línea (0) / F: 5x10 (1); 5x8 (0)
// D: display on (1); off (0) / C: cursor on (1); off (0) / B: parpadeo pos.cursor (1); no (0)
// I/D: incremento en R/W (1) o decremento (0) / S: acompaña desplaz.display (1); no (0)
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Lee el byte señalado por el puntero, 1º parte alta, 2º parte baja
// Si al llamar a esta función rs=0, devuelve busy flag (+signif.) y dirección actual
/////////////////////////////////////////////////////////////////////////////////////////////
byte lcd_read_byte()
{
byte low,high;
trisc&=0b11111000; //Las señales de control siguen siendo salidas, el resto lo que sean
trisb|=0b00001111; //Las de datos pasan a ser entradas, las demas igual
lcd_control.rw = 1;
delay_cycles(1);
lcd_control.enable = 1;
delay_cycles(1);
high = lcd_datos.datos;
lcd_control.enable = 0;
delay_cycles(1);
lcd_control.enable = 1;
delay_us(1);
low = lcd_datos.datos;
lcd_control.enable = 0;
trisb&=0b11110000; // Dejamos RD0 a RD3 como salidas
return( (high<<4) | low);
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Envía medio byte, los 4 bits más bajos de n
// Necesario poner rs y rw de modo adecuado y entrar con enable=0
/////////////////////////////////////////////////////////////////////////////////////////////
void lcd_send_nibble( byte n )
{
lcd_datos.datos = n;
delay_cycles(1);
lcd_control.enable = 1;
delay_us(2);
lcd_control.enable = 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Envía un byte (n) al registro de instrucciones (si address=0) o reg. de datos (address=1)
// Utiliza lcd_send_nibble(n) enviando primero nibble alto del byte
/////////////////////////////////////////////////////////////////////////////////////////////
void lcd_send_byte( byte address, byte n )
{
lcd_control.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ; //Mientras esté ocupado el LCD, espera
lcd_control.rs = address;
delay_cycles(1);
lcd_control.rw = 0;
delay_cycles(1);
lcd_control.enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0x0F);
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Sitúa el contador de direcciones en la DDRAM (para lectura o escritura posterior)
// x puede ir de 1 a 40, posición dentro de una línea (16 visibles)
// y puede ser 1 (línea 1) o 2 (línea 2)
/////////////////////////////////////////////////////////////////////////////////////////////
void lcd_gotoxy( byte x, byte y)
{
byte posicion;
switch(y)
{
case 1 : posicion=0x80;break;
case 2 : posicion=0xc0;break;
case 3 : posicion=0x94;break;
case 4 : posicion=0xd4;break;
}
posicion+=x-1;
lcd_send_byte(0,0x80|posicion); //Las direcciones de la DDRAM empiezan por 1xxxxxxx
}
////////////////////////////////////////////////////////////////////////////////////////////
// Envía un carácter c a la DDRAM del LCD, también algunos caracteres de control
////////////////////////////////////////////////////////////////////////////////////////////
void lcd_putc( char c)
{
switch (c)
{
case "f" : lcd_send_byte(0,1); //Limpia la pantalla
delay_ms(2);
break;
case "
" : lcd_gotoxy(1,2); //Coloca puntero en 1ª posicion de la 2ª línea
break;
case "" : lcd_send_byte(0,0x10); //Retrocede una posición el cursor
break;
case " " : lcd_send_byte(0,0x14); //Avanza una posición el cursor
break;
case "" : lcd_send_byte(0,0x18); //Retrocede una posición la pantalla visible
break;
case "v" : lcd_send_byte(0,0x1C); //Avanza una posición la pantalla visible
break;
default : lcd_send_byte(1,c); //Envía caracter a DDRAM,
break; //Si es una tira, los envía todos uno a uno
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Devuelve el carácter situado en la posición x,y de la DDRAM
///////////////////////////////////////////////////////////////////////////////////////////
char lcd_getc( byte x, byte y) {
char value;
lcd_gotoxy(x,y);
lcd_control.rs=1;
value = lcd_read_byte();
lcd_control.rs=0;
return(value);
}
////////////////////////////////////////////////////////////////////////////////////
// Limpia la linea correspondiente y se situa al principio de la misma //
////////////////////////////////////////////////////////////////////////////////////
void lcd_clr_line(char fila)
{
int j;
lcd_gotoxy(1,fila);
for (j=0;j<40;j++) lcd_putc(" ");
lcd_gotoxy(1,fila);
}
Salu2!!:s)
ok oshow... aklarado keda :D ;)
pic-chi, te explico la parte que creo q es mas "filosofica" del programa :P
Codigo:
void menu(void)
{
testado=0;
delay_ms(100); // evitamos revotes
op1();
op2();
}
void op1(void) // función encargada de mostrar el menú
{
lcd_gotoxy(1,1);
lcd_putc("1 Ajustar RTC");
lcd_gotoxy(1,2);
lcd_putc("2 Ajustar T.ON T.OFF");
lcd_gotoxy(1,3);
lcd_putc("3 Ajustar Max y Min ");
lcd_gotoxy(1,4);
lcd_putc("OPCION : ");
}
void op2(void) // funcion encargada de detectar y seleccionar opcion
{
char i;
for (i=0;i!=255;i++) // solo estaremos un tiempo X dentro del menú
{
delay_ms(40); // X será: 255·0,04 = 10seg
if (!t_mas){delay_ms(100); testado++; if (testado>3){testado=0;};} // si se pulsa la tecla mas, y testado es mayor que 3, este vuelve a ser 0, esto es para que el menu solo avance entre 0 y 3
else if (!t_mns){delay_ms(100); testado--; if (testado<0|testado==255){testado=3;};} // lo mismo para la tecla menos, solo que se añade tambien la condicion de que el número sea 255, ya que si estamos en cero y retrocedemos no vamos al -1 sino a 255 ;)
lcd_gotoxy(11,4);
printf(lcd_putc,"%u",testado);
if (!t_ok) // al pulsar la tecla OK...
{
if (testado==0){return;} // Comrobamos lo que vale testado y vamos a ese submenú
else if (testado==1){lcd_putc("f"); menu_ajustar_rtc();}
else if (testado==2){lcd_putc("f"); menu_ajustar_temporizador();}
else if (testado==3){lcd_putc("f"); menu_ajustar_max_y_min();}
}
if (!t_menu){delay_ms(300);return;} // estando dentro del menu si se pulsa la tecla menu se sale de el
};
}
Así a grandes rasgos:
Pulsamos la tecla menu estando en la pantalla inicial, y nos muesta el menú, la variable testado estará a 0, si pulsamos OK saldremos del menú, también podremos salir del menú pulsando la tecla menu para cualquier valor de testado. Dentro del menú solo tendremos 10 segundos para seleccionar una opcion, pasado ese tiempo volvemos a la pantalla inicial. Una vez configurados los distintos submenus volveremos a la pantalla inicial, por eso acaban por op1();
Bueno creo que mas o menos se entiende no?
Por cierto usa un 11% de rom y un 4% de ram
Salu2! ;)
La explicación de las diversas funciones incluidas en la librería para el control de la LCD, la tienes al principio de esta:
Codigo:
lcd_init() Inicialización,llamar antes de cualquier otra función////
//// ////
//// lcd_putc(c) Muestra c en la posicion siguiente del LCD. ////
//// Caracteres de control: ////
//// f Borra display ////
////
Sitúa cursor al comienzo de la línea 2 ////
//// Retrocede el cursor una posición ////
//// Avanza el cursor una posición ////
//// Retrocede una posición la pantalla visible ////
//// v Avanza una posición la pantalla visible ////
//// ////
//// ////
//// lcd_gotoxy(x,y) Sitúa escritura en posición del LCD ////
//// (posición 1,1: arriba a la izquierda) ////
//// ////
//// lcd_getc(x,y) Devuelve carácter en posición x,y del LCD
Te explico lcd_gotoxy(x,y) con un ejemplo:
Quieres escribir Pepe en la línea primera de la LCD (y), posición 10 (x):
lcd_gotoxy(10,1);
lcd_putc("Pepe"
;
El librito ese, ¿está en inglés?