Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Interfacing an OLED to PIC18F4550

Status
Not open for further replies.

Hero.sl

New Member
Hi folks,
I've been working in this project where I have to send a video stream from a PC to a display. I'm using Densitron 160x128 65/252k OLED (Driver:SEPS525) module for some reasons. The famous 18F4550 is handling the interfacing part.
Without further I do, I present my progress :)


Currently I'm just sending a list of full frames (160x128x16bit) via the USB using my PC app which I developed using C#. The device acts like a generic USB device.
The OLED is connected to the PIC mainly via the SPI port. It consumes few other GPIOs too. The PIC is running @ 48MHz with PLL.

I'm experience a slow frame rate when I'm filling up the RAM of the OLED.(Not related to the above video) It is stated that the SPI can go up to 12Mbit/s in the datasheet. Is this because something wrong with the SPI config or because I'm having little processing (only Loops..) in between the SPI calls?

Tell me if I missed anything in this long post. And please feel free to advice me on my design, I'm not an embedded expert. Thank you

Code:
// CCS C 
// Main function
// OLED Initialization

setup_spi(SPI_MASTER|SPI_H_TO_L|SPI_CLK_DIV_4);  // Div by 4 to get the max rate

while(1){
      for(i=0;i<128;i++)
      {
         for(j=0;j<160;j++)
         {
            Write_Data(0xF8);          // Sending : 11111000 00000000 = Red
            Write_Data(0x00);
         }
      }
      // Fill another color
}

void Write_Data(unsigned char Data)
{
   output_low(CS);     
   output_high(DC);
   
   spi_write(Data);
   
   output_high(CS);     
   output_high(DC);
}
 
Last edited by a moderator:
Can you post more code like the actual config line... It should be working at about 12mhz so it maybe a config line issue ... there are many config types since this is a USB uC also... It makes it a hassle,,, I would recommend the 18F4620
 
Thanks for you response. These are the config settings I'm using

Code:
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HSPLL                    //High Speed Crystal/Resonator with PLL enabled
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES NOPUT                    //No 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 IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOPBADEN                 //NO PORTB pins are configured as analog input channels 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 LPT1OSC                  //Timer1 configured for low-power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL5                     //Divide By 5(20MHz oscillator input)
#FUSES CPUDIV1                  //No System Clock Postscaler
#FUSES USBDIV                   //USB clock source comes from PLL divide by 2
#FUSES VREGEN                   //USB voltage regulator enabled
#FUSES ICPRT                    //ICPRT enabled

Following is the corresponding asm code to the write_data()
Code:
[COLOR="green"].................... void Write_Data(unsigned char Data)[/COLOR]
[COLOR="green"].................... { [/COLOR]
[COLOR="green"]....................    output_low(CS);[/COLOR]      
[COLOR="red"]006A:  BCF    F89.0[/COLOR]
[COLOR="green"]....................    output_high(DC); [/COLOR]
[COLOR="red"]006C:  BSF    F89.1[/COLOR]
[COLOR="green"]....................     
....................    spi_write(Data); [/COLOR]
[COLOR="red"]006E:  MOVF   FC9,W
0070:  MOVFF  0E,FC9
0074:  RRCF   FC7,W
0076:  BNC   0074[/COLOR]
[COLOR="green"]....................     
....................    output_high(CS); [/COLOR]     
[COLOR="red"]0078:  BSF    F89.0[/COLOR]
[COLOR="green"]....................    output_high(DC); [/COLOR]
[COLOR="red"]007A:  BSF    F89.1[/COLOR]
[COLOR="green"].................... } [/COLOR]
[COLOR="red"]007C:  RETLW  00[/COLOR]

And this is for nested for loops
Code:
[COLOR="green"].................... void Write_Data(unsigned char Data) 
.................... { 
....................    output_low(CS);    [/COLOR]  
[COLOR="red"]006A:  BCF    F89.0[/COLOR]
[COLOR="green"]....................    output_high(DC); [/COLOR]
[COLOR="red"]006C:  BSF    F89.1[/COLOR]
[COLOR="green"]....................     
....................    spi_write(Data); [/COLOR]
[COLOR="red"]006E:  MOVF   FC9,W
0070:  MOVFF  0E,FC9
0074:  RRCF   FC7,W
0076:  BNC   0074[/COLOR]
[COLOR="green"]....................     
....................    output_high(CS)[/COLOR];      
[COLOR="red"]0078:  BSF    F89.0[/COLOR]
[COLOR="green"]....................    output_high(DC); [/COLOR]
[COLOR="red"]007A:  BSF    F89.1[/COLOR]
[COLOR="green"].................... } [/COLOR]
[COLOR="red"]007C:  RETLW  00[/COLOR]

If my rough calculations are correct, it would nearly take 100ms for a single frame to be drawn. Well that proves the result I got practically. But I'm still wondering whether I need a higher speed MCU or a redesign.
 
Last edited:
I'm using PLL unit to generate a higher frequency clock source(48MHz) for the core. This PIC has a PLL which generates 96MHz clock from a fixed input of 4MHz. I have a 20MHz crystal connected to the PIC and configured it in the HSPLL mode. What "#FUSES PLL5" (PLL prescaler) does is that it will divide 20MHz clock input by 5 and provide the 4MHz fixed input required by the PLL.

#FUSES CPUDIV1 (PLL postscaler) setting is responsible for dividing the PLL freq of 96MHz by 2 to get the 48MHz clock which is the maximum supported frequency.
 
i dont see anything wrong . Maybe its just too slow. but check this out:

Code:
CPUDIV1:CPUDIV0: System Clock Postscaler Selection bits
For XT, HS, EC and ECIO Oscillator modes:
11 = Primary oscillator divided by 4 to derive system clock
10 = Primary oscillator divided by 3 to derive system clock
01 = Primary oscillator divided by 2 to derive system clock
00 = Primary oscillator used directly for system clock (no postscaler)
For XTPLL, HSPLL, ECPLL and ECPIO Oscillator modes:
11 = 96 MHz PLL divided by 6 to derive system clock
10 = 96 MHz PLL divided by 4 to derive system clock
01 = 96 MHz PLL divided by 3 to derive system clock
00 = 96 MHz PLL divided by 2 to derive system clock
Since we are using HSPLL we need to divide by 2 so try this:

Code:
#FUSES CPUDIV2               	//System Clock by 2

Since both should represent 00 it shouldnt change really but hey you never know
 
Last edited:
Just a dot

I can see that your code is very simple (that gives me some hope to draw a few lines or boxes), is that all? Lets supose that you want to draw a single dot in a spesific zone of the screen, all you need is to wait untill the V and H clocks to reach the zone were you want to draw the dot? and just send 11110101... to draw the specific color? (keeping in mind that in the next cicle it will be erased). I don worry about the refresh rate because all I want is to draw something very basic to control. Thaks a lot
 
hey jjpl2001
Actually 'just a dot' is very simple than that. You don't have to think about H and V signals. The reason is that this OLED comes with a driver IC which does all the hard work for you. All you need to do is to go through the datasheet of the driver and learn how to communicate with it. For you requirement, there are several possible ways. You can set the start position of drawing (Display Offset) and send data for a pixel. Or you can send a set of pixel data to draw on the entire screen in which you can color the pixel you want.

that gives me some hope to draw a few lines or boxes
Oh yea. If you're using a display with a driver and if you have decent processing speed, you can go for complex graphics.

@AtomSoft : I shifted to parallel communication. Now the frame rate is nearly doubled. Now I'm pretty sure than a 12MIPS processor cannot go beyond that. I decided to use a PIC32 since I may have to do some image decoding in order to speed up the USB link. It got me several days to get the PIC32 working as I'm using a 'messy' board built by myself and this is the first time I'm working with a 32bit one.
 
Last edited:
Hi , I have a similar module that I want to connect to a PIC or dsPIC but I have little knowledge .
Can you help me with some info :
How do you supply the module ( different voltages and OLED-drive voltage) ?
What is the best communication ( SPI or 8- or 16-bit parallel ) ?
What pic is best for this ( 3V3 ?) ? and speed ?
Can you share the initialization routines ?

best regards,
ctd
 
Status
Not open for further replies.

Latest threads

Back
Top