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 CCS Technical Support

Low power lcd with flex driver
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Sam_40



Joined: 07 Jan 2015
Posts: 127

View user's profile Send private message

Low power lcd with flex driver
PostPosted: Sun Mar 01, 2015 12:15 pm     Reply with quote

http://www.ccsinfo.com/forum/viewtopic.php?t=24661
PCM programmer,
Thanks for sharing this driver, I had used it in a project in the past and it works great!
I want to use 16x2 hd44780 LCD in a timer project. Using the Timer1 to generate the RTC at 32768Hz to save power and components. I have three questions:

1- Does the hd44780 LCD operate if the PIC running at 32768Hz or does the hd44780 need higher PIC clock?

2- I want to turn the LCD OFF during operation and just turn it on during time setup to save power. I am thinking to connect the LCD as follow:
Code:

PIN     SYMBOL  FUNCTION                Connection to the PIC
===     ======  ========                =====================   
1       Vss     GND                     GND
2       Vdd     + 5V                    RA5 (direct connection!)
3       Vo      Contrast Adjustment     Connected to +5 through 1K resistor
4       RS H/L  Register Select Signal  RC7
5       R/W H/L Read/Write Signal       GND
6       E       Enable Signal           RC6
7       DB0     Data Bus Line           GND
8       DB1     Data Bus Line           GND
9       DB2     Data Bus Line           GND
10      DB3     Data Bus Line           GND
11      DB4     Data Bus Line           RC2
12      DB5     Data Bus Line           RC3
13      DB6     Data Bus Line           RC4
14      DB7     Data Bus Line           RC5
15      LED+    LCD Back Light          Not used
16      LED-    LCD Back Light          Not used

Turn RA5 ON during setup and OFF during operation. Would that works?
3- Do I need to change the flex_lcd.c code to put the LCD in the power saving mode? What do you suggest as a test program for the modified Flex driver?

Thanks,
Sam
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Mar 01, 2015 12:53 pm     Reply with quote

re: 1)...LCD module has it's own internal clock, so PIC 'speed' isn't a factor.. Check the LCD module datasheet..as there are 'timing' concerns about I/O.

2) _might_ work, though NOT recommended. Use that PIC I/O pin to control a 'high side switch',as Vout of the I/O pin will NOT be 5 volts. check the PIC data sheet... ( electrical specs...)

3) LCD driver does NOT have to be changed, simply create you own 'LCD_power_control' function. Simple on/off or high /low to appropriate I/O pin. Read the CCS manual for info about controlling I/O pins.

As a general comment, you need to do a 'power calculation' study. Running a PIC at 32KHz will not save energy in the long run. You're better to run 'high speed' when awake, then 'slow speed' when asleep.
Microchip has a few application notes about this, well worth reading!!
Also read the LCD datasheet, there are a LOT of detail YOU must learn and understand about it's operation with respect to power consumption
This 'study' should take no more than 3 or 4 days of reading and 'pencil and paper' calculations. You don't say which PIC you're using, several 'newer' ones are 'ultra low power '.
Frankly I'd just use 4 AA batteries and an LDO reg. I've had an LCD clock running here for the past 15 years on 2 AA batteries.




Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Sun Mar 01, 2015 1:09 pm     Reply with quote

The one about power/clock is very important to understand. It was covered some weeks ago in a thread, but the key is that the only time to run the CPU at 32K, is if you are leaving it running all the time.

In sleep mode, the power is vastly lower than any speed.

Generally PIC's do the most operations/uW, at speeds like perhaps 1 to 4MHz. Internal oscillators cost less power than crystals etc..
32K, even using the internal oscillator, uses more power per instruction than these faster speeds.

So the most efficient way of using power is to sleep as much as you can, wake the chip, at perhaps 1MHz, do the job, and sleep again
Sam_40



Joined: 07 Jan 2015
Posts: 127

View user's profile Send private message

PostPosted: Sun Mar 01, 2015 2:07 pm     Reply with quote

Temtronic,
The LCD that I have is (Varitronix MDLS 16265B with the hd44780). I used it before with a PIC set for 4Mhz and it works great!
1- The datasheet that I have for the LCD does not show the timing required! So I am using the Hitachi hd44780 datasheet. I am not sure what the value for the LCD clock.
2- Are you suggesting using a transistor to control +5 to the LCD?
3- I will have to experiment with that.
I need help making my mind on the right approach so I can design the PCB for this project. Then I can edit the code!

Ttelmah,
The PIC datasheet shows and I quote:
“12.6 Using Timer1 as a Real-Time
Clock
Adding an external LP oscillator to Timer1 (such as the
one described in Section 12.3 “Timer1 Oscillator”)
gives users the option to include RTC functionality to
their applications. This is accomplished with an
inexpensive watch crystal to provide an accurate time
base and several lines of application code to calculate
the time. When operating in Sleep mode and using a
battery or supercapacitor as a power source, it can
completely eliminate the need for a separate RTC
device and battery backup.”

As per the datasheet is what I am planning to do as far as generate the RTC function! Which is the same as what you are saying?

Thanks,
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 01, 2015 6:18 pm     Reply with quote

Quote:

3- Do I need to change the flex_lcd.c code to put the LCD in the power
saving mode? What do you suggest as a test program for the modified
Flex driver?


Look at the schematic on page 35 of the Picdem2-Plus (new vs.) board:
http://ww1.microchip.com/downloads/en/DeviceDoc/41584B.pdf
It shows a transistor on PIC pin D7 is used to switch power on/off for the lcd.

The code in this post shows how to turn on the power for the lcd:
http://www.ccsinfo.com/forum/viewtopic.php?t=24661&start=51
Microchip also made some other changes, requiring that the R/W pin
not be used on the Rohs vs. of that board. You can ignore that part
of the post.
Sam_40



Joined: 07 Jan 2015
Posts: 127

View user's profile Send private message

PostPosted: Sun Mar 01, 2015 6:28 pm     Reply with quote

PCM programmer,
Thanks alot for the help. Do I need to connect the LCD unused IO to ground or just leave them open? Does my other connections to the PIC look OK?
Thanks,
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 01, 2015 6:56 pm     Reply with quote

Quote:
Do I need to connect the LCD unused IO to ground or just leave them open?

The unused data bus pins can be left unconnected. The LCD has internal
pullups on those pins, so they are not left floating.

Quote:
Vo Contrast Adjustment Connected to +5 through 1K resistor

This is wrong. Vo should go to the wiper pin of a 10K trimpot. The other
ends of the trimpot go to +5 and Ground.

Quote:
4 RS H/L Register Select Signal RC7
5 R/W H/L Read/Write Signal GND
6 E Enable Signal RC6

Pins C6 and C7 are usually the hardware UART pins on a PIC. Using them
for the LCD is not desirable. The UART is useful for providing debugging
messages.
Sam_40



Joined: 07 Jan 2015
Posts: 127

View user's profile Send private message

PostPosted: Sun Mar 01, 2015 7:00 pm     Reply with quote

PCM programmer,
You have provided me with enough information to build my project.
Thanks for your time and help,
Sam
Sam_40



Joined: 07 Jan 2015
Posts: 127

View user's profile Send private message

PostPosted: Mon Mar 16, 2015 7:49 pm     Reply with quote

Hello,
I have problem with this test program.
The chip is good as I did run tests on it, The LCD is OK as I tested it on with another code and it did run. It is connected as per code. No additional hardware just the PIC, LCD, 5k potentiometer for the LCD CONT, 32768HZ crystal and 2 X 27pf caps on the crystal. Any idea what I have wrong in this code?


Code:
/*
 * Software RTC using PIC18F2685 and 32768Hz crystal connected to T1OSO and T1OSI
 * Thanks to E_KARVELAs and PCM programmer
 */


#include <18F2685.h>
#use delay(clock=8000000)
#fuses INTRC_IO,NOWDT,NOLVP,NOPROTECT, NOBROWNOUT, NOXINST

// flex_lcd.c

 // These pins are for the Microchip PicDem2-Plus board,
 // which is what I used to test the driver.  Change these
 // pins to fit your own board.

 #define LCD_DB4   PIN_C2
 #define LCD_DB5   PIN_C3
 #define LCD_DB6   PIN_C4
 #define LCD_DB7   PIN_C5

 #define LCD_E     PIN_B0
 #define LCD_RS    PIN_B2
 #define LCD_RW    PIN_B1

 // If you only want a 6-pin interface to your LCD, then
 // connect the R/W pin on the LCD to ground, and comment
 // out the following line.

 #define USE_LCD_RW   1     

 //========================================

 #define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines
 #define lcd_line_two 0x40 // LCD RAM address for the 2nd line


 int8 const LCD_INIT_STRING[4] =
 {
  0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
  0xc,                    // Display on
  1,                      // Clear display
  6                       // Increment cursor
  };
                               

 //-------------------------------------
 void lcd_send_nibble(int8 nibble)
 {
 // Note:  !! converts an integer expression
 // to a boolean (1 or 0).
  output_bit(LCD_DB4, !!(nibble & 1));
  output_bit(LCD_DB5, !!(nibble & 2)); 
  output_bit(LCD_DB6, !!(nibble & 4));   
  output_bit(LCD_DB7, !!(nibble & 8));   

  delay_cycles(1);
  output_high(LCD_E);
  delay_us(2);
  output_low(LCD_E);
 }

 //-----------------------------------
 // This sub-routine is only called by lcd_read_byte().
 // It's not a stand-alone routine.  For example, the
 // R/W signal is set high by lcd_read_byte() before
 // this routine is called.     

 #ifdef USE_LCD_RW
 int8 lcd_read_nibble(void)
 {
 int8 retval;
 // Create bit variables so that we can easily set
 // individual bits in the retval variable.
 #bit retval_0 = retval.0
 #bit retval_1 = retval.1
 #bit retval_2 = retval.2
 #bit retval_3 = retval.3

 retval = 0;
     
 output_high(LCD_E);
 delay_cycles(1);

 retval_0 = input(LCD_DB4);
 retval_1 = input(LCD_DB5);
 retval_2 = input(LCD_DB6);
 retval_3 = input(LCD_DB7);
   
 output_low(LCD_E);
     
 return(retval);   
 }   
 #endif

 //---------------------------------------
 // Read a byte from the LCD and return it.

 #ifdef USE_LCD_RW
 int8 lcd_read_byte(void)
 {
 int8 low;
 int8 high;

 output_high(LCD_RW);
 delay_cycles(1);

 high = lcd_read_nibble();

 low = lcd_read_nibble();

 return( (high<<4) | low);
 }
 #endif

 //----------------------------------------
 // Send a byte to the LCD.
 void lcd_send_byte(int8 address, int8 n)
 {
 output_low(LCD_RS);

 #ifdef USE_LCD_RW
 while(bit_test(lcd_read_byte(),7)) ;
 #else
 delay_us(60); 
 #endif

 if(address)
    output_high(LCD_RS);
 else
    output_low(LCD_RS);
       
  delay_cycles(1);

 #ifdef USE_LCD_RW
 output_low(LCD_RW);
 delay_cycles(1);
 #endif

 output_low(LCD_E);

 lcd_send_nibble(n >> 4);
 lcd_send_nibble(n & 0xf);
 }

 //----------------------------
 void lcd_init(void)
 {
 int8 i;

 output_low(LCD_RS);

 #ifdef USE_LCD_RW
 output_low(LCD_RW);
 #endif

 output_low(LCD_E);

 delay_ms(15);

 for(i=0 ;i < 3; i++)
    {
     lcd_send_nibble(0x03);
     delay_ms(5);
    }

 lcd_send_nibble(0x02);

 for(i=0; i < sizeof(LCD_INIT_STRING); i++)
    {
     lcd_send_byte(0, LCD_INIT_STRING[i]);
     
     // If the R/W signal is not used, then
     // the busy bit can't be polled.  One of
     // the init commands takes longer than
     // the hard-coded delay of 60 us, so in
     // that case, lets just do a 5 ms delay
     // after all four of them.
     #ifndef USE_LCD_RW
     delay_ms(5);
     #endif
    }

 }

 //----------------------------

 void lcd_gotoxy(int8 x, int8 y)
 {
 int8 address;

 if(y != 1)
    address = lcd_line_two;
 else
    address=0;

 address += x-1;
 lcd_send_byte(0, 0x80 | address);
 }

 //-----------------------------
 void lcd_putc(char c)
 {
  switch(c)
    {
     case '\f':
       lcd_send_byte(0,1);
       delay_ms(2);
       break;
     
     case '\n':
        lcd_gotoxy(1,2);
        break;
     
     case '\b':
        lcd_send_byte(0,0x10);
        break;
     
     default:
        lcd_send_byte(1,c);
        break;
    }
 }

 //------------------------------
 #ifdef USE_LCD_RW
 char lcd_getc(int8 x, int8 y)
 {
 char value;

 lcd_gotoxy(x,y);

 // Wait until busy flag is low.
 while(bit_test(lcd_read_byte(),7)); 

 output_high(LCD_RS);
 value = lcd_read_byte();
 output_low(lcd_RS);

 return(value);
 }
 #endif
// End of flex_lcd.c


#Byte TMR1H = 0xFCF   // TIMER1 HIGH BYTE LOOK DATASHEET
#Byte T1CON = 0xFCD  //TIMER1 CONFIG REGISTER LOOK DATASHEET

int sec=0;
int min=0;
int hour=0;
int1 flg=false;

 #int_TIMER1
 void TIMER1_isr()    // 2^16=  65536/2 = 32768 * 1/32.768Hz <--- (1sec)                     
 {
   
    bit_clear(T1CON,7);  //Enable access to the individual bytes of the timer register
    Bit_Set(TMR1H,7);   //Add 32768 to timer1 by setting high bit or timer register       
    Bit_Set(T1CON,7);   //Disable access to the individual bytes of the timer register
    flg=true;
 }
 
void main()
{
   enable_interrupts(INT_TIMER1);
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT);
   enable_interrupts(GLOBAL);
   setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_PLL_ON);       //<-- internal 8MHZ crystal with PLL ON 8X4=32MHZ
   lcd_init();                   
 
   for(;;)
   {
      if(flg==true)
      {
         //set_timer1(32768);                           //2^16=  65536/2 = 32768 * 1/32.768Hz <--- (1sec)                                           
         setup_timer_1(T1_EXTERNAL|T1_CLK_OUT);       //    external TIMER1 with
                                                      //    32.768Khz ,clock out for oscillator,asynchronus mode
   
         if (++sec>59)
         {
            sec=0;
            if(++min>59)
            {
               min=0;
               hour++;
               if(++hour>23)
               {
                  hour=0;
               }
            }
         }
                     
                     
         lcd_gotoxy(1,1);
         printf(lcd_putc,"%02u:%02u:%02u",hour,min,sec); 
         flg=false;
      }
   
   }
}


Thanks,


Last edited by Sam_40 on Mon Mar 16, 2015 9:49 pm; edited 4 times in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Mar 16, 2015 8:30 pm     Reply with quote

Tell us what you see on the LCD. What is it doing ?

Also, the LCD may require some extra time to self-initialize after power is
applied to the board. And, the Timer1 oscillator can take 200 ms to
start-up with the watch crystal. Add the delay_ms() shown in bold below
to take care of these two things.
Quote:
void main()
{
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT);
delay_ms(500);
lcd_init();
Sam_40



Joined: 07 Jan 2015
Posts: 127

View user's profile Send private message

PostPosted: Mon Mar 16, 2015 9:22 pm     Reply with quote

The LCD shows nothing (it is not the contrast)?
I did add the delay_ms(500); with no avail!
I inspected the code and did a few changes without any luck!
I suspect it to be #fuses problem or clock issue?

E_KRAVELAs used the following:
Code:
lcd_gotoxy(1,1);
printf(lcd_putc,"%02u:%02u:%02u",hour,min,sec);


I did change it to:
Code:
printf(lcd_putc,"\f%02d:%02d:%02d",hour,min,sec);


My main code:
Code:

#Byte TMR1H = 0xFCF   // TIMER1 HIGH BYTE LOOK DATASHEET
#Byte T1CON = 0xFCD  //TIMER1 CONFIG REGISTER LOOK DATASHEET

int sec=0;
int min=0;
int hour=0;
int1 flg=false;

 #int_TIMER1
 void TIMER1_isr()    // 2^16=  65536/2 = 32768 * 1/32.768Hz <--- (1sec)                     
 {
   
    bit_clear(T1CON,7);  //Enable access to the individual bytes of the timer register
    Bit_Set(TMR1H,7);   //Add 32768 to timer1 by setting high bit or timer register       
    Bit_Set(T1CON,7);   //Disable access to the individual bytes of the timer register
    flg=true;
 }
 
void main()
{
   enable_interrupts(INT_TIMER1);
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT);
   enable_interrupts(GLOBAL);
   setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_PLL_ON);       //<-- internal 8MHZ crystal with PLL ON 8X4=32MHZ
   delay_ms(500);
   lcd_init();                   
 
   for(;;)
   {
      if(flg==true)
      {
         //set_timer1(32768);                           //2^16=  65536/2 = 32768 * 1/32.768Hz <--- (1sec)                                           
         setup_timer_1(T1_EXTERNAL|T1_CLK_OUT);       //    external TIMER1 with
                                                      //    32.768Khz ,clock out for oscillator,asynchronus mode
   
         if (++sec>59)
         {
            sec=0;
            if(++min>59)
            {
               min=0;
               hour++;
               if(++hour>23)
               {
                  hour=0;
               }
            }
         }
                     
                     
         //lcd_gotoxy(1,1);
         //printf(lcd_putc,"%02u:%02u:%02u",hour,min,sec);
         printf(lcd_putc,"\f%02d:%02d:%02d",hour,min,sec);
         flg=false;
      }
   
   }
}

That did not change anything! it seems the PIC is failing to boot even though the PICKIT3 shows target is running!
Thanks,
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Mar 16, 2015 9:48 pm     Reply with quote

Remove the interrupt routine, timer1 setup code, and the RTC code and just write Hello World to the lcd. Verify that it's working. Example:
Code:

void main()
{
delay_ms(500);
lcd_init();
printf(lcd_putc, "\f  Hello World  ");

while(TRUE);
}


If it doesn't work, check your connections between the PIC and the LCD
vs. the pin list at the start of flex_lcd.c.
Sam_40



Joined: 07 Jan 2015
Posts: 127

View user's profile Send private message

PostPosted: Mon Mar 16, 2015 10:14 pm     Reply with quote

With:

Code:
void main()
{
delay_ms(500);
lcd_init();
printf(lcd_putc, "\f  Hello World  ");

while(TRUE);
}


The LCD output:
Code:
Hello World 
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 17, 2015 3:15 pm     Reply with quote

The next thing is to prove if the 32.768 KHz Timer1 oscillator is working.
You could put a line of code in the #int_timer1 isr to toggle an LED on or
off, on each pass through the isr.
Code:

#int_timer1
void timer1_isr(void)
{
output_toggle(LED_PIN);
}

If it's all working, that LED should turn on for 2 seconds, and then off
for 2 seconds, continuously. You'll need the Timer1 setup code in main(),
then let it sit in a while(TRUE) statement forever, while the interrupt blinks
the LED.
Sam_40



Joined: 07 Jan 2015
Posts: 127

View user's profile Send private message

PostPosted: Tue Mar 17, 2015 7:34 pm     Reply with quote

PCM programmer,
Thanks for all of your help. I really appreciate you are giving the time and efforts to help me.
I finally got the code functional. It has been running for about 3 hours, it seems very accurate Smile I still have to add more hardware for the complete project and do more testing. I will run it for at least a week to make sure of the accuracy.
I did have to edit E_KARVELAs code for more efficiency (as far as I think Smile ).

Would someone please review my code and let me know how can I improve it! I welcome all feedback, suggestions and criticism.

Code:
/*
 * Software RTC using PIC18F2685 and 32768Hz crystal connected to T1OSO and T1OSI
 * Thanks to E_KARVELAs and PCM programmer
 */

#include <18F2685.h>
#use delay(clock=8000000)

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BORV21                   //Brownout reset at 2.0V
#FUSES PUT                      //Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOIESO                   //NO Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOPBADEN                 //NO PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOLPT1OSC                //Timer1 configured for higher power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)


// flex_lcd.c

/* These pins are for the Microchip PicDem2-Plus board,
   which is what I used to test the driver.  Change these
   pins to fit your own board. */

/* Start of flex_lcd.c */


 #define LCD_DB4   PIN_C2
 #define LCD_DB5   PIN_C3
 #define LCD_DB6   PIN_C4
 #define LCD_DB7   PIN_C5

 #define LCD_E     PIN_B0
 #define LCD_RW    PIN_B1
 #define LCD_RS    PIN_B2
 

 // If you only want a 6-pin interface to your LCD, then
 // connect the R/W pin on the LCD to ground, and comment
 // out the following line.

 #define USE_LCD_RW   1     

 //========================================

 #define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines
 #define lcd_line_two 0x40 // LCD RAM address for the 2nd line


 int8 const LCD_INIT_STRING[4] =
 {
  0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
  0xc,                    // Display on
  1,                      // Clear display
  6                       // Increment cursor
  };
                               

 //-------------------------------------
 void lcd_send_nibble(int8 nibble)
 {
 // Note:  !! converts an integer expression
 // to a boolean (1 or 0).
  output_bit(LCD_DB4, !!(nibble & 1));
  output_bit(LCD_DB5, !!(nibble & 2)); 
  output_bit(LCD_DB6, !!(nibble & 4));   
  output_bit(LCD_DB7, !!(nibble & 8));   

  delay_cycles(1);
  output_high(LCD_E);
  delay_us(2);
  output_low(LCD_E);
 }

 //-----------------------------------
 // This sub-routine is only called by lcd_read_byte().
 // It's not a stand-alone routine.  For example, the
 // R/W signal is set high by lcd_read_byte() before
 // this routine is called.     

 #ifdef USE_LCD_RW
 int8 lcd_read_nibble(void)
 {
 int8 retval;
 // Create bit variables so that we can easily set
 // individual bits in the retval variable.
 #bit retval_0 = retval.0
 #bit retval_1 = retval.1
 #bit retval_2 = retval.2
 #bit retval_3 = retval.3

 retval = 0;
     
 output_high(LCD_E);
 delay_cycles(1);

 retval_0 = input(LCD_DB4);
 retval_1 = input(LCD_DB5);
 retval_2 = input(LCD_DB6);
 retval_3 = input(LCD_DB7);
   
 output_low(LCD_E);
     
 return(retval);   
 }   
 #endif

 //---------------------------------------
 // Read a byte from the LCD and return it.

 #ifdef USE_LCD_RW
 int8 lcd_read_byte(void)
 {
 int8 low;
 int8 high;

 output_high(LCD_RW);
 delay_cycles(1);

 high = lcd_read_nibble();

 low = lcd_read_nibble();

 return( (high<<4) | low);
 }
 #endif

 //----------------------------------------
 // Send a byte to the LCD.
 void lcd_send_byte(int8 address, int8 n)
 {
 output_low(LCD_RS);

 #ifdef USE_LCD_RW
 while(bit_test(lcd_read_byte(),7)) ;
 #else
 delay_us(60); 
 #endif

 if(address)
    output_high(LCD_RS);
 else
    output_low(LCD_RS);
       
  delay_cycles(1);

 #ifdef USE_LCD_RW
 output_low(LCD_RW);
 delay_cycles(1);
 #endif

 output_low(LCD_E);

 lcd_send_nibble(n >> 4);
 lcd_send_nibble(n & 0xf);
 }

 //----------------------------
 void lcd_init(void)
 {
 int8 i;

 output_low(LCD_RS);

 #ifdef USE_LCD_RW
 output_low(LCD_RW);
 #endif

 output_low(LCD_E);

 delay_ms(15);

 for(i=0 ;i < 3; i++)
    {
     lcd_send_nibble(0x03);
     delay_ms(5);
    }

 lcd_send_nibble(0x02);

 for(i=0; i < sizeof(LCD_INIT_STRING); i++)
    {
     lcd_send_byte(0, LCD_INIT_STRING[i]);
     
     // If the R/W signal is not used, then
     // the busy bit can't be polled.  One of
     // the init commands takes longer than
     // the hard-coded delay of 60 us, so in
     // that case, lets just do a 5 ms delay
     // after all four of them.
     #ifndef USE_LCD_RW
     delay_ms(5);
     #endif
    }

 }

 //----------------------------

 void lcd_gotoxy(int8 x, int8 y)
 {
 int8 address;

 if(y != 1)
    address = lcd_line_two;
 else
    address=0;

 address += x-1;
 lcd_send_byte(0, 0x80 | address);
 }

 //-----------------------------
 void lcd_putc(char c)
 {
  switch(c)
    {
     case '\f':
       lcd_send_byte(0,1);
       delay_ms(2);
       break;
     
     case '\n':
        lcd_gotoxy(1,2);
        break;
     
     case '\b':
        lcd_send_byte(0,0x10);
        break;
     
     default:
        lcd_send_byte(1,c);
        break;
    }
 }

 //------------------------------
 #ifdef USE_LCD_RW
 char lcd_getc(int8 x, int8 y)
 {
 char value;

 lcd_gotoxy(x,y);

 // Wait until busy flag is low.
 while(bit_test(lcd_read_byte(),7)); 

 output_high(LCD_RS);
 value = lcd_read_byte();
 output_low(lcd_RS);

 return(value);
 }
 #endif

/* End of flex_lcd.c */


/* Start of the RTC program */

#Byte TMR1H = 0xFCF                                            /* TIMER1 HIGH BYTE LOOK DATASHEET */
#Byte T1CON = 0xFCD                                            /* TIMER1 CONFIG REGISTER LOOK DATASHEET */

int sec=0;
int min=0;
int hour=0;
int1 flg=false;

 #int_TIMER1
 void TIMER1_isr()    // 2^16=  65536/2 = 32768 * 1/32.768Hz <--- (1sec)                     
 {
   
    bit_clear(T1CON,7);                                        /* Enable access to the individual bytes of the timer register */
    Bit_Set(TMR1H,7);                                          /* Add 32768 to timer1 by setting high bit or timer register */       
    Bit_Set(T1CON,7);                                          /* Disable access to the individual bytes of the timer register. */
    output_toggle(PIN_B3);                                     /* To toggle the LED on PIN RB3 every 2 seconds (1 second ON next second OFF). */
    flg=true;
    if(flg==true)
    {
   
         if (++sec>59)
         {
            sec=0;
            if(++min>59)
            {
               min=0;
               hour++;
               if(++hour>23)
               {
                  hour=0;
               }
            }
         }
    }
    flg=false;
 }

/* End of the RTC program */


/* Start of main() */

void main()
{

   enable_interrupts(INT_TIMER1);
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT);
   enable_interrupts(GLOBAL);
   setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_PLL_ON);            /* internal 8MHZ crystal with PLL ON 8X4=32MHZ */
   delay_ms(500);
   lcd_init();                   
   while(true)
   {
         delay_ms(100);                                        /* Delay so the LCD won't flicker! */
         printf(lcd_putc,"\f%02d:%02d:%02d",hour,min,sec);     /* Output the HH:MM:SS on the LCD */
         if(input(PIN_A0 )==0)                                 /* If the switch on pin RA0 is pressed then increase the hours count variable */
         {
            delay_ms(250);                                     /* Add delay between key presses so the count won't speed up on hyper mode */ 
            ++hour;
            if (hour == 24)
            {
               hour=0;
            }
         }
         if(input(PIN_A1 )==0)                                 /* If the switch on pin RA1 is pressed then increase the minutes count variable */
         {
            delay_ms(250); 
            ++min;
            if (min == 60)
            {
               min=0;
            }
         }
   
         if(input(PIN_A2 )==0)                                 /* If the switch on pin RA2 is pressed then reset the seconds count variable to accuratly set the clock! */
         {
            sec=0;
         }
   }
}

/* End of main() */



/*Test program provided by PCM programmer to test the LCD connection to the PIC*/
//!void main()
//!{
//!   output_high(PIN_B3);
//!   delay_ms(500);
//!   lcd_init();
//!   printf(lcd_putc, "\f Hello World ");
//!   while(TRUE);
//!
//! }
//!

Regards,
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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