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

I2C on Digole serial control module for LCDs

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



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

I2C on Digole serial control module for LCDs
PostPosted: Thu Nov 27, 2014 10:36 am     Reply with quote

I am trying to display on a Digole LCDSP_T Ver2.0 serial control module with LCD display.
I am using I2C code that worked on another project but with a different PIC and for a different purpose.
1.5k pullups on both lines. Both lines active with pulses. The display shows "I2C address:0x27" so the control module and display seem to be working. It does not respond to any commands like CS0 to turn the cursor off. I assume that is how I'm supposed to use it. The PIC blinks an output in a different test program.
Does this code look correct? Are the three ways to send a Z correct? I corrected what was here previously. I don't know what changed it.
CCS PCM C Compiler, Version 5.019

Code:
 #include <16F882.H>
 #fuses INTRC_IO, NOWDT, PUT, NOPROTECT, BROWNOUT, MCLR
 #use delay (clock=2000000)
 #use I2C (master, SCL=PIN_C3, SDA=PIN_C4)
 #byte portc = getenv("SFR:PORTC")

// define I2C addresses
 #define LCD_WRT_ADDR 0X27      // LCD display
 
// The main function
void main(void)
 {
    set_tris_c (0x00);         // all outputs
  while (1)
  {
// output_toggle(PIN_C3);
// send to LCD
   I2C_START ();                // start I2C
   I2C_WRITE (0x27);         // addr of LCD
   I2C_WRITE (0x5A);         // send Z
   I2C_WRITE ("Z");            // send Z
   I2C_WRITE (90);            // send Z
   I2C_STOP ();                 // stop I2C
delay_ms(3000);
  }                             // end of while loop
 }                              // end of main function
// end
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 27, 2014 2:43 pm     Reply with quote

Quote:
I2C: Slave Mode, 7-bit address, default address is Hex:27, change able

The address they give is in 7-bit format. CCS uses 8-bit format, so you
must shift their address left by 1 bit to convert it to CCS format. Doing
this gives the address as: 0x4E

The Digole board must also be jumpered to put it in i2c mode. It is
shipped with UART mode enabled by default.

Connect your PIC to the Digole board. Then run this program
on your PIC and see if it finds the board as an i2c slave device.
http://www.ccsinfo.com/forum/viewtopic.php?t=49713
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Working now
PostPosted: Thu Nov 27, 2014 4:35 pm     Reply with quote

Thanks PCM Programmer. The address was all that was wrong.
I had modified my program to increment the address each second and send again but the display and backlight vanished and I had to reset long before I got to the correct address. Your program is much more elegant.

I can

Code:
I2C_WRITE(84);
I2C_WRITE(0x54);


but cannot

Code:
I2C_WRITE("T");

is there a way to put the actual letter into the statement?

I will play with an array in a loop next to display a message unless you have a function to do this.
Much appreciated.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 27, 2014 5:51 pm     Reply with quote

When a function has byte parameter, you should put an ASCII character
in single quotes. Example:
Code:
i2c_write('T');
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Nesting functions
PostPosted: Thu Nov 27, 2014 6:36 pm     Reply with quote

Thanks again, that works.
My attempt to write functions to display ended with a compile error that I cannot nest functions.
How do I get around that one?
I will try searching on I2C programs, someone must have done it already.
It seems that
OLED 128x64 SSD1306 I2C PIC16F1788 driver
nests functions. I will see where i'm going wrong
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 27, 2014 7:39 pm     Reply with quote

Post a short test program that shows the error. We can copy it into
MPLAB and try to compile it and see your problem.
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PostPosted: Thu Nov 27, 2014 9:48 pm     Reply with quote

I put the closing brackets for the main function AFTER the functions at the end. Embarassed
I think everything will work OK and I have the
OLED 128x64 SSD1306 I2C PIC16F1788 driver
examples to learn from.
Thanks PCM programmer, you have incredible patience with us part-time programmers.
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Pleased with Digole LCDSP_T serial control module
PostPosted: Fri Nov 28, 2014 2:19 pm     Reply with quote

I am pleased with the Digole module and have an application that uses 5 LCD displays that can now be controlled on a pair of wires from one PIC.
The next one I will tackle is their Universal Graphic Serial LCD Adapter since I want to be able to place graphics on an LCD and this seems to be the easiest way.
The working code for my 16x2 alphanumeric display is below. I left in the brute force way of sending to I2C just as an illustration.

Code:
/* Pre-processor directives */
 #include <16F882.H>
 #fuses INTRC_IO, NOWDT, PUT, NOPROTECT, BROWNOUT, MCLR
 #use delay (clock=2000000)
 #use I2C (master, SCL=PIN_C3, SDA=PIN_C4)
 #byte portc = getenv("SFR:PORTC")

// define I2C address and LCD size
    #define LCD_WRT_ADDR 0X4E       // LCD display
    #define num_of_char  17         // characters per line plus 1

// Function prototypes
    void clear_LCD (void);                      // Clear LCD
    void cursor(short ctrl);                    // Turn cursor ON(1) or OFF(0)
    void control_addr (short ctrl);             // Turn on mode
    void text_position (int line, int column);   // set start for next text
    void text(char txt [num_of_char]);                    // Send string to LCD

// The main function
void main(void)
 {
// declare variables
  set_tris_c (0x00);         // all outputs
  int1 ON=TRUE;
  int1 OFF=FALSE;

// declare a literal string which is automatically terminated by
// a null character and the size is calculated automatically
  char text_array[]="Short test";       // insert text up to 16 characters here
  char text_array2[]="Hello World";   // insert text up to 16 characters here

// Start the display sequence
  control_addr(ON);             // control startup display
  delay_ms(2000);              // display start screen for 2 secs
  clear_LCD();                    // clear the LCD
  delay_ms(2000);              // show cursor at start for 2 secs
  cursor(OFF);                    // turn cursor OFF
  delay_ms(2000);              // show cursor is off for 2 secs
  text(text_array);              // display text array
  delay_ms(3000);              // for 3 seconds
  clear_LCD();                    // clear the LCD
  text(text_array2);            // display text array
  delay_ms(3000);              // for 3 seconds
//  clear_LCD();                  // clear the LCD
  text_position(3,1);           // 3rd column, 2nd line

// send to LCD the old way
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD

   I2C_WRITE ('T');             // T
   I2C_WRITE ('T');             // T
   I2C_WRITE ('H');             // H
   I2C_WRITE (69);              // E
   I2C_WRITE (76);              // L
   I2C_WRITE (76);              // L
   I2C_WRITE (79);              // O
   I2C_WRITE (32);              // SPACE
   I2C_WRITE (0X41);              // A
   I2C_WRITE (0X47);              // G
   I2C_WRITE (0X41);              // A
   I2C_WRITE (0X49);              // I
   I2C_WRITE (0X4E);              // N
   I2C_WRITE (0);               // 0 TO TERMINATE

   I2C_STOP ();                 // stop I2C

   delay_ms(2000);
 }                              // end of main function

// Functions
// Clear Display
void clear_LCD (void)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('C');             // C CL to clear display
   I2C_WRITE ('L');             // L
   I2C_STOP ();                 // stop I2C
   }
// Turn cursor ON or OFF
void cursor(short ctrl)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('C');             // C, CS0 to control cursor
   I2C_WRITE ('S');             // S
   I2C_WRITE (ctrl);            // 1=ON, 0=OFF
   I2C_STOP ();                 // stop I2C
   }
// Display Configuration: Control address display
void control_addr (short ctrl)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE (0x44);            // D, to display I2C address
   I2C_WRITE (0x43);            // C
   I2C_WRITE (ctrl);            // 1=on, 0 to turn off
   I2C_STOP ();                 // stop I2C
   }
// set position of next text
void text_position(int line, int column)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('T');            // T, TP set text position
   I2C_WRITE ('P');            // P
   I2C_WRITE (line);            // line position
   I2C_WRITE (column);          // column position
   I2C_STOP ();                 // stop I2C
   }
// send string to LCD
void text(char txt [num_of_char])
   {
   int i;
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE('T');              // send TT for text coming
   I2C_WRITE('T');
    for (i=0; i<num_of_char; i++)
   {
   I2C_WRITE(txt[i]);          // start with a Z
   }
   I2C_WRITE(0);
   I2C_STOP ();                 // stop I2C   
   }
// end


29 Nov 2014: Note I have added "#define num_of_char 17" so the size of LCD can be changed easily. I made it 17 because of the advice below. I also corrected the text position statement which had line,col instead of col,line


Last edited by rovtech on Sat Nov 29, 2014 9:52 am; edited 4 times in total
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Display formatting
PostPosted: Sat Nov 29, 2014 8:02 am     Reply with quote

Now that I have the serial adapter working I wondered how I can display a floating point number like 3.27 volts. It would be nice to be able to use proper C code such as

Code:
printf(lcd_putc, "Battery %2.2fv", volts);

that I have used with the CCS LCD functions. One option is to modify the CCS code to use the I2C to parallel adapter and have the LCD driver in software instead of using the hardware with the driver in firmware. I do like this adapter though, which is what this project is about, and would like to be able to send floating point numbers to the display.
Any suggestions?
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Sat Nov 29, 2014 8:58 am     Reply with quote

You can get close with what you already show.
Code:

   char buff[17]; //Remember a 'string' is one character longer than the data.

   sprintf(buff, "Battery %5.2fv", volts);
   text(buff);


Remember in C, the number in front of the decimal point in a format declaration, is the total field width _not_ the number of characters in front of the decimal. '.2f' required a field width of 3, so your code would be overflowing the field width all the time....

To have 16 usable characters to display (if the number got that large), you have to have the source array able to hold 17 characters. You also need to be aware that if (for instance) the number got to over 99999, then the print statement could overflow the space available in the array:

'Battery 100000.00' is 17 characters long, and would result in the next variable being overwritten with the null terminator character. You either need to ensure this cannot happen (depending on how 'volts' is calculated), or testthe value before formatting, or allow a longer target string, and then accept the data being lost off the end....
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Formatting and a correction
PostPosted: Sat Nov 29, 2014 9:43 am     Reply with quote

Thanks, I will try that.
I have added "#define num_of_char 17" so the size of LCD can be changed easily. I also corrected the text position statement which had line,col instead of col,line.
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Formatting works!
PostPosted: Sat Nov 29, 2014 10:49 am     Reply with quote

Thanks Ttelmah, that works perfectly.

Code:
/* Pre-processor directives */
 #include <16F882.H>
 #fuses INTRC_IO, NOWDT, PUT, NOPROTECT, BROWNOUT, MCLR
 #use delay (clock=2000000)
 #use I2C (master, SCL=PIN_C3, SDA=PIN_C4)
 #byte portc = getenv("SFR:PORTC")

// define I2C address
#define LCD_WRT_ADDR 0X4E       // LCD display
#define buff_size 17                 // characters per line plus one
   
// Function prototypes
    void clear_LCD (void);                      // Clear LCD
    void cursor(short ctrl);                    // Turn cursor ON(1) or OFF(0)
    void control_addr (short ctrl);             // Turn on mode
    void text_position (int line, int column);   // set start for next text
    void sen_str(char buff[buff_size]);                    // Send string to LCD

// The main function
void main(void)
 {
// declare variables
  set_tris_c (0x00);         // all outputs
  int1 ON=TRUE;
  int1 OFF=FALSE;
  char buff[buff_size];
  float BV=2.43;

// declare a literal string which is automaticall terminated by a
// null character and the array size is calculated automatically
  char text_1[]="Battery State:";   // insert text up to 16 characters here

// Start the display sequence
  delay_ms(500);                // allow I2C module to start
  control_addr(OFF);            // control startup display
  clear_LCD();                  // clear the LCD
  cursor(OFF);                  // turn cursor OFF
  sen_str(text_1);              // display text array
  text_position(1,1);           // 2nd line, 5th column
  sprintf(buff, "Battery %5.2fv", BV);
  sen_str(buff);
 }                              // end of main function

// Functions
// Clear Display
void clear_LCD (void)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('C');             // C CL to clear display
   I2C_WRITE ('L');             // L
   I2C_STOP ();                 // stop I2C
   }
// Turn cursor ON or OFF
void cursor(short ctrl)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('C');             // C, CS0 to control cursor
   I2C_WRITE ('S');             // S
   I2C_WRITE (ctrl);            // 1=ON, 0=OFF
   I2C_STOP ();                 // stop I2C
   }
// Display Configuration: Control address display
void control_addr (short ctrl)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE (0x44);            // D, to display I2C address
   I2C_WRITE (0x43);            // C
   I2C_WRITE (ctrl);            // 1=on, 0 to turn off
   I2C_STOP ();                 // stop I2C
   }
// set position of next text
void text_position(int line, int column)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('T');            // T, TP set text position
   I2C_WRITE ('P');            // P
   I2C_WRITE (line);            // line position
   I2C_WRITE (column);          // column position
   I2C_STOP ();                 // stop I2C
   }
// send string to LCD
void sen_str(char buff[buff_size])
   {
   int i;
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE('T');              // send TT for text coming
   I2C_WRITE('T');
    for (i=0; i<buff_size; i++)
   {
   I2C_WRITE(buff[i]);          // start with a Z
   }
   I2C_WRITE(0);
   I2C_STOP ();                 // stop I2C   
   }
// end


I could also use sprintf instead of making special strings as I did for "Battery State:" in the above code. Replacing with this works perfectly:

Code:
  sprintf(buff, "Battery State:");
  sen_str(buff);              // display text array
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

I2C to 8 bit board
PostPosted: Sat Nov 29, 2014 3:47 pm     Reply with quote

I tried a "dumb" I2C to 8 bit adapter, Ebay item
http://www.ebay.ca/itm/321475410959?ssPageName=STRK:MEWAX:IT&_trksid=p3984.m1423.l2649
It also specifies address 0x27 but uses the 8 bit version 0x4E
Can anyone explain what this is all about?
What, besides a teletype, sends 7 bits?
It works to translate I2C to 8 bits without any smarts.
It was connected to an LCD and this flashes the backlight (see schematic download):

Code:
While(1)
 {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE (0x08);            // turn on LED
   I2C_STOP ();                 // stop I2C

  delay_ms(500);

   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE (0x00);            // turn on LED
   I2C_STOP ();                 // stop I2C
  delay_ms(2000);
 }


It could have several uses. Just remember tha address 0x4E.
The address lines have pullups and the edge pads are grounded and are jumpered to ground the line, despite what the instructions say.
I don't intend to go any further with this device.
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