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

ssd 1306 initialization problem

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



Joined: 27 Apr 2008
Posts: 168

View user's profile Send private message Send e-mail MSN Messenger

ssd 1306 initialization problem
PostPosted: Tue Oct 27, 2015 6:02 am     Reply with quote

Hi there.
The SD1306 datasheet is a mess, poor work done by SOLOMON SYSTECH unfortunately. Well, I am trying to initialize the LCD with horizontal addressing mode, but besides tons of changes and attempts, no positive results!!! The only thing I never tried is to first initialize the LCD, and after that, prior to send data, change the memory access to horizontal, I will give a shot moreover at night.
This is my procedure to initialize the LCD, is there anything wrong with this code? I inform that, apparently, everything works well, besides of no change in memory access that remains always as page access.

Any help or clue will be much appreciated.

Regards.


Code:
void lcd_init()
   {
   restart_wdt();
       i2c_start ();
       i2c_write(lcd_address); //select the display
       i2c_write(lcd_cmd); //we are sending a command
   i2c_write(0xAE); //S_DISPLAYOFF
       i2c_write(0xD5); //S_SETDISPLAYCLOCKDIV
       i2c_write(0x80); //DIV_RATIO
       i2c_write(0xA8); //S_SETMULTIPLEX
       i2c_write(0x3F); //MULTIPLEX 
       i2c_write(0xD3); //S_SETDISPLAYOFFSET
       i2c_write(0x00); //NO OFFSET
       i2c_write(0x7F); //S_SETSTARTLINE
       i2c_write(0x8D); //S_CHARGEPUMP
       i2c_write(0x14); //INT_VCC
       i2c_write(0x20); //Set Memory Addressing Mode
       i2c_write(0b00000000); //P=10 - H=00b - V=01
       i2c_write(0x21); //COLUM REGISTER
   i2c_write(0x00); //START
   i2c_write(0X7F); //END
       i2c_write(0x22); //PAGE REGISTER
       i2c_write(0x02); //START
   i2c_write(0X03); //END
   i2c_write(0xb0);
       i2c_write(0xA1); //S_SEGREMAP
       i2c_write(0xC8); //S_COMSCANDEC
       i2c_write(0xDA); //S_SETCOMPINS
       i2c_write(0x12);
       i2c_write(0x81); //S_SETCONTRAST
       i2c_write(0xFF);
       i2c_write(0xD9);  //S_SETPRECHARGE
       i2c_write(0xF1);
       i2c_write(0xDB); //S_SETVCOMDETECT
       i2c_write(0x40);
       i2c_write(0xA4); //S_DISPLAYALLON_RESUME
   i2c_write(0xA7); //S_NORMALDISPLAY
   i2c_write(0xAF); //S_DISPLAYON
   i2c_stop();
   }
MikeW



Joined: 15 Sep 2003
Posts: 184
Location: Warrington UK

View user's profile Send private message

PostPosted: Tue Oct 27, 2015 6:38 am     Reply with quote

This code works a treat.

just change for your chip, and SDA/SCL pins. no otherr changes are needed.

if it still doesnt work, its a hardware problem such as

pullup resistors etc

http://www.ccsinfo.com/forum/viewtopic.php?t=54453
rudy



Joined: 27 Apr 2008
Posts: 168

View user's profile Send private message Send e-mail MSN Messenger

PostPosted: Tue Oct 27, 2015 6:50 am     Reply with quote

Mike, Thanks.

Anyway, the logo that I am trying to show only appears in the top of the LCD (PAGE 0), like the page access is always running. It don´t seem to me to be a pull up resistor problem, once that commands like Entire LCD on (at the very end of code) works very fine.
I really don´t know what to do, but there is also an RDA5807 FM radio on the line, I will take it out from SDA and SCL pins, and check how it goes.
Thank you.
Regards.
Ttelmah



Joined: 11 Mar 2010
Posts: 19556

View user's profile Send private message

PostPosted: Tue Oct 27, 2015 8:04 am     Reply with quote

If you just want to write a logo, then the 'draw_window' function in my driver, can do this for you. It just writes a block of memory (from the area defined as 'window_buffer' if you are using the graphic functions I supply), directly to any 'cell' location on the display (0-127 x 0-7). The block it transfers is defined by the 'WINDOW_WIDTH' & 'WINDOW_HEIGHT' defines, so easy to change. It is easy to rewrite.

Don't get confused by the layout of the screen. The pixels run vertically down the columns, and you advance to the next column when you get to the bottom. Switching mode will only help you if you are going to fill an entire row or column, which with a small logo is unlikely to happen. This is why the draw_window function calls the address function when it gets to the end of each column it is sending.
rudy



Joined: 27 Apr 2008
Posts: 168

View user's profile Send private message Send e-mail MSN Messenger

PostPosted: Tue Oct 27, 2015 2:24 pm     Reply with quote

Ttelmah, I disagree with you, a little!
Your code is good, no doubt. It clear my mind trough this mess that is the datasheet, unfortunately, and congratulations to you to find a way in this confusion.
I see that there are three different ways to address the LCD. This three ways, in my understanding, is for avoid you to move large quantities of data every time you need to update the LCD information. The horizontal and vertical memory data access is exactly to do this, depending only of the way you draw your initial image. Once you move the entire LCD initial information, with a little quantity of code, you can access any particular portion of the LCD, making small changes where needed, it is poor mentioned in datasheet, but for sure it does this.
I am sure that, once that I discover how to change this memory access mode, I will be able to do what I need. It is almost what you did in the “draw_window” function, but it is slight different. When finish I will update my approach.
Thank all anyway.
Ttelmah



Joined: 11 Mar 2010
Posts: 19556

View user's profile Send private message

PostPosted: Tue Oct 27, 2015 3:08 pm     Reply with quote

Where I disagree with you is in using horizontal address mode.

Problem is that since the data is organized vertically in the display, you end up writing eight bits vertically, then moving horizontally, across the row, and then going back to continue the next row of the character. I'd suggest that it is much easier to use the vertical mode, and complete each column in turn.
I'd say that horizontal mode only makes sense, when the display is operating rotated the other way.

Then you need to ensure that the limits are turned off after your logo is written, otherwise any subsequent write is going to wrap again.

I'd also split things up. Set the unit up, then change modes.
For instance, this is my 'contrast change' routine:
Code:

void OLED_contrast(int8 contrast)
//Set the display current
{
   i2c_start();
   i2c_write(SSDADDR);
   i2c_write(COMMAND_ONLY);
   i2c_write(S_SETCONTRAST);
   i2c_write(contrast);
   i2c_stop();
}

Just change the mode, set the address, write the data, and set the mode back.
You also don't tell us the definitions for some of the commands you are sending?. 'COMMAND_ONLY' (in your code lcd_cmd), has to be 0, for the successive commands to work right. 0x80, which can also be used, stops the successive initialisations from working properly, when they are burst transmitted.
rudy



Joined: 27 Apr 2008
Posts: 168

View user's profile Send private message Send e-mail MSN Messenger

PostPosted: Tue Oct 27, 2015 3:31 pm     Reply with quote

Kkk (Leffen), ok. (This is a very good discussion, but allow me to disagree again.)
From my point of view, in VERTICAL access mode, you can go through, for example, COL 0 to COL 7 straight, in this case there shall be 64 bits directly. I see that vertical and horizontal depends only of your graphic design, better, how you generate the array of bits (bytes) to be send to LCD, just that.
Anyway, give me some time to deep check this issue, I may be wrong also. The good thing is that for sure this will help lots of people who seek for information about this subject.
Regards.
Ttelmah



Joined: 11 Mar 2010
Posts: 19556

View user's profile Send private message

PostPosted: Tue Oct 27, 2015 3:38 pm     Reply with quote

The display always _outputs_ the data one byte at a time organised vertically (in the standard organisation). You don't get 64 bits across a row, you get 64 (or 128) bytes across the row, each carrying 8 bits vertically.
So you can't send 64 bits sequentially along a row (it'd be lovely if you could). Look carefully at the output diagrams showing how the drive bits are derived from the bytes. The horizontal/vertical modes, change how you increment through the bytes, when sequential ones are sent, not how the bytes are organised on the display. Since the bytes are organised vertically, I prefer to finish each column in turn.
rudy



Joined: 27 Apr 2008
Posts: 168

View user's profile Send private message Send e-mail MSN Messenger

PostPosted: Wed Oct 28, 2015 5:10 pm     Reply with quote

Ttelmah, good day!

Well, I was right!!!!

I also discovered an error in the “MESS” datasheet (How many must have more..). The error is at page 34, concerning with PAGE access, as follows:

Where you read “Set the lower start column address of pointer by command 00h~0Fh.”

You must note that first segment (column) is not 0x00, but 0x01, this is also valid for 0x0F, the end column number is 0x7f or 0x80 (not tested the end column number)

Also, where you read “Set the upper start column address of pointer by command 10h~1Fh” it shall be exactly as above, someone please test all situations and update the forum. I will do it myself, but don't know when.

Regarding with the issue of PAGE, HORIZONTAL and VERTICAL Addressing mode. What I was trying to explain is that I should be able to move 1024 bytes of information in a single shot, if I started by using H or V addressing modes, depending only of the way my image was build. You can use LCDAssistant or FastLCd to do your logos, I use Windows Paint to draw and LCDAssistant to convert bitmap to my array. FastLcd don't work fine.

In my case, after initialization, you can see two lines of code, i2c_write(0x20); and i2c_write(0x00);.
The first, I am accessing register 0x20, that handles the memory access mode, the second, I move 0x00, changing to H memory access mode. Once I did that, I could move the entire 1024 bytes in just one loop, avoiding to move 128 bytes, change page, plus 128bytes and change page again till end of page 7, so my code is very light and fast.

Of course I will need to access other specific parts of the LCD, but now, and only now I will have to deal with PAGE, COLUMNS and so on, just to rebuild small parts of the image.

Try this simple example by yourself and check how it goes.

Hope to that this code helps more peoples.
Code:
#include <16f688.h>
#fuses INTRC_IO, NOWDT, NOPROTECT, NOBROWNOUT, NOMCLR, NOCPD, PUT        //304C 342C
#use delay(clock = 4000000, RESTART_WDT)
#use i2c(MASTER, FAST, SDA=PIN_C5, SCL=PIN_C4, FORCE_HW)
// #include <string.h>
//#include <stdlib.h>
#define lcd_cmd 0b00000000 //next byte is a command only
#define lcd_data 0b01000000 //next byte is data
#define lcd_address 0x78 //address for the chip - usually 0x7C or 0x78.
int page = 200;


 const int logo[1024] =
 {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x78, 0xC8, 0x08, 0x08, 0x08, 0x08, 0x0C, 0x04, 0x04, 0xFC, 0xFC, 0x04, 0x04, 0x04, 0x06,
   0x02, 0x02, 0x02, 0x0E, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x18, 0x18, 0x18, 0x18,
   0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xC0, 0x80,
   0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x00,
   0x80, 0xC0, 0xE0, 0xE0, 0xF8, 0x38, 0x38, 0x18, 0x08, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00,
   0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0xF8, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
   0xE0, 0xF0, 0xF8, 0x38, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x38, 0xF8, 0xF8, 0xE0, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x1F, 0xF0, 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x09, 0x7F, 0xFC, 0x0C, 0x0C, 0x0C,
   0x0C, 0x04, 0x04, 0x04, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0C, 0x0C, 0x0C, 0x0C,
   0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0x07, 0x1F,
   0x3E, 0xFC, 0xF0, 0xE0, 0x80, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3C, 0x1E, 0x0F,
   0x1F, 0x3F, 0x7D, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0xC1, 0xC3, 0x87, 0x07, 0x0E, 0x0E, 0x0E, 0x1C, 0x1C, 0x1C, 0x3C, 0xF8, 0xF0, 0xE0, 0x00, 0x00,
   0x00, 0x00, 0x80, 0xBF, 0xA0, 0xA0, 0xA0, 0xB0, 0x90, 0x90, 0x90, 0x90, 0x9F, 0x9C, 0x98, 0x88,
   0x88, 0x88, 0x88, 0x88, 0x88, 0x8B, 0x8E, 0x80, 0x80, 0x8F, 0x8F, 0x8F, 0x80, 0x80, 0x80, 0x80,
   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x83, 0x87, 0x8F, 0x8E, 0x8C, 0x8C, 0x8C,
   0x8C, 0x8E, 0x8F, 0x87, 0x87, 0x81, 0x80, 0x80, 0x80, 0x8F, 0x8F, 0x8F, 0x80, 0x80, 0x80, 0x80,
   0x80, 0x80, 0x81, 0x83, 0x8F, 0x8F, 0x8F, 0x8F, 0x80, 0x80, 0x80, 0x8F, 0x8F, 0x80, 0x80, 0x80,
   0x80, 0x80, 0x80, 0x81, 0x83, 0x87, 0x8F, 0x8E, 0x8C, 0x80, 0x80, 0x8F, 0x8F, 0x8F, 0x80, 0x80,
   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x8F, 0x8F, 0x8F, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
   0x83, 0x87, 0x8F, 0x8E, 0x8E, 0x8C, 0x8C, 0x8C, 0x8C, 0x8E, 0x8F, 0x87, 0x83, 0x81, 0x00, 0x00,
   0x00, 0x00, 0xF2, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x02, 0x02, 0x02, 0xF2, 0x02,
   0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0xF2, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
   0x12, 0x12, 0x02, 0x02, 0x02, 0x02, 0x02, 0xC2, 0x22, 0x12, 0x12, 0x12, 0x12, 0x12, 0x22, 0x42,
   0x02, 0x02, 0x12, 0x12, 0x12, 0x12, 0xF2, 0x12, 0x12, 0x12, 0x12, 0x02, 0x02, 0xF2, 0x12, 0x12,
   0x12, 0x12, 0x12, 0x12, 0xE2, 0x02, 0x02, 0x02, 0xC2, 0x22, 0x22, 0x12, 0x12, 0x12, 0x12, 0x12,
   0x22, 0x22, 0xC2, 0x02, 0x02, 0x02, 0xF2, 0x22, 0x22, 0xC2, 0x02, 0x02, 0x02, 0x02, 0xF2, 0x02,
   0x02, 0x02, 0x02, 0xF2, 0xF2, 0x02, 0x02, 0x02, 0x02, 0xC2, 0x22, 0x12, 0x12, 0x12, 0x12, 0x12,
   0x22, 0x42, 0x02, 0x02, 0x02, 0xE2, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x62, 0x00, 0x00,
   0x00, 0x00, 0x3F, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x3F, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
   0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x08,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x02, 0x02,
   0x02, 0x02, 0x06, 0x1A, 0x21, 0x00, 0x00, 0x00, 0x0F, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x10, 0x10, 0x0F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x03, 0x0C, 0x0C, 0x10, 0x3F, 0x00,
   0x00, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x10, 0x08, 0x00, 0x00, 0x00, 0x18, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };

void lcd_init()
   {
   restart_wdt();
    i2c_start ();
    i2c_write(lcd_address); //select the display
    i2c_write(lcd_cmd); //we are sending a command
   i2c_write(0xAE); //set LCD off
    i2c_write(0xD5); //set LCD clock div
    i2c_write(0x80); //set LCD osc frequency
    i2c_write(0xA8); //set LCD mux
    i2c_write(0x3F); //set LCD mux
    i2c_write(0xD3); //set LCD offset
    i2c_write(0x00); //set no offset
    i2c_write(0x40); //set LCD start line
    i2c_write(0x8D); //set LCD charge pump
    i2c_write(0x14); //set charge pump vcc 
    i2c_write(0xA1); //set LCD remap
    i2c_write(0xC8); //set scan direction
    i2c_write(0xDA); //set com pins
    i2c_write(0x12); //set com pins
    i2c_write(0x81); //set LCD contrast
    i2c_write(0xCF); //set LCD contrast
    i2c_write(0xD9); //set LCD pre charge
    i2c_write(0xF1); //set LCD pre charge
    i2c_write(0xDB); //set vcon detect
    i2c_write(0x40); //set vcon detect
    i2c_write(0xA4); //set LCD all on = A5
   i2c_write(0xA6); //set LCD normal=A6 inverse = A7
   i2c_write(0xAF); //set display on=AF off=AE
   i2c_write(0x20); //access memory mode
    i2c_write(0x00); //switch for H mode
   i2c_stop();
   }

 void lcd_write()
    {
    long i;
    i2c_start ();
    i2c_write(lcd_address); //select the display
    i2c_write(lcd_data) ;
    for (i=0; i<1024; i++)
       {
      restart_wdt();
        i2c_write(logo[i]) ;
         }
    i2c_stop();
   }

 void main()
   {
   lcd_init();
loop:
   while(page==190)
      {
      restart_wdt();
      }
   while(page==200) //start
      {
      restart_wdt();
      lcd_write();   
      page=190;
      }
   goto loop;
   }
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Oct 29, 2015 2:38 am     Reply with quote

Thanks for sharing your code and putting in all the effort.

Just a few remarks, not related to your issue but will make you a better programmer:
1) Using the goto command is considered bad programming as it soon leads to spaghetti code. The command is in the C-language to make it possible to create special code like exception handlers. I'm not a hardliner against the use of 'goto' as I used to be, but for situations like here it is the wrong solution.

2) Why use a watchdog? In my experience they cause more problems than they solve. Only when no user is present to reset your device it makes sense having a watchdog. In all other cases they cause code clutter and hard to find problems.

3)
Code:
   while(page==190)
      {
      restart_wdt();
      }
This will loop forever. If that's intentional, then your program can be simplified by a 'while(TRUE){}' which also shows your intention more clearly.

Considering all above, your main routine can be reduced to:
Code:
void main()
{
   lcd_init();
   lcd_write();

   while(TRUE){};
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19556

View user's profile Send private message

PostPosted: Thu Oct 29, 2015 3:38 am     Reply with quote

What I have to ask (still) is why you were fiddling with the mode?.
To burst transmit 1024 bytes, you only need to set the write address to 0, and write 1024 bytes. Nothing else needed. No mode changes etc..

This is what my OLED_CLS function does. It writes 1024 bytes (assuming the display is 128*64) of either all 1's or all 0's (depending if you have the display inverted), straight to the display.
rudy



Joined: 27 Apr 2008
Posts: 168

View user's profile Send private message Send e-mail MSN Messenger

PostPosted: Thu Oct 29, 2015 4:34 am     Reply with quote

Answering ckielstra!

Thanks, I know this is not the best way, but I learn this way and so now I could not change. For each value of page I write some code to do something different.

I don´t know, it seems more structured to me I guess, that´s why I never changed the way I write. But thank you anyway.

Regarding with WDT, I never had problems with it, and always leave it running to restart CPU if any crash happens.

The code is not finished yet, so there will be more "pages" to hold all the functions needed. Please don´t blame me, everybody says it is wrong, it is not the first time I heard that, but works for me.

Answering Ttelmah.

In fact, I had some trouble to true understand your code, my stupidity only, I am not so skilled C writer.

I had tried the burst transmission you provided, but there is some other functions that is needed to change page address and so on. When you write to more powerful processors, there may be more ram memory. In my case, for 16F688, there is not.

So I trying to enjoy the fact that the pointer is automatically updated when you reach the end of page columns, avoid more codes to do this, that´s why.

I soon discover some problems that I will try to solve moreover with H or V address mode, for example after a power up. Today morning, before I left to work, I turned on the power, and the display only was updated on the first page (PAGE=0).

It seems to me that something still need to be done at the lcd_init() code. As soon as I find out I will update the final code.

Thanks all!
Ttelmah



Joined: 11 Mar 2010
Posts: 19556

View user's profile Send private message

PostPosted: Thu Oct 29, 2015 5:07 am     Reply with quote

The pointer does this all the time. No need to change anything!.
Also look at how I send the initialisation. No need for loads of separate calls, I just write the data straight from a ROM array.
rudy



Joined: 27 Apr 2008
Posts: 168

View user's profile Send private message Send e-mail MSN Messenger

PostPosted: Fri Oct 30, 2015 5:52 am     Reply with quote

Ttelmah, you are right.

Checking your code I could see 0x20 plus 0x00, indicating that your code also pointed to H address mode. Unfortunately, my LCD module stops to answer to this command, it simple just don’t change more for H or V address mode, just remain fixed in 0x02 that is PAGE address.
I cannot wait long time to receive another one, to check if it is a problem in my code or some damage to the module itself, so I moved to work with PAGE address mode only.
I will check if others registers may have something with this issue, like clock, mux and so one. Anyway, moreover I will post my code to share with all.
Regards.
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