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...

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)