I2C LCD Library

Discussion in 'Embedded Systems and Microcontrollers' started by jayanthd, Sep 15, 2015.

  1. jayanthd

    Thread Starter Member

    Jul 4, 2015
    264
    27
  2. Wendy

    Moderator

    Mar 24, 2008
    20,764
    2,535
    Sorry, but this does not meet the criteria of the Completed Projects thread. The attached file is unreadable, and as near as I can tell it is a library, not a project.

    If you disagree with this decision just flag the post using the report button, and the moderating staff will discuss it in more detail.

    How to post a project to the collection
     
  3. jayanthd

    Thread Starter Member

    Jul 4, 2015
    264
    27
    Hi Wendy

    Please use WinRAR to extract the file. There are two folders. One is Hardware I2C LCD project and another is software I2C LCD project. It is written for mikroC PRO PIC Compiler using mikroC PRO PIC I2C and Software I2C Libraries. I hope the code can be compiled with demo version of the Compiler.

    Anyways I am posting the code for both the hardware and software I2C LCD but it only applies for mikroC PRO PIC Compiler.

    Hardware I2C LCD Code

    Code (C):
    1.  
    2. #define _LCD_FIRST_ROW          0x80     //Move cursor to the 1st row
    3. #define _LCD_SECOND_ROW         0xC0     //Move cursor to the 2nd row
    4. #define _LCD_THIRD_ROW          0x94     //Move cursor to the 3rd row
    5. #define _LCD_FOURTH_ROW         0xD4     //Move cursor to the 4th row
    6. #define _LCD_CLEAR              0x01     //Clear display
    7. #define _LCD_RETURN_HOME        0x02     //Return cursor to home position, returns a shifted display to
    8.                                          //its original position. Display data RAM is unaffected.
    9. #define _LCD_CURSOR_OFF         0x0C     //Turn off cursor
    10. #define _LCD_UNDERLINE_ON       0x0E     //Underline cursor on
    11. #define _LCD_BLINK_CURSOR_ON    0x0F     //Blink cursor on
    12. #define _LCD_MOVE_CURSOR_LEFT   0x10     //Move cursor left without changing display data RAM
    13. #define _LCD_MOVE_CURSOR_RIGHT  0x14     //Move cursor right without changing display data RAM
    14. #define _LCD_TURN_ON            0x0C     //Turn Lcd display on
    15. #define _LCD_TURN_OFF           0x08     //Turn Lcd display off
    16. #define _LCD_SHIFT_LEFT         0x18     //Shift display left without changing display data RAM
    17. #define _LCD_SHIFT_RIGHT        0x1E     //Shift display right without changing display data RAM
    18.  
    19. #define  Waddr 0x4E
    20.  
    21. /*   LCD_I2C found with PCF8574
    22.          P7,P6,P5,P4 of PCF8574 = MSbits DB7,DB6,DB5,DB4 of LCD Display.
    23.          P3 is hardware display bit (BackLight : 1 = on / 0 = off)
    24.          P2 is hardware E display bit clock : E = 1 -> E = 0 active
    25.          P1 is R/W hardware Read/Write bit hardware : Read = 1 / Write = 0
    26.          P0 is RS hardware Register Select : CmdReg = 0 / DataReg = 1
    27. */
    28.  
    29. char msg[21];
    30. char message1[] = "Hardware I2C LCD";
    31. char message2[] = "16x2, 20x2, 20x4";
    32. const char message3[] = "PIC12F1840";
    33. const char message4[] = "mikroC PRO PIC";
    34.  
    35. //copy const to ram string
    36. char *CopyConst2Ram(char *dest, const char *src) {
    37.     char *d;
    38.  
    39.     asm clrwdt
    40.     d = dest;
    41.     for(;*dest++ = *src++;)asm clrwdt;
    42.     asm clrwdt
    43.     return d;
    44. }
    45.  
    46. void I2C_LCD_Cmd(char out_char) {
    47.  
    48.     char hi_n, lo_n;
    49.     char rs = 0x00;
    50.  
    51.     hi_n = out_char & 0xF0;
    52.     lo_n = (out_char << 4) & 0xF0;
    53.  
    54.     I2C1_Start();
    55.     I2C1_Is_Idle();
    56.     I2C1_Wr(Waddr);
    57.     I2C1_Is_Idle();
    58.     I2C1_Wr(hi_n | rs | 0x04 | 0x08);
    59.     I2C1_Is_Idle();
    60.     Delay_us(50);
    61.     I2C1_Wr(hi_n | rs | 0x00 | 0x08);
    62.     I2C1_Is_Idle();
    63.     Delay_us(100);
    64.     I2C1_Wr(lo_n | rs | 0x04 | 0x08);
    65.     I2C1_Is_Idle();
    66.     Delay_us(50);
    67.     I2C1_Wr(lo_n | rs | 0x00 | 0x08);
    68.     I2C1_Is_Idle();
    69.     I2C1_stop();
    70.  
    71.     if(out_char == 0x01)Delay_ms(2);
    72. }
    73.  
    74. void I2C_LCD_Chr(char row, char column, char out_char) {
    75.  
    76.     char hi_n, lo_n;
    77.     char rs = 0x01;
    78.  
    79.     switch(row){
    80.  
    81.         case 1:
    82.         I2C_LCD_Cmd(0x80 + (column - 1));
    83.         break;
    84.         case 2:
    85.         I2C_LCD_Cmd(0xC0 + (column - 1));
    86.         break;
    87.         case 3:
    88.         I2C_LCD_Cmd(0x94 + (column - 1));
    89.         break;
    90.         case 4:
    91.         I2C_LCD_Cmd(0xD4 + (column - 1));
    92.         break;
    93.     };
    94.  
    95.     hi_n = out_char & 0xF0;
    96.     lo_n = (out_char << 4) & 0xF0;
    97.  
    98.     I2C1_Start();
    99.     I2C1_Is_Idle();
    100.     I2C1_Wr(Waddr);
    101.     I2C1_Is_Idle();
    102.     I2C1_Wr(hi_n | rs | 0x04 | 0x08);
    103.     I2C1_Is_Idle();
    104.     Delay_us(50);
    105.     I2C1_Wr(hi_n | rs | 0x00 | 0x08);
    106.     I2C1_Is_Idle();
    107.     Delay_us(100);
    108.     I2C1_Wr(lo_n | rs | 0x04 | 0x08);
    109.     I2C1_Is_Idle();
    110.     Delay_us(50);
    111.     I2C1_Wr(lo_n | rs | 0x00 | 0x08);
    112.     I2C1_Is_Idle();
    113.     I2C1_stop();
    114. }
    115.  
    116. void I2C_LCD_Chr_Cp(char out_char) {
    117.  
    118.     char hi_n, lo_n;
    119.     char rs = 0x01;
    120.  
    121.     hi_n = out_char & 0xF0;
    122.     lo_n = (out_char << 4) & 0xF0;
    123.  
    124.     I2C1_Start();
    125.     I2C1_Is_Idle();
    126.     I2C1_Wr(Waddr);
    127.     I2C1_Is_Idle();
    128.     I2C1_Wr(hi_n | rs | 0x04 | 0x08);
    129.     I2C1_Is_Idle();
    130.     Delay_us(50);
    131.     I2C1_Wr(hi_n | rs | 0x00 | 0x08);
    132.     I2C1_Is_Idle();
    133.     Delay_us(100);
    134.     I2C1_Wr(lo_n | rs | 0x04 | 0x08);
    135.     I2C1_Is_Idle();
    136.     Delay_us(50);
    137.     I2C1_Wr(lo_n | rs | 0x00 | 0x08);
    138.     I2C1_Is_Idle();
    139.     I2C1_stop();
    140. }
    141.  
    142.  
    143. void I2C_LCD_Init() {
    144.  
    145.     char rs = 0x00;
    146.  
    147.     I2C1_Start();
    148.     I2C1_Is_Idle();
    149.     I2C1_Wr(Waddr);
    150.     I2C1_Is_Idle();
    151.  
    152.     Delay_ms(30);
    153.  
    154.     I2C1_Wr(0x30 | rs | 0x04 | 0x08);
    155.     I2C1_Is_Idle();
    156.     Delay_us(50);
    157.     I2C1_Wr(0x30 | rs | 0x00 | 0x08);
    158.     I2C1_Is_Idle();
    159.  
    160.     Delay_ms(10);
    161.  
    162.     I2C1_Wr(0x30 | rs | 0x04 | 0x08);
    163.     I2C1_Is_Idle();
    164.     Delay_us(50);
    165.     I2C1_Wr(0x30 | rs | 0x00 | 0x08);
    166.     I2C1_Is_Idle();
    167.  
    168.     Delay_ms(10);
    169.  
    170.     I2C1_Wr(0x30 | rs | 0x04 | 0x08);
    171.     I2C1_Is_Idle();
    172.     Delay_us(50);
    173.     I2C1_Wr(0x30 | rs | 0x00 | 0x08);
    174.     I2C1_Is_Idle();
    175.  
    176.     Delay_ms(10);
    177.  
    178.     I2C1_Wr(0x20 | rs | 0x04 | 0x08);
    179.     I2C1_Is_Idle();
    180.     Delay_us(50);
    181.     I2C1_Wr(0x20 | rs | 0x00 | 0x08);
    182.     I2C1_Is_Idle();
    183.     I2C1_Stop();
    184.  
    185.     Delay_ms(10);
    186.  
    187.     I2C_LCD_Cmd(0x28);
    188.     I2C_LCD_Cmd(0x06);
    189. }
    190.  
    191. void I2C_LCD_Out(char row, char col, char *text) {
    192.     while(*text)
    193.          I2C_LCD_Chr(row, col++, *text++);
    194. }
    195.  
    196. void I2C_LCD_Out_Cp(char *text) {
    197.     while(*text)
    198.          I2C_LCD_Chr_Cp(*text++);
    199. }
    200.  
    201. void main() {
    202.  
    203.     APFCON = 0x00;
    204.     ANSELA = 0x00;
    205.     CM1CON0 = 0x00;
    206.     TRISA = 0x00;
    207.     PORTA = 0x00;
    208.     LATA = 0x00;
    209.  
    210.     asm clrwdt
    211.  
    212.     I2C1_Init(100000);
    213.  
    214.     I2C_LCD_Init();
    215.     I2C_LCD_Cmd(_LCD_CURSOR_OFF);
    216.     I2C_LCD_Cmd(_LCD_CLEAR);
    217.  
    218.     I2C_LCD_Out(1,1,message1);
    219.     I2C_LCD_Out(2,1,message2);
    220.     I2C_LCD_Out(3,1,CopyConst2Ram(msg, message3));
    221.     I2C_LCD_Out(4,1,CopyConst2Ram(msg, message4));
    222.  
    223.     while(1) {
    224.  
    225.     }
    226. }
    227.  
    Software I2C LCD Code

    Code (C):
    1.  
    2. #define _LCD_FIRST_ROW          0x80     //Move cursor to the 1st row
    3. #define _LCD_SECOND_ROW         0xC0     //Move cursor to the 2nd row
    4. #define _LCD_THIRD_ROW          0x94     //Move cursor to the 3rd row
    5. #define _LCD_FOURTH_ROW         0xD4     //Move cursor to the 4th row
    6. #define _LCD_CLEAR              0x01     //Clear display
    7. #define _LCD_RETURN_HOME        0x02     //Return cursor to home position, returns a shifted display to
    8.                                          //its original position. Display data RAM is unaffected.
    9. #define _LCD_CURSOR_OFF         0x0C     //Turn off cursor
    10. #define _LCD_UNDERLINE_ON       0x0E     //Underline cursor on
    11. #define _LCD_BLINK_CURSOR_ON    0x0F     //Blink cursor on
    12. #define _LCD_MOVE_CURSOR_LEFT   0x10     //Move cursor left without changing display data RAM
    13. #define _LCD_MOVE_CURSOR_RIGHT  0x14     //Move cursor right without changing display data RAM
    14. #define _LCD_TURN_ON            0x0C     //Turn Lcd display on
    15. #define _LCD_TURN_OFF           0x08     //Turn Lcd display off
    16. #define _LCD_SHIFT_LEFT         0x18     //Shift display left without changing display data RAM
    17. #define _LCD_SHIFT_RIGHT        0x1E     //Shift display right without changing display data RAM
    18.  
    19. #define  Waddr 0x4E
    20.  
    21. sbit Soft_I2C_Scl           at GP0_bit;
    22. sbit Soft_I2C_Sda           at GP1_bit;
    23. sbit Soft_I2C_Scl_Direction at TRISIO0_bit;
    24. sbit Soft_I2C_Sda_Direction at TRISIO1_bit;
    25.  
    26. /*   LCD_I2C found with PCF8574
    27.          P7,P6,P5,P4 of PCF8574 = MSbits DB7,DB6,DB5,DB4 of LCD Display.
    28.          P3 is hardware display bit (BackLight : 1 = on / 0 = off)
    29.          P2 is hardware E display bit clock : E = 1 -> E = 0 active
    30.          P1 is R/W hardware Read/Write bit hardware : Read = 1 / Write = 0
    31.          P0 is RS hardware Register Select : CmdReg = 0 / DataReg = 1
    32. */
    33.  
    34. char msg[21];
    35. char message1[] = "Software I2C LCD";
    36. char message2[] = "16x2, 20x2, 20x4";
    37. const char message3[] = "PIC12F683";
    38. const char message4[] = "mikroC PRO PIC";
    39.  
    40. //copy const to ram string
    41. char *CopyConst2Ram(char *dest, const char *src) {
    42.     char *d;
    43.  
    44.     asm clrwdt
    45.     d = dest;
    46.     for(;*dest++ = *src++;)asm clrwdt;
    47.     asm clrwdt
    48.     return d;
    49. }
    50.  
    51. void Soft_I2C_LCD_Cmd(char out_char) {
    52.  
    53.     char hi_n, lo_n;
    54.     char rs = 0x00;
    55.    
    56.     hi_n = out_char & 0xF0;
    57.     lo_n = (out_char << 4) & 0xF0;
    58.  
    59.     Soft_I2C_Start();
    60.     Soft_I2C_Write(Waddr);
    61.     Soft_I2C_Write(hi_n | rs | 0x04 | 0x08);
    62.     Delay_us(50);
    63.     Soft_I2C_Write(hi_n | rs | 0x00 | 0x08);
    64.     Delay_us(100);
    65.     Soft_I2C_Write(lo_n | rs | 0x04 | 0x08);
    66.     Delay_us(50);
    67.     Soft_I2C_Write(lo_n | rs | 0x00 | 0x08);
    68.     Soft_I2C_Stop();
    69.  
    70.     if(out_char == 0x01)Delay_ms(2);
    71. }
    72.  
    73. void Soft_I2C_LCD_Chr(char row, char column, char out_char) {
    74.  
    75.     char hi_n, lo_n;
    76.     char rs = 0x01;
    77.  
    78.     switch(row){
    79.  
    80.         case 1:
    81.         Soft_I2C_LCD_Cmd(0x80 + (column - 1));
    82.         break;
    83.         case 2:
    84.         Soft_I2C_LCD_Cmd(0xC0 + (column - 1));
    85.         break;
    86.         case 3:
    87.         Soft_I2C_LCD_Cmd(0x94 + (column - 1));
    88.         break;
    89.         case 4:
    90.         Soft_I2C_LCD_Cmd(0xD4 + (column - 1));
    91.         break;
    92.     };
    93.  
    94.     hi_n = out_char & 0xF0;
    95.     lo_n = (out_char << 4) & 0xF0;
    96.  
    97.     Soft_I2C_Start();
    98.     Soft_I2C_Write(Waddr);
    99.     Soft_I2C_Write(hi_n | rs | 0x04 | 0x08);
    100.     Delay_us(50);
    101.     Soft_I2C_Write(hi_n | rs | 0x00 | 0x08);
    102.     Delay_us(100);
    103.     Soft_I2C_Write(lo_n | rs | 0x04 | 0x08);
    104.     Delay_us(50);
    105.     Soft_I2C_Write(lo_n | rs | 0x00 | 0x08);
    106.     Soft_I2C_Stop();
    107. }
    108.  
    109. void Soft_I2C_LCD_Chr_Cp(char out_char) {
    110.  
    111.     char hi_n, lo_n;
    112.     char rs = 0x01;
    113.  
    114.     hi_n = out_char & 0xF0;
    115.     lo_n = (out_char << 4) & 0xF0;
    116.  
    117.     Soft_I2C_Start();
    118.     Soft_I2C_Write(Waddr);
    119.     Soft_I2C_Write(hi_n | rs | 0x04 | 0x08);
    120.     Delay_us(50);
    121.     Soft_I2C_Write(hi_n | rs | 0x00 | 0x08);
    122.     Delay_us(100);
    123.     Soft_I2C_Write(lo_n | rs | 0x04 | 0x08);
    124.     Delay_us(50);
    125.     Soft_I2C_Write(lo_n | rs | 0x00 | 0x08);
    126.     Soft_I2C_Stop();
    127. }
    128.  
    129.  
    130. void Soft_I2C_LCD_Init() {
    131.  
    132.     char rs = 0x00;
    133.  
    134.     Soft_I2C_Start();
    135.     Soft_I2C_Write(Waddr);
    136.     Delay_ms(30);
    137.  
    138.     Soft_I2C_Write(0x30 | rs | 0x04 | 0x08);
    139.     Delay_us(50);
    140.     Soft_I2C_Write(0x30 | rs | 0x00 | 0x08);
    141.     Delay_ms(10);
    142.     Soft_I2C_Write(0x30 | rs | 0x04 | 0x08);
    143.     Delay_us(50);
    144.     Soft_I2C_Write(0x30 | rs | 0x00 | 0x08);
    145.     Delay_ms(10);
    146.     Soft_I2C_Write(0x30 | rs | 0x04 | 0x08);
    147.     Delay_us(50);
    148.     Soft_I2C_Write(0x30 | rs | 0x00 | 0x08);
    149.     Delay_ms(10);
    150.     Soft_I2C_Write(0x20 | rs | 0x04 | 0x08);
    151.     Delay_us(50);
    152.     Soft_I2C_Write(0x20 | rs | 0x00 | 0x08);
    153.     Soft_I2C_Stop();
    154.     Delay_ms(10);
    155.  
    156.     Soft_I2C_LCD_Cmd(0x28);
    157.     Soft_I2C_LCD_Cmd(0x06);
    158. }
    159.  
    160. void Soft_I2C_LCD_Out(char row, char col, char *text) {
    161.     while(*text)
    162.          Soft_I2C_LCD_Chr(row, col++, *text++);
    163. }
    164.  
    165. void Soft_I2C_LCD_Out_Cp(char *text) {
    166.     while(*text)
    167.          Soft_I2C_LCD_Chr_Cp(*text++);
    168. }
    169.  
    170. void main() {
    171.  
    172.     CMCON0 = 0x07;
    173.     ANSEL = 0x00;
    174.     TRISIO = 0x00;
    175.     GPIO = 0x00;
    176.  
    177.     Soft_I2C_Init();
    178.  
    179.     Soft_I2C_LCD_Init();
    180.     Soft_I2C_LCD_Cmd(_LCD_CURSOR_OFF);
    181.     Soft_I2C_LCD_Cmd(_LCD_CLEAR);
    182.  
    183.     Soft_I2C_LCD_Out(1,1,message1);
    184.     Soft_I2C_LCD_Out(2,1,message2);
    185.     Soft_I2C_LCD_Out(3,1,CopyConst2Ram(msg, message3));
    186.     Soft_I2C_LCD_Out(4,1,CopyConst2Ram(msg, message4));
    187.  
    188.     while(1) {
    189.  
    190.     }
    191. }
    192.  
     
  4. Wendy

    Moderator

    Mar 24, 2008
    20,764
    2,535
    I can be talked into expanding my horizons, but code without hardware is not really the intent of the Completed Projects Forum. Do you have an actual piece of hardware you can show for it?

    I will take this up with the moderating staff, but do review the link I attached showing the requirements for the Completed Projects Forum.

    Actually, I see you have flagged my post per my suggestion. So the moderators will get on board and we will let you know how it goes.
     
  5. jayanthd

    Thread Starter Member

    Jul 4, 2015
    264
    27
    Doesn't the two images show the hardware ? The banggood.com link shows the PCF8574T module used to convert HD44780 Parallel Interface LCD to I2C LCD. The code provides hardware and software I2C LCD routines. The same code can be used with any PIC microcontrollers and the same circuit can be used with any PIC microcontroller. The two I2C lines connect to either hardware I2C or software I2C lines of any desired PIC. The codes are for mikroC PRO PIC Compiler.
     
  6. ScottWang

    Moderator

    Aug 23, 2012
    4,853
    767
    The project you show on this forum should be easy to let the members who want to duplicated without your help, so you need to write a help file with a practical example that it explain how to use the library, and you also need to attach the photos of two pics hardware, thank you.
     
  7. jayanthd

    Thread Starter Member

    Jul 4, 2015
    264
    27
    Hardware is simple. Use one of these I2C LCDs or the I2C LCD module with HD44780 compatible LCDs.

    http://www.banggood.com/buy/iic-lc.html

    No need for pullups shown in the two images. The pullups are on the I2C module. All you have to do is connect two power supply lines of the I2C module to 5V and GND and SDA and SCL lines to I2C or soft I2C lines of the PIC.
     
  8. ScottWang

    Moderator

    Aug 23, 2012
    4,853
    767
    This forum is for the members who willing to sharing their results, their knowledges, all the project, project can be small or big, but must be let the members know what to do without any help or just a little help.
     
  9. Wendy

    Moderator

    Mar 24, 2008
    20,764
    2,535
    If you have not built this, and can not show it is a proven project, then it can not be posted in the Completed Projects forum. Ideas and concepts do not count, everyone has ideas, and while software is work it is not proven until implemented.
     
  10. jayanthd

    Thread Starter Member

    Jul 4, 2015
    264
    27
    I have tested these projects in hardware. Do you want me to post the photo of the working hardware ? I have used EasyPIC v7 development board and I2C LCD module from Banggood.com to test the projects.
     
  11. dannyf

    Well-Known Member

    Sep 13, 2015
    1,771
    358
    Good work.

    Some suggestions for you to consider:

    1. Put your code in a module (.h / .c files) so that others can easily incorporate your module into their applications.

    2. Give your code more flexibility: the wiring scheme in your code is hard coded -> like D4..D7 on P4..P7, EN on P2, .... It is fairly easy to allow the user to assign pins, either at compile time or run time.

    3. [Optional] Utilize continuous / block writes: for each write, your code incurs i2c overhead (start condition, device address + stop condition) for each byte of data transmitted, via four i2c write operations. So there is a chance to improve the performance by 20% if you were to send the start condition, device addresses, and then follow-up with all the data to be written to the device, followed by a stop condition.

    If you want, I can post my code for this. It's entirely device independent, and sends 16 chars to the lcd in 3 - 3.7ms, over a 40Kbps i2c connection, on a PIC18 with 20Mhz crystal. All for about 600 bytes of foot print. Pin connections fully user configurable.
     
  12. joeyd999

    AAC Fanatic!

    Jun 6, 2011
    2,674
    2,717
    And consider a non-blocking approach, especially during the initialization. There is no reason for the MCU to sit around twiddling its thumbs for in excess of 50ms when it could be initializing something else at the same time.

    In fact, all the microsecond delays you have coded could be eliminated and replaced with a polled state machine thereby freeing up an awful lot of clock cycles for other, unrelated, things. Isn't there a busy flag you can check?

    What is the definition of I2C1_Init() and I2C1_Is_Idle()?
     
  13. dannyf

    Well-Known Member

    Sep 13, 2015
    1,771
    358
    I ported your code to XC, added the ability for the user to configure i2c <-> lcd connection.

    Using XC1.12, 20Mhz 18F4520, 11.5ms per 16 chars, software i2c. Total code size: 780 bytes. Additional room for improvement.

    Considerably slower than mine, but much faster than even the fastest implementation on Arduino.

    Since the code is in C, infinitely portable to any other mcus. Did all of that in 10-15 minutes.
     
  14. dannyf

    Well-Known Member

    Sep 13, 2015
    1,771
    358
    This is the wiring for your typical ebay i2c board, driving a 4-line lcd.
     
Loading...