CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

menu system for LCD

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mesuty
Guest







menu system for LCD
PostPosted: Wed Jul 20, 2005 8:13 am     Reply with quote

Hi friends;

I inspected the existing codes in the forum. My problem is to implement a menu system on a 2 line LCD. I have 4 buttons on circuit. By pressing two predefined buttons , the menu must appear. Menu has nearly 50 sub items in 4 sub groups. Most of the sub items deals with entering an float number through those 4 keys.

any kind of idea / help is appreciated.
Note : I inspected the function pointer based LCD algorithm , though could not apply to the problem.
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Wed Jul 20, 2005 8:31 am     Reply with quote

I like the simple method. Use the up down keys to select menu items. and the left right keys to increment or decrement. The trick is to inc/dec on a fixed time interval as the key is held down and increase the amount of the inc/dec while the key is pressed. Use one line to display the paramater name and the other paramater value. While this does mean scrolling through all the menu items you dont need to adjust its very simple and eazy to understand. It's also simple to explane to a new user where sub-menus are more dificult.
Salenko



Joined: 08 Sep 2008
Posts: 84

View user's profile Send private message

PostPosted: Sun Nov 02, 2008 12:07 pm     Reply with quote

Neutone wrote:
I like the simple method. Use the up down keys to select menu items. and the left right keys to increment or decrement. The trick is to inc/dec on a fixed time interval as the key is held down and increase the amount of the inc/dec while the key is pressed. Use one line to display the paramater name and the other paramater value. While this does mean scrolling through all the menu items you dont need to adjust its very simple and eazy to understand. It's also simple to explane to a new user where sub-menus are more dificult.


hi Neutone,
I´m nearly in the same situation, I have to display 4 lines in my Menu ,I have a 2 lines LCD, and when I use my code (below), the lines are over written .

Code:

lcd_putc("1-CHANGE A");
lcd_gotoxy(1,2);
lcd_putc("2-CHANGE B");
lcd_gotoxy(1,3);
lcd_putc("3-CHANGE C");
lcd_gotoxy(1,4);
lcd_putc("4-QUIT");


I changed
Code:
lcd_gotoxy(1,2);

with
Code:
lcd_putc("\n");


but the result is the same, what should I do to display the 4 lines in my 2-lines LCD ,(I mean the LCD will be as a window to my Menu, then I would be able to scroll it)

thanks for any help.
Ttelmah
Guest







PostPosted: Mon Nov 03, 2008 5:26 am     Reply with quote

Code:

int8 menu(int8 max) {
   //Routine to toggle between two displayed prompts, and allow one to be
   //selected. Returns selected number.
   int1 flag;
   int8 selected;
   int8 display_from;
   int1 toggle;
   //Start at the top of the list
   selected=display_from=0;
   toggle=true;
   flag=true;
   //Use zero relative for maximum
   max--;
   sys_tick=0;
   LCD_PUTC('\f');
   //Wait for key to be released
   while (ENTER==0) ;
   while (flag) {
      while (sys_tick) ;
      sys_tick=1;
      if (toggle) {
         LCD_GOTOXY(1,1);
         printf(LCD_PUTC,"%s",&prompt[display_from][0]);
         LCD_GOTOXY(1,2);
         printf(LCD_PUTC,"%s",&prompt[display_from+1][0]);
         toggle=false;
      }
      else {
         if (selected==display_from) {
            LCD_GOTOXY(1,1);
            LCD_PUTC("                ");
            LCD_GOTOXY(1,2);
            printf(LCD_PUTC,"%s",&prompt[display_from+1][0]);
         }
         else {
            LCD_GOTOXY(1,1);
            printf(LCD_PUTC,"%s",&prompt[display_from][0]);
            LCD_GOTOXY(1,2);
            LCD_PUTC("                ");
         }
         toggle=true;
      }
      if (UP==0) {
         if (selected>0) --selected;
         if (selected<display_from) --display_from;
      }
      if (DOWN==0) {
         if (selected<max) ++selected;
         if (selected>(display_from+1)) ++display_from;
      }
      if (ENTER==0) flag=false;
   }
   return selected;
}

This is cut directly out of a project of mine, and requires several things.
First, there has to be an interrupt driven 'clock' running, which clears 'sys_tick' at intervals. On my code, it is about 2/3rd second.
Second three keys, called 'UP', 'DOWN', and 'ENTER', which pull their inputs low, when pushed. The bit defines for these need to be present. If you are using 'standard_io', then you will need to change the tests for these, to use 'input_bit', rather than just reading them.
An array of text 'labels' for the lines, called 'prompt'. In my case defined as:

char prompt[6][17];

You load this with the menu lines you want, so:
Code:

      strcpy(&prompt[0][0],"FIRST MENU ");
      strcpy(&prompt[1][0],"SECOND MENU ");
      strcpy(&prompt[2][0],"THIRD MENU");
      switch(menu(3)) {


and call the 'menu' function, with the number of entries to use (as shown in the switch above - three for the example shown). The function returns the line selected. Remember 16 characters per entry max, and 6 entries max with the array as shown.

The display starts showing the top two entries, with the upper one flashing as the speed determined by the interrupt already mentioned. 'down', flashes the second line'. Hit down again, and the next two lines are displayed, with the bottom one flashing. Whichever line is flashing when the 'enter' key is pushed, is the number returned.

Hopefully it gives you some ideas.

Best Wishes
Salenko



Joined: 08 Sep 2008
Posts: 84

View user's profile Send private message

PostPosted: Mon Nov 03, 2008 2:21 pm     Reply with quote

hi,

thanks would be light to express my gratitude Mr Ttelmah, in two words : great person you are.



Quote:

Second three keys, called 'UP', 'DOWN', and 'ENTER', which pull their inputs low, when pushed. The bit defines for these need to be present. If you are using 'standard_io', then you will need to change the tests for these, to use 'input_bit', rather than just reading them.


I assume that you are using FAST_IO(),

I made a small program to test the code (below), I got this error

Quote:

Not enough RAM for all variables


so I reduced prompt[6][17] to prompt[6][16] and the program was compiled without errors (but with warnings of conditions always false).





Code:
#include <16F876.h>

#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 20000000)
#use rs232 (baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,ERRORS,bits=8)

#include "flex_lcd.c"

#byte PortB = 6   

#use FAST_IO(B)


//=====pins configuration==========

#define  UP       PIN_B5
#define  DOWN     PIN_B7
#define  ENTER    PIN_B6




//========Variables=======

int1 sys_tick;    //bit
     
char prompt[6][16];

//=======TIMER==========



#int_timer0
void timer0_isr ( ) 
{

set_timer1(69);

sys_tick=0;

}


//=============Procedures==============

void initialisation()

{
lcd_init();
lcd_putc("READY...\@");
}

int8 menu(int8 max) {
   //Routine to toggle between two displayed prompts, and allow one to be
   //selected. Returns selected number.
   int1 flag;
   int8 selected;
   int8 display_from;
   int1 toggle;
   //Start at the top of the list
   selected=display_from=0;
   toggle=true;
   flag=true;
   //Use zero relative for maximum
   max--;
   sys_tick=0;
   LCD_PUTC('\f');
   //Wait for key to be released
   while (ENTER==0) ;
   while (flag) {
      while (sys_tick) ;
      sys_tick=1;
      if (toggle) {
         LCD_GOTOXY(1,1);
         printf(LCD_PUTC,"%s",&prompt[display_from][0]);
         LCD_GOTOXY(1,2);
         printf(LCD_PUTC,"%s",&prompt[display_from+1][0]);
         toggle=false;
      }
      else {
         if (selected==display_from) {
            LCD_GOTOXY(1,1);
            LCD_PUTC("                ");
            LCD_GOTOXY(1,2);
            printf(LCD_PUTC,"%s",&prompt[display_from+1][0]);
         }
         else {
            LCD_GOTOXY(1,1);
            printf(LCD_PUTC,"%s",&prompt[display_from][0]);
            LCD_GOTOXY(1,2);
            LCD_PUTC("                ");
         }
         toggle=true;
      }
      if (UP==0) {
         if (selected>0) --selected;
         if (selected<display_from) --display_from;
      }
      if (DOWN==0) {
         if (selected<max) ++selected;
         if (selected>(display_from+1)) ++display_from;
      }
      if (ENTER==0) flag=false;
   }
   return selected;
}







the main:


Code:



//=========PROGRAM============



void main()
{

//char cb;

set_tris_b(0xE0);



   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);

   enable_interrupts(INT_TIMER1);
   
    disable_interrupts(INT_EXT);
    disable_interrupts(INT_RB);
 
 
   

initialisation();


 strcpy(&prompt[0][0],"FIRST MENU");
 strcpy(&prompt[1][0],"SECOND MENU");
 strcpy(&prompt[2][0],"THIRD MENU");
 
     

while(1)
 
{

int a;
 
a=menu(3);


}
 
 
 
 
}

 
 



in simulation, I did not get flashing lines and scrolling menu, I just got those fixed two lines.



Last edited by Salenko on Mon Nov 03, 2008 11:52 pm; edited 1 time in total
Ttelmah
Guest







PostPosted: Mon Nov 03, 2008 4:07 pm     Reply with quote

You are missing the point about the note about the pins.
If you are using the standard pin defines, you need to use the CCS input instructions, not just defines for the pin numbers.
You could (for instance), do this:
Code:

#define UP input_bit(PIN_B5)
#define DOWN input_bit(PIN_B7)
#define ENTER input_bit(PIN_B6)

Otherwise, the defines need to be _bit_ defines like:
Code:

#ifdef __PCH__
   #byte PORTB=0xF81
#else
   #byte PORTB=0x6
#endif
#bit UP=PORTB.5
#bit DOWN=PORTB.7
#bit ENTER=PORTB.6

The pin numbers themselves will never equal zero, which is why the warnings...
With the bit defines, you need to either just set the TRIS before calling the function, or use FAST_IO.
Beware of going down to 16 characters per row in the array. remember that a 16 character string needs 17 characters. Reduce the number of rows, unless you need this many in the menu.
You are interrupting on timer1, but programming up timer0?.
I'd suggest:
Code:

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);
   enable_interrupts(INT_TIMER0);
   //Will give just over half second for the tick.


#int_timer0
void timer0_isr ( )  {
  sys_tick=0;
}

I actually use a number for sys_tick, in my own code, since I can program timeout's for lots of other code using it. However as shown should be fine.

Best Wishes
Salenko



Joined: 08 Sep 2008
Posts: 84

View user's profile Send private message

PostPosted: Tue Nov 04, 2008 8:16 am     Reply with quote

hi Ttelmah, thank you for answering me again,

I've made the following changements/corrections:

Code:

#define UP      input_state(PIN_B5)  //*
#define DOWN    input_state(PIN_B7)
#define ENTER   input_state(PIN_B6)

main()
{
set_tris_b(0xE0);
}


*:I did not use the input_bit() function cause it is not defined in my compiler (PCM 4.057).


Quote:

Beware of going down to 16 characters per row in the array. remember that a 16 character string needs 17 characters. Reduce the number of rows, unless you need this many in the menu.


I did so:

Code:
char prompt[5][17];


should I make a changement in your code if I have to add another Menu line, (for instance,FOURTH MENU) in addition to adding :

Code:
strcpy(&prompt[3][0],"FOURTH MENU");




setting timer1 insted of timer0 was a careless mistake, this will give 600ms for the tick, here is the correct timer isr:

Code:

#int_timer0
void timer0_isr ( ) 
{
set_timer0(69);
sys_tick=0;
}




Code:

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);
   enable_interrupts(INT_TIMER0);
   //Will give just over half second for the tick.
#int_timer0
void timer0_isr ( )  {
  sys_tick=0;
}


by the way, I'd like to know, how the interruption time is set in your code without the set_timer0() in the routine ?



when simulating, every line below the flashing line has a curser moving through it (for instance, FIRST MENU and SECOND MENU in the beginning), I don't know from where this came ? , did you get this ?






last question:
how should I deal with this code if I like to have a sub menu when I select one of the lines (and get an QUIT on it to return to the main Menu).

just an idea ...


and thank you a lot in advance.
crystal_lattice



Joined: 13 Jun 2006
Posts: 164

View user's profile Send private message

LCD MENU SYTEM
PostPosted: Wed Nov 05, 2008 7:17 am     Reply with quote

i've just presented my project yesterday (after completing a 3hour examination... and more than a month's worth of agonising documentation...) and was thinking to post my version of a LCD menu system in the code section in the near future.

I used the 16F886 as the touch key pad interface and this communicates with a 18LF4620 which is running the LCD menu. The keypad only had 4 buttons, UP,DOWN, ENTER and ESCAPE.

I did not have to enter any values but it enabled me to execute various functions like a calibration sequence and it also enables the user to adjust the date/time of the RTC using the UP/DOWN arrows. The whole menu was designed around a switch statement "state machine" and contained several sub menus.

During the next few days/week(s) i will try and strip it down and include a useful demo which i will post in the code section. It is not the most elegant menu system, but i gets the job done and is very simple to maintain.
Salenko



Joined: 08 Sep 2008
Posts: 84

View user's profile Send private message

Re: LCD MENU SYTEM
PostPosted: Thu Nov 06, 2008 1:08 am     Reply with quote

crystal_lattice wrote:
i've just presented my project yesterday (after completing a 3hour examination... and more than a month's worth of agonising documentation...) and was thinking to post my version of a LCD menu system in the code section in the near future.

I used the 16F886 as the touch key pad interface and this communicates with a 18LF4620 which is running the LCD menu. The keypad only had 4 buttons, UP,DOWN, ENTER and ESCAPE.

I did not have to enter any values but it enabled me to execute various functions like a calibration sequence and it also enables the user to adjust the date/time of the RTC using the UP/DOWN arrows. The whole menu was designed around a switch statement "state machine" and contained several sub menus.

During the next few days/week(s) i will try and strip it down and include a useful demo which i will post in the code section. It is not the most elegant menu system, but i gets the job done and is very simple to maintain.


thanks

you're welcome.
Ttelmah
Guest







PostPosted: Thu Nov 06, 2008 3:50 am     Reply with quote

As a comment 'back' to the question about interrupt time, I'm just letting the timer 'free run'.
Timers interrupt whenever they 'wrap' at the end of their count, back to zero. You can set a timer 'to' a value, to accelerate this, but unless you 'need' an exact time interval, you can just use the ntural wrap.
So, in the example, the timer is a 16bit timer (wraps every 65536 counts), fed off the prescaler of /8, which counts in Fosc/4 intervals. So the timer will interrupt every:

(4000000)/(4*8*65536)times per second

1.907times per second. Just over half a second intervals.
In fact, setting timers 'to' values, is always dangerous. The problem is that if the timer is being fed from a clock faster than perhaps a few dozen instruction times, there is always the potential for the clock to have already counted some cycles, before you reach the interrupt routine. Hence timings _will_ be inaccurate. Alternative is to read the timer, and add an offset to the value. Better, but still loses any counts that happen between the read, and the write. Also, on most timers, the prescaler is reset, when it's value is written, leading to another error...

Generally then, I'll always let timers free run, or use the timer2, which on the bigger PICs, has a hardware reset.

Best Wishes
soulraven



Joined: 08 Feb 2009
Posts: 72
Location: campulung muscel

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Mon Apr 06, 2009 10:04 am     Reply with quote

i have a problem with the code.....

Code:
*** Error 28 "main.c" Line 27(28,29): Expecting an identifier
*** Error 43 "main.c" Line 27(39,40): Expecting a declaration
*** Error 43 "main.c" Line 27(39,40): Expecting a declaration
*** Error 43 "main.c" Line 27(40,41): Expecting a declaration
*** Error 28 "main.c" Line 28(29,30): Expecting an identifier
*** Error 43 "main.c" Line 28(30,31): Expecting a declaration
      6 Errors,  0 Warnings.
Halting build on first failure as requested.
BUILD FAILED: Mon Apr 06 18:50:32 2009


http://s4.transfer.ro/storage/Calculator-4a91f.zip
colesha



Joined: 09 Jan 2012
Posts: 45

View user's profile Send private message Send e-mail

PostPosted: Mon Feb 10, 2020 1:53 pm     Reply with quote

Ttelmah wrote:
You are missing the point about the note about the pins.
If you are using the standard pin defines, you need to use the CCS input instructions, not just defines for the pin numbers.
You could (for instance), do this:
Code:

#define UP input_bit(PIN_B5)
#define DOWN input_bit(PIN_B7)
#define ENTER input_bit(PIN_B6)

Otherwise, the defines need to be _bit_ defines like:
Code:

#ifdef __PCH__
   #byte PORTB=0xF81
#else
   #byte PORTB=0x6
#endif
#bit UP=PORTB.5
#bit DOWN=PORTB.7
#bit ENTER=PORTB.6

The pin numbers themselves will never equal zero, which is why the warnings...
With the bit defines, you need to either just set the TRIS before calling the function, or use FAST_IO.
Beware of going down to 16 characters per row in the array. remember that a 16 character string needs 17 characters. Reduce the number of rows, unless you need this many in the menu.
You are interrupting on timer1, but programming up timer0?.
I'd suggest:
Code:

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);
   enable_interrupts(INT_TIMER0);
   //Will give just over half second for the tick.


#int_timer0
void timer0_isr ( )  {
  sys_tick=0;
}

I actually use a number for sys_tick, in my own code, since I can program timeout's for lots of other code using it. However as shown should be fine.

Best Wishes

Hello, kindly help me with working code for a menu with up/down, enter and esc push buttons .

Thanks
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group