i2c LCD display adapter and PIC microprocessor

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
OK. Finally the i2c LCD adaptor has turned up and I've got it working. I am now programming in C and it's been a steep learning curve.

The pinout actually is:

PCF8574 -- LCD
-----------------
P0 -------- RS
P1 -------- R/W
P2 -------- En
P3 -------- LED on/off
P4 -------- Data pin 4
P5 -------- Data pin 5
P6 -------- Data pin 6
P7 -------- Data pin 7

ErnieM, we were discussing how to send the data to the module, you can simply send the i2c start condition, send the address and then high nibble, with enable high, then again with enable low, then the low nibble. It clocks in on the falling edge of the enable bit. You can keep sending data to it without having to send the stop condition after each byte. It really is a nice bit of gear.


However I'm a little bit stumped on something. I have a real time clock module and the LCD module both running on the i2c bus. I am reading the RTC module and storing the data in raw_seconds, raw_minutes and raw_hours. Each of these variables hold the tens in the high nibble and the units in the low nibble.

If I put them into variables like seconds_tens, second_units, minutes_tens.....etc. and want to display them on the LCD, how can I do this?

Originally I thought I would use my 'lcd_write_chars' function and simply pass it one of the variables with 0x30 added to it to give it the correct ascii code, but the compiler says: illegal conversion of integer to pointer

I Googled how I could achieve what I want and came across 'itoa', but I cant get this to work either. If I do this:

Rich (BB code):
        char buf[];
        itoa(buf,seconds_units,16);
        lcd_wr_chars(buf);
I get the seconds counting up from 0 to 9 etc.

If I try this:
Rich (BB code):
        char buf[];
        itoa(buf,seconds_tens,16);
        lcd_wr_chars(buf);

        char buf[];
        itoa(buf,seconds_units,16);
        lcd_wr_chars(buf);
I get 131 displayed and then 10 seconds later I get 232, and another 10 seconds later I get 333 etc.

I know it's something to do with the array, but I'm not sure what to do.

Is there an easier way to do what I want to do?

I thought that writing the program to send the commands over i2c to the LCD adaptor and getting it to toggle the pins correctly was going to be tricky, but it proved to be OK, even in C which I've only been on for a weeks. I never expected it to be so tricky to simply convert a few variables to ascii.

Again, thanks for any help you can give :)
 

MMcLaren

Joined Feb 14, 2010
861
Sounds like the clock data may be "packed bcd". If so, could this be useful?

Rich (BB code):
    seconds_tens = (raw_seconds >> 4) | '0'    // ascii '0'..'5'
    seconds_ones = (raw_seconds &= 15) | '0'   // ascii '0'..'9'
My PIC 4-Digit Single-Chip 24-Hour Clock project and my PIC 4-Digit 99-Minute Timer project both use packed BCD variables. They're written in BoostC so not sure if that would be much help.

Good luck on your project.

Cheerful regards, Mike
 
Last edited:

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
Yeah, that's what I do to get the two variables from the 'raw_seconds' byte.

When I make my Nixie clock, all I will do is copy those values to a port and use a bcd chip, but as for displaying them on the LCD, I need to convert them to an ascii character.
 

MMcLaren

Joined Feb 14, 2010
861
That's what OR'ing or adding '0' (0x30) is supposed to do;

binary 0..9 + 0x30 = 0x30 ('0') .. 0x39 ('9')...

Have you checked it out using the MPLAB Simulator?
 

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
Yeah, it does give the correct hex value for the character I want to display, but my function is declared as follows:

void lcd_wr_chars (const char *data);

If I write lcd_wr_chars ("Hello");

Hello is displayed.

If I write lcd_wr_chars (seconds_tens);

I get an integer to character error.


I've managed to solve it by doing this:

Rich (BB code):
        char buf[1];
        itoa(buf,(raw_hours >> 4),10);
        lcd_wr_chars(buf);

        char buf[1];
        itoa(buf,(raw_hours &= 15),10);
        lcd_wr_chars(buf);
 

MMcLaren

Joined Feb 14, 2010
861
Ah, I see. I just use an "overload" function in my BoostC programs;

Rich (BB code):
   void PutCMD(char pdata)        // lcd command (RS=0)
   { rs = 0; PutLCD(pdata);       // rs = 0, send command
   }                              //

   void PutDAT(char pdata)        // lcd data (RS=1) character
   { rs = 1; PutLCD(pdata);       // rs = 1, send data
   }                              //

   void PutDAT(rom char *data)    // lcd data (RS=1) const string
   { char ndx = 0; rs = 1;        //
     while(work = data[ndx++])    // while not end-of-string
       PutLCD(work);              //
   }                              //
 

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
Here's a strange one....

If I do this:
Rich (BB code):
        char buf[1];
        itoa(buf,(raw_hours >> 4),10);
        lcd_wr_chars(buf);
        
        char buf[1];
        itoa(buf,(raw_hours &= 15),10);
        lcd_wr_chars(buf);
The units of the hours is always displayed as 0. I've run it through the simulator and it is 0 there too.

But if I do this:
Rich (BB code):
        char h = raw_hours;
        char l = raw_hours;

        char buf[1];
        itoa(buf,(h >> 4),10);
        lcd_wr_chars(buf);
        
        char buf[1];
        itoa(buf,(l &= 15),10);
        lcd_wr_chars(buf);
It works fine. What is happening?
 
Top