• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Scroll Menu on 20x4 LCD

drkidd22

Member
Hello,

I'm using a 20x4 serial LCD to display different states of some LEDs. I have created the main menu and I'm able to display it on the screen with no problem. What I want to do next is to be able to scroll, DOWN/UP, and hightlight the lines while doing this. There is also a ENTER so that when the user presses the button it goes into the sub-menu of the higlighted screen. Any info/help with this will be appreciated. I'm Using a PIC24FJxxxx with a Matrix Orbital LCD
 
Last edited:

drkidd22

Member
I looked on your threads and the one that comes close to what I'm building is the security system you built. All the code is in ASM, I'm not that good with ASM. It would be easier for me in C.
 

drkidd22

Member
This is what menu in C looks like. I have a little trouble trying to understand the stuff on the thread you had. The issue with me is trying to translate this stuff into MPLAB and program the chip with it.

With Button (UP/DOWN) user will high light one of the main menu options and then with enter they will go into the sub-menu. I'm working on MPLAB with this and trying to make it work.

Code:
#include <stdio.h>
#include <stdlib.h>

void power(void);
void security(void);
void status(void);

int main()
{

int mSelec;

const char mMenu[]   =  ("Main Menu\n");
const char pManage[] =  ("Power Management\n");     //case 1
const char sSystem[] =  ("Security System\n");      //case 2
const char sStatus[] =  ("System Status\n");        //case 3

printf(mMenu);
printf(pManage);
printf(sSystem);
printf(sStatus);

scanf("%d",&mSelec);

switch (mSelec)
{
case 1:
  power();
break;

case 2:
  securtiy();
break;

case 3:
  status();
break;
}
  return 0;
}

/******************Sub-Menus********************************
These are the sub-menus to be displayed on the LCD depending
of the selection made on the main menu.
**********************************************************/

void power (void)
{
  printf("Lights\n");
  printf("Pumps\n");
  printf("Doors\n");

}

void security (void)
{
  printf("Windows\n");
  printf("Doors\n");
  printf("Strobe/Siren\n");
  
}

void status (void)
{
  printf("Lights\n");
  printf("Doors\n");
  printf("Security System\n");
  
}
 

Noggin

Member
I think I'd try something along these lines...

Code:
const char main_menu[NBR_MAIN_MENU_ITEMS][LCD_CHAR_LEN + 10]=
{
   "Main Menu", 
   "Power Management",
   "Security System",
   "System Status",
   "Option 5",
   "Option 6",
   "Option 7",
   "Option 8",
   "Option 9",
   "Option 10",
};

enum main_menu_options
{
   MAIN_MENU=0,
   POWER_MANAGEMENT,
   SECURITY_SYSTEM,
   SYSTEM_STATUS,
   OPTION5,
   OPTION6,
   OPTION7,
   OPTION8,
   OPTION9,
   OPTION10,
   NBR_MENU_OPTIONS,
};
Uint8 main_menu_selected_item = POWER_MANAGEMENT;
Uint8 key_status;
Uint8 app_state;

void main( void )
{
   Init_Sync_Timer();

   while (1)
   {
      Sync_To_Real_Time();
      Service_Application();
      Service_Keyboard();
      Service_Display();
   }
}

void Init_Sync_Timer( void )
{
#define MAIN_LOOP_MS        5   
   // Init a timer to expire in 5mS intervals
   // Do not enable the timer's interrupt
}

void Sync_To_Real_Time( void )
{
   while (timer interrupt flag is not set)
      ; // just wait

   clear timer interrupt flag
}

void Service_Keyboard( void )
{
static Uint8 last_key_status;
Uint8 raw_key_status;

   raw_key_status = keyboard input;
   if (last_key_status != raw_key_status)
   {
      key_status = raw_key_status;
   }
   else
   {
      key_status = NO_BUTTONS_PRESSED;
   }

   last_key_status = raw_key_status;
}

void Service_Application( void )
{
#define SPLASH_SCREEN_DELAY         3000/MAIN_LOOP_DELAY   // 3 seconds
static Uint8 delay_timer = 0;

   switch (app_state)
   {
      case APP_SPLASH_SCREN:
         if ((++delay_timer == SPLASH_SCREEN_DELAY) || (key_status == KEY_ENTER))
         {
            delay_timer = 0;
            app_state = APP_MAIN_MENU;
         }
         break;

      case APP_MAIN_MENU:
         switch (key_status)
         {
             case KEY_UP:
                main_menu_selected_item--;
                if (main_menu_selected_item == 0)
                   main_menu_selected_item = NBR_MENU_ITEMS - 1;
                break;
          
             case KEY_DOWN:
                main_menu_selected_item++;
                if (main_menu_selected_item == NBR_MENU_ITEMS)
                   main_menu_selected_item = 1;
                break;

             case KEY_ENTER:
                switch (main_menu_selected_item)
                {
                   case POWER_MANAGEMENT:
                      app_state = APP_POWER_MANAGEMENT;
                      break;

                   case OPTION5:
                      Some_Function();
                      break;
                }
      }
}

void Service_Display( void )
{
   switch (app_state)
   {
      case APP_SPLASH_SCREEN:
         Display_Splash_Screen();
         break;

      case APP_MAIN_MENU:
         Display_Main_Menu();
         break;
  
       case APP_POWER_MANAGEMENT:
         Display_Power_Management_Menu();
         break;
      }
}

void Display_Splash_Screen( void )
{
   printf("Application title\n");
   printf("Date of Build\n");
   printf("Firmware Version Nbr\n");
   printf("Author\n");
}

void Display_Main_Menu( void )
{
   printf("%s\n", main_menu[0] );

   if (main_menu_selected_item == 1)
   {
      printf("> %s\n", main_menu[1]);
      printf("  %s\n", main_menu[2];
      printf("  %s\n", main_menu[3];
   }
   else if (main_menu_selected_item == NBR_MENU_OPTIONS - 1)
   {
      printf("  %s\n", main_menu[NBR_MENU_OPTIONS-3]);
      printf("  %s\n", main_menu[NBR_MENU_OPTIONS-2];
      printf("> %s\n", main_menu[NBR_MENU_OPTIONS-1];
   }
   else
   {
      printf("  %s\n", main_menu[main_menu_selected_item-1]);
      printf("> %s\n", main_menu[main_menu_selected_item];
      printf("  %s\n", main_menu[main_menu_selected_item+1];
   }
}
Hopefully it works, I just made it up and it is 100% untested.

Edit: The printf's to the display are probably fairly slow. If it causes the system to drag, you can change the sync timer to something more like 10 or 20 ms and/or add the following code to the display servicing routine at the very beginning

#define DISPLAY_UPDATE_DELAY 100/MAIN_LOOP_MS // 100 mS - Update the display 10 times per second
static Uint8 display_update_timer = 0;

if (++display_update_timer < DISPLAY_UPDATE_DELAY)
return; // don't update the display yet

display_update_timer = 0;
 
Last edited:

drkidd22

Member
Hey thanks. That looks pretty good. I will try it out when I get home later. For printing to the screen I think I might change that and write directly to the UART2 character by character and keep looking at the UART2 to see if it's busy.

I really appreciate that.
 
Last edited:

drkidd22

Member
I got it working man. Thanks a lot. Had to read up on C structures a little bit. I had never used them before, but the LCD now displays the Main Menu option on and I can scroll thru the main options.

Now I'm looking into how I can "highlight" a line on my LCD. I have a MatrixOrbital LK204-25

Thanks Alot.
-Jose
 

Latest threads

EE World Online Articles

Loading

 
Top