|
|
View previous topic :: View next topic |
Author |
Message |
Sam_40
Joined: 07 Jan 2015 Posts: 127
|
Low power lcd with flex driver |
Posted: Sun Mar 01, 2015 12:15 pm |
|
|
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: 9241 Location: Greensville,Ontario
|
|
Posted: Sun Mar 01, 2015 12:53 pm |
|
|
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: 19537
|
|
Posted: Sun Mar 01, 2015 1:09 pm |
|
|
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
|
|
Posted: Sun Mar 01, 2015 2:07 pm |
|
|
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
|
|
Posted: Sun Mar 01, 2015 6:18 pm |
|
|
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
|
|
Posted: Sun Mar 01, 2015 6:28 pm |
|
|
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
|
|
Posted: Sun Mar 01, 2015 6:56 pm |
|
|
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
|
|
Posted: Sun Mar 01, 2015 7:00 pm |
|
|
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
|
|
Posted: Mon Mar 16, 2015 7:49 pm |
|
|
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
|
|
Posted: Mon Mar 16, 2015 8:30 pm |
|
|
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
|
|
Posted: Mon Mar 16, 2015 9:22 pm |
|
|
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
|
|
Posted: Mon Mar 16, 2015 9:48 pm |
|
|
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
|
|
Posted: Mon Mar 16, 2015 10:14 pm |
|
|
With:
Code: | void main()
{
delay_ms(500);
lcd_init();
printf(lcd_putc, "\f Hello World ");
while(TRUE);
} |
The LCD output:
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Mar 17, 2015 3:15 pm |
|
|
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
|
|
Posted: Tue Mar 17, 2015 7:34 pm |
|
|
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 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 ).
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, |
|
|
|
|
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
|