ATMega16L and Nokia5110 LCD

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I made a test program wich shoul fill alll the LCD with black pixels. It doesn't work. Back light turns on but nothing happens. Here's the code:

 

#include <avr/io.h>
#define F_CPU 40000UL  //4 MHz
#include <math.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>


typedef struct
{
	unsigned int bit0:1;
	unsigned int bit1:1;
	unsigned int bit2:1;
	unsigned int bit3:1;
	unsigned int bit4:1;
	unsigned int bit5:1;
	unsigned int bit6:1;
	unsigned int bit7:1;
} _io_reg;

#define REGISTER_BIT(rg,bt)((volatile _io_reg*)&rg)->bit##bt


#define LCD_RST REGISTER_BIT(PORTB,0)
#define LCD_DC REGISTER_BIT(PORTB,1)
#define SS_LCD REGISTER_BIT(PORTB,2)

	int main(void)
	{
		DDRB=0b10110111;
		SS_LCD=1;
		
		SPCR |=(1<<SPE)| (1<<MSTR)|(1<SPR0)|(1<<SPIE);
		sei();
		LCD_RST=0;
		sleep1ms();
		LCD_RST=1;
		
		//LCD_DC=1;
		SS_LCD=0;
		LCD_DC=0;
		SPDR=0x21; // LCD Extended Commands.
		sleep();
		temp=SPDR;
		SS_LCD=1;
		sleep250us();
		
		SS_LCD=0;
		SPDR= 0xB1; // Set LCD Vop (Contrast). //0xB0 for 5V, 0XB1 for 3.3v, 0XBF if screen too dark
		sleep();
		temp=SPDR;
		SS_LCD=1;
		sleep250us();
		
		SS_LCD=0;
		SPDR=0x04; // Set Temp coefficient. //0x04
		sleep();
		temp=SPDR;
		SS_LCD=1;
		sleep250us();
		
		SS_LCD=0;
		SPDR=0x13; // LCD bias mode 1:48.
		sleep();
		temp=SPDR;
		SS_LCD=1;
		sleep250us();
		
		SS_LCD=0;
		SPDR=0x0C; // LCD in normal mode. 0x0d for inverse
		sleep();
		temp=SPDR;
		SS_LCD=1;
		sleep250us();
		
		SS_LCD=1;
		SPDR=0x20; // We must send 0x20 before modifying the display control mode
		sleep();
		temp=SPDR;
		SS_LCD=1;
		sleep250us();
		
		SS_LCD=0;
		SPDR=0x0C; // Set display control, normal mode. 0x0D for inverse, 0x0C for normal
		sleep();
		temp=SPDR;
		SS_LCD=1;
		sleep250us();
		
		
		while(1)
		{
			SS_LCD=0;
			LCD_DC=1;
			SPDR=0xFF;
			sleep();
			SS_LCD=1;
			sleep1s();
						

		}
	}


	void sleep()
	{
		
		// Choose our preferred sleep mode:
		set_sleep_mode(SLEEP_MODE_IDLE);
		
		// Set sleep enable (SE) bit:
		sleep_enable();
		
		// Put the device to sleep:
		sleep_mode();
		
		// Upon waking up, sketch continues from this point.
		sleep_disable();
	}
	void sleep1s()
	{
		
		OCR1A=3906;
		TIMSK|=(1<<OCIE1A);
		TCCR1B|=(1<<CS12)|(0<<CS11)|(1<<CS10);
		// Choose our preferred sleep mode:
		set_sleep_mode(SLEEP_MODE_IDLE);
		
		// Set sleep enable (SE) bit:
		sleep_enable();
		
		// Put the device to sleep:
		sleep_mode();
		
		// Upon waking up, sketch continues from this point.
		sleep_disable();
	}
	void sleep1ms()
	{
		
		OCR1A=4;
		TIMSK|=(1<<OCIE1A);
		TCCR1B|=(1<<CS12)|(0<<CS11)|(1<<CS10);
		// Choose our preferred sleep mode:
		set_sleep_mode(SLEEP_MODE_IDLE);
		
		// Set sleep enable (SE) bit:
		sleep_enable();
		
		// Put the device to sleep:
		sleep_mode();
		

		// Upon waking up, sketch continues from this point.
		sleep_disable();
	}
	void sleep250us()
	{
		
		OCR1A=1;
		TIMSK|=(1<<OCIE1A);
		TCCR1B|=(1<<CS12)|(0<<CS11)|(1<<CS10);
		// Choose our preferred sleep mode:
		set_sleep_mode(SLEEP_MODE_IDLE);
		
		// Set sleep enable (SE) bit:
		sleep_enable();
		
		// Put the device to sleep:
		sleep_mode();
		

		// Upon waking up, sketch continues from this point.
		sleep_disable();		
		
	}	
	ISR (TIMER1_COMPA_vect)
	{
		TIMSK &=~(1<<OCIE1A);
		TCCR1B &=~(0<<CS12)|(0<<CS10);
		TCNT1=0;
		
	}
	ISR (SPI_STC_vect)
	{
		
	}

Here's the schematic:

 

 

The microcontroller runs at +5v

This topic has a solution.
Last Edited: Mon. Mar 30, 2015 - 02:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have seen this actually operate

Attachment(s): 

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's a huge code. I fear it's too complex but thanks anyway, I'll try to understand how it works. What about the wiring?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The Nokia display is 3.3V.    The STK500 can be programmed for 3.3V.    The ATmega16L is designed to run at 3.3V.

 

Driving the display is pretty trivial.    After all,  you just want a lcd_init(),  lcd_data() and lcd_cmd() function.    JUst like any other display.

 

Setting or clearing a pixel is described in the data sheet.

 

Yes,   a whole library of graphics functions does look 'big'.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:

The Nokia display is 3.3V.    The STK500 can be programmed for 3.3V.    The ATmega16L is designed to run at 3.3V.

 

Driving the display is pretty trivial.    After all,  you just want a lcd_init(),  lcd_data() and lcd_cmd() function.    JUst like any other display.

 

Setting or clearing a pixel is described in the data sheet.

 

Yes,   a whole library of graphics functions does look 'big'.

 

David.

 

What if i must run atmega16 at 5v? Do I need a voltage divider on each output pin?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I used a voltage divider on each LCD logic pin and I edited my code. Now it's similar to the one posted by bobgardener. It should fill the whole display but...it doesn't work. Again, just the backlight turns on.

Here's the code

 

#include <avr/io.h>
#define F_CPU 40000UL  //4 MHz
#include <math.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>


typedef struct
{
	unsigned int bit0:1;
	unsigned int bit1:1;
	unsigned int bit2:1;
	unsigned int bit3:1;
	unsigned int bit4:1;
	unsigned int bit5:1;
	unsigned int bit6:1;
	unsigned int bit7:1;
} _io_reg;

#define REGISTER_BIT(rg,bt)((volatile _io_reg*)&rg)->bit##bt


#define LCD_RST REGISTER_BIT(PORTB,0)
#define LCD_DC REGISTER_BIT(PORTB,1)
#define SS_LCD REGISTER_BIT(PORTB,2)



int main(void)
{
	ioinit();
	spiinit();
	lcdinit();
	lcdclear();
	lcdfill();

	
	while(1)
	{

		
	}
}

void sleep30ms()
{
	
	OCR1A=120;
	TCCR1B|=(1<<CS12)|(0<<CS11)|(1<<CS10)|(1<<WGM12);


	while(OCF1A==0)
	{
	
	}

	TCCR1B &=~(1<<CS12);
	TCCR1B &=~(1<<CS10);
	TCNT1=0;

}


void ioinit()
{
	DDRB|=(1<<0)|(1<<1)|(1<<2);
}

void spiinit()
{
			//SCK	MOSI	!SS
	DDRB |= (1<<7)|(1<<5)|(1<<4);
		//enable-master-fclk/128
	SPCR =0x53;


}

void lcdinit()
{
	LCD_RST=0;
	sleep30ms();
	LCD_RST=1;
	lcdcommand(0x21);	//extend command
	lcdcommand(0x0B);	//contrast
	lcdcommand(0x04);	//temp coeff
	lcdcommand(0x14);	//bias mode 1:48
	lcdcommand(0x0C);	//lcd in normal mode
	lcdcommand(0x20);	//normal mode
	lcdcommand(0x0C);	//normal display
}

void lcdcommand(char data)
{
	LCD_DC=0;
	SS_LCD=0;
	spiout(data);
	SS_LCD=1;
}

void lcddata(char data)
{
	LCD_DC=1;
	SS_LCD=0;
	spiout(data);
	SS_LCD=1;
}

void spiout(char data)
{
	SPDR=data;
	while(!(SPSR & (1<<SPIF)))
	;

}

void lcdclear()
{
	unsigned int i;

	for(i = 0; i < 504; i++)  
	{
		lcddata(0x00);
	}
}

void lcdfill()
{
	unsigned int i;

	for(i = 0; i < 504; i++)  
	{
		lcddata(0xff);
	}
}

Any idea?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you mean 4 megahertz? Looks like 40 kilohertz to me.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bobgardner wrote:

Did you mean 4 megahertz? Looks like 40 kilohertz to me.

 

Is it about #define F_CPU 40000UL  //4 MHz#define F_CPU 40000UL  //4 MHzthe

#define F_CPU 40000UL  //4 MHz

?

 

The fuses are programmed correctly. Do you think this is the problem? I'll try to correct

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The STK500 can be programmed for 3.3V.

WARNING! Due to it's age the STK500 is likely to forget  the 3.3V setting next time you power it up and may end up with fries.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll show my Nokia 5100 initialization code, in Bascom.

 

Note that at least in my data sheet there appeared to be inconsistencies even within the data sheet on how one should power up and initialize the display!

 

Also, the setup from the data sheet failed!

I ended up using an init sequence from a program on the web, slightly modified.

 

Finally, I spent a LONG time working with the code before I tried a bunch of different contrast setting values.

Suddenly it came to life!

It turns out there is a WIDE VARIABILITY in what the contrast setting should be.

You should try your code with a number of widely different settings.

 

Good luck!

Its a nice little display, once you have it up and running!

 

JC

 

Edit:

Also, run your project on 3.3 V, (micro and LCD), at least until you have in working.

Then think about how to modify it for a dual voltage system.

 

Nokiareset:
   'Send Reset\ signal to the Nokia GLCD
   Reset Glcdrst                                            'Reset\ goes low
   Waitus 10
   Set Glcdrst                                              'High to operate
   Return

Nokiasetup:
   'Initialize the Nokia GLCD Display Parameters
   Spiinit                                                  'Init the uC SPI pin's status
 '  Waitms 1
   Reset Glcdcs                                             'GLCD Chip Select Active
 '  Waitms 1
   Reset Glcdrst                                            'Reset the GLCD
   Waitus 2                                                 'Overkill
   Set Glcdrst
   Waitms 1                                                 'Enable GLCD

   'Now send inits to GLCD
   Reset Glcdmode                                           'Mode, Command

'Setup from web, seven steps:  (Contrast value is specific for each display!)
'Setup from web example

   'Display is Active, (On), Horizontal Mode, Switch to Extended Commands:
   Glcddb = 33                                              'Extended Commands
   Spiout Glcddb , 1                                        'Send it to GLCD

   Glcddb = 180                                             'Voop, (Contrast)
   Spiout Glcddb , 1                                        'Send it to GLCD

   Glcddb = 4                                               'Temp Corf
   Spiout Glcddb , 1                                        'Send it to GLCD

   Glcddb = 20                                              'Bias 1:48
   Spiout Glcddb , 1                                        'Send it to GLCD

   Glcddb = 12                                              'Nl Mode
   Spiout Glcddb , 1                                        'Send it to GLCD

   'Display is Active, (On), Horizontal Mode, Switch to Basic Commands:
   Glcddb = 32
   Spiout Glcddb , 1                                        'Send it to GLCD

   Glcddb = 12
   Spiout Glcddb , 1                                        'Send it to GLCD

   Set Glcdcs                                               'GLCD Chip Select Inactive

   Return

 

Last Edited: Tue. Mar 31, 2015 - 02:45 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

DocJC wrote:

I'll show my Nokia 5100 initialization code, in Bascom.

 

Note that at least in my data sheet there appeared to be inconsistencies even within the data sheet on how one should power up and initialize the display!

 

Also, the setup from the data sheet failed!

I ended up using an init sequence from a program on the web, slightly modified.

 

Finally, I spent a LONG time working with the code before I tried a bunch of different contrast setting values.

Suddenly it came to life!

It turns out there is a WIDE VARIABILITY in what the contrast setting should be.

You should try your code with a number of widely different settings.

 

Good luck!

Its a nice little display, once you have it up and running!

 

JC

 

Edit:

Also, run your project on 3.3 V, (micro and LCD), at least until you have in working.

Then think about how to modify it for a dual voltage system.

 

Nokiareset:
   'Send Reset\ signal to the Nokia GLCD
   Reset Glcdrst                                            'Reset\ goes low
   Waitus 10
   Set Glcdrst                                              'High to operate
   Return

Nokiasetup:
   'Initialize the Nokia GLCD Display Parameters
   Spiinit                                                  'Init the uC SPI pin's status
 '  Waitms 1
   Reset Glcdcs                                             'GLCD Chip Select Active
 '  Waitms 1
   Reset Glcdrst                                            'Reset the GLCD
   Waitus 2                                                 'Overkill
   Set Glcdrst
   Waitms 1                                                 'Enable GLCD

   'Now send inits to GLCD
   Reset Glcdmode                                           'Mode, Command

'Setup from web, seven steps:  (Contrast value is specific for each display!)
'Setup from web example

   'Display is Active, (On), Horizontal Mode, Switch to Extended Commands:
   Glcddb = 33                                              'Extended Commands
   Spiout Glcddb , 1                                        'Send it to GLCD

   Glcddb = 180                                             'Voop, (Contrast)
   Spiout Glcddb , 1                                        'Send it to GLCD

   Glcddb = 4                                               'Temp Corf
   Spiout Glcddb , 1                                        'Send it to GLCD

   Glcddb = 20                                              'Bias 1:48
   Spiout Glcddb , 1                                        'Send it to GLCD

   Glcddb = 12                                              'Nl Mode
   Spiout Glcddb , 1                                        'Send it to GLCD

   'Display is Active, (On), Horizontal Mode, Switch to Basic Commands:
   Glcddb = 32
   Spiout Glcddb , 1                                        'Send it to GLCD

   Glcddb = 12
   Spiout Glcddb , 1                                        'Send it to GLCD

   Set Glcdcs                                               'GLCD Chip Select Inactive

   Return

 

 

You saved me. It was just a contrast issue. Now I'm able to blink the display. More test to come. Thanks to everybody!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is The Moment Of Learning. Look at the 5110 init in bascom and in c (from the Big File) side by side. Should be mostly the same. Look at the menu that lets you peck in a letter or number in and call a subroutine that draws a line or a rectangle. Look at the main down at the end of the file. See how it calls init functions then falls into the menu loop? Not so complex when you look at it in pieces is it?

 

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bobgardner wrote:

This is The Moment Of Learning. Look at the 5110 init in bascom and in c (from the Big File) side by side. Should be mostly the same. Look at the menu that lets you peck in a letter or number in and call a subroutine that draws a line or a rectangle. Look at the main down at the end of the file. See how it calls init functions then falls into the menu loop? Not so complex when you look at it in pieces is it?

 

 

You're right! The logic behind the code is the same for both