lpcware

LCD 2x16 WINSTAR WH1602A with LPC1769 - something wrong

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by teslabox on Mon Oct 13 06:37:30 MST 2014
Hi everyone!

I try to communicate with my LCD display according to HD44780 but probably I do something wrong way.
I write C code step by step according the algorithm on page 42:
https://www.sparkfun.com/datasheets/LCD/HD44780.pdf
When I turn on the Vcc one line is lighting.
When I run uC with program this line disapears - so it can be good sign but there is no cursor or any char.


#include "LPC17xx.h"
#include <cr_section_macros.h>
#include <NXP/crp.h>

__CRP const unsigned int CRP_WORD = CRP_NO_CRP; // CRP - Code Read Protection; brak ochrony odczytu kodu

/* Pinout description:
*
* Cinfigure lines:
* pin 4 - RS - GPIO P0.0 (Register Select: 0 - Instruction Register, 1 - Data Register)
* pin 5 - RW - GPIO P0.1 (Read or Write: 0 - Write to the LCD, 1 - Read from the LCD)
* pin 6 - EN - GPIO P0.2 (Enable/Clock: Data is latched on falling edge)
*
* Data bits lines (only MSB nibble) of 4 bits transmission:
* pin 11 - DB4 - GPIO P2.0 (bit 0 - LSb)
* pin 12 - DB5 - GPIO P2.1 (bit 1)
* pin 13 - DB6 - GPIO P2.2 (bit 2)
* pin 14 - DB7 - GPIO P2.3 (bit 3 - MSb)
*
*/

void Timer0_MicroSeconds2 (uint32_t NanoSeconds);// Measured on oscilloscope - 1.0 us, work properly with ABP 100 MHz
void Timer0_MiliSeconds2 (uint32_t MiliSeconds);// Measured on oscilloscope - 1.0 ms, work properly with ABP 100 MHz

// Function of setting GPIO as outputs and RW and EN lines low
void SetPorts (void)
{
// Set all lines as GPIO output
LPC_GPIO2->FIODIR = ((1<<3)|(1<<2)|(1<<1)|(1<<0));// DATA lines - D0, D1, D2, D3 (4 bits)
LPC_GPIO0->FIODIR = ((1<<2)|(1<<1)|(1<<0));// Configure lines - RS, RW, EN (3 bits)
LPC_GPIO0->FIOCLR = (1<<1);// RW line on the GND all the time - only Write to the LCD
LPC_GPIO0->FIOCLR = (1<<2);// EN line low for start as a default state
Timer0_MiliSeconds2 (10);// Delay 10 ms for stable lines
}

// Function of dividing byte on MSB and LSB and send them to the HD44780
void SentLCD (uint8_t Byte)
{
// Send first nibble of the byte - MSB (b7-b4)
// Bus timing values according to Hitachi HD44780 user manual set - Write Operation Figure 25 on page 26
LPC_GPIO0->FIOSET = (1<<2);// Enable = 1
Timer0_MicroSeconds2 (1);// Delay 1 us (delay 150 ns at least)
LPC_GPIO2->FIOSET = ((Byte & 0xF0) >> 4);// Byte MSB shifted to LSB place and set on the data lines DB4-DB7
Timer0_MicroSeconds2 (1);// Delay 1 us (delay 80 ns at least)
LPC_GPIO0->FIOCLR = (1<<2);// Enable = 0
Timer0_MicroSeconds2 (2);// Delay 2 us (delay 250 ns at least)
// Untill here the MSB (4-bits) were sent to the LCD/HD44780
// The cycle of EN line was HI-2 us and LO-2 us so whole cycle took 2 us

// Send second nibble of byte - LSB
// Bus timing values according to Hitachi HD44780 user manual set - Write Operation Figure 25 on page 26
LPC_GPIO0->FIOSET = (1<<2);// Enable=1
Timer0_MicroSeconds2 (1);// Delay 1 us (delay 150 ns at least)
LPC_GPIO2->FIOSET = (Byte & 0x0F);// Byte LSB set on the data lines DB4-DB7
Timer0_MicroSeconds2 (1);// Delay 1 us (delay 80 ns at least)
LPC_GPIO0->FIOCLR = (1<<2);// Enable = 0
Timer0_MicroSeconds2 (2);// Delay 2 us (delay 250 ns at least)
// Until here the LSB (4-bits) were sent
// The cycle of EN line was HI-2 us and LO-2 us so whole cycle took again 2 us

// Whole byte sending (MSB + LSB) took 8 us together
}

// Function of the LCD setting and write them to the HD44780
void SetLCD (uint8_t Byte)
{
// Now writing data to the Instruction Register so line RS goes low
LPC_GPIO0->FIOCLR = (1<<0);// RS = 0
Timer0_MicroSeconds2 (1);// Delay 1 us (delay 80 ns at least)
//Now when RS line is low configure byte can be send
SentLCD (Byte);// Write data to the HD44780
// Let give 1 ms delay
Timer0_MiliSeconds2 (1);
}

// Function of sending data (chars) to the LCD
void DataLCD (uint8_t Data)
{
// Now writing to the Data Register so line RS goes high
LPC_GPIO0->FIOSET = (1<<0);// RS = 1
Timer0_MicroSeconds2 (1);// Delay 1us
SentLCD (Data);// Send data to the LCD
}

void StaticTxtLCD (char * s)
{
while (*s)
{
DataLCD (*s);
s++;
}
}

// Function of initializing the LDC
void InitLCD (void)
{
// Reset Function
// Initializing by Internal Reset Circuit
// Hitachi HD44780 user manual, page 23

// Set proper GPIOs for LDC lines
SetPorts ();
// Delay 50 ms for stable lines
Timer0_MiliSeconds2 (50);

// Now writing to the Setting Register so RS line goes low
LPC_GPIO0->FIOCLR = (1<<0);// RS = 0
Timer0_MicroSeconds2 (1);// Delay 1 us (delay 80 ns at least)
// Set EN line low as a default value for next steps
LPC_GPIO0->FIOCLR = (1<<2);// Enable=0
Timer0_MiliSeconds2 (10);// Delay 10 ms for stable

// Temporary variable for 'for' loop below only
uint8_t i = 0;

// Triple set DB4-DB7 (bits 4-7) as value 0x03 according to HD44780 user manual
for (i = 0; i < 3; i++)
{
LPC_GPIO0->FIOSET = (1<<2);// Enable = 1
Timer0_MicroSeconds2 (1);// Delay 1 us for EN line proper working
LPC_GPIO2->FIOSET = (0x03); // Set Data lines as 0x03 value
Timer0_MicroSeconds2 (1);// Delay 1 us for EN line proper working
LPC_GPIO0->FIOCLR = (1<<2);// Enable = 0
Timer0_MiliSeconds2 (5);// Delay 5ms (should be 4.1 ms at least)
}

Timer0_MiliSeconds2 (50);

// Main settings of the LCD
SetLCD (0x28);// 4-bit transmission, 2 or 4 lines LCD, char 5x8 dots
Timer0_MiliSeconds2 (5);
SetLCD (0x08);// Display Off, Cursor Off, Cursor Toggle Off
Timer0_MiliSeconds2 (5);
SetLCD (0x01);// Clear display
Timer0_MiliSeconds2 (5);
SetLCD (0x06);// Shift characters right (not left), Cursor is moving and window LCD is non-moving
Timer0_MiliSeconds2 (5);
SetLCD (0x0F);// Display On, Cursor On, Cursor Toggle On
Timer0_MiliSeconds2 (5);

Timer0_MiliSeconds2 (50);

}
// Main program
int main (void)
{
// Set the Timer0 for proper delays timing
LPC_SC->PCONP |= (1<<1); // Set Power On for Timer0
LPC_SC->PCLKSEL0 |= (1<<2); // Timer0 CLK = APB = 100 MHz (Divider = 1)
LPC_SC->PCLKSEL0 &=~(1<<3); // Timer0 CLK = APB = 100 MHz (Divider = 1)

// Set GPIO P0.22 as output - there is a LED diode for toggle
LPC_GPIO1->FIODIR = ((1<<30)|(1<<31));
LPC_GPIO1->FIOCLR = ((1<<30)|(1<<31));

InitLCD ();
DataLCD (36);

for (;;)
{
LPC_GPIO1->FIOSET = ((1<<30)|(1<<31));
Timer0_MiliSeconds2 (100);
LPC_GPIO1->FIOCLR = ((1<<30)|(1<<31));
Timer0_MiliSeconds2 (100);
}

return (0);
}

void Timer0_MicroSeconds2 (uint32_t MicroSeconds)
{
LPC_TIM0->TCR = 0x02;/* reset timer */
LPC_TIM0->PR  = 0x00;/* set prescaler to zero */
LPC_TIM0->MR0 = MicroSeconds;
LPC_TIM0->IR  = 0xff;/* reset all interrrupts */
LPC_TIM0->MCR = 0x04;/* stop timer on match */
LPC_TIM0->TCR = 0x01;/* start timer */

/* wait until delay time has elapsed */
while (LPC_TIM0->TCR & 0x01);
}

void Timer0_MiliSeconds2 (uint32_t MiliSeconds)
{
LPC_TIM0->TCR = 0x02;/* reset timer */
LPC_TIM0->PR  = 0x00;/* set prescaler to zero */
LPC_TIM0->MR0 = MiliSeconds*100000;
LPC_TIM0->IR  = 0xff;/* reset all interrrupts */
LPC_TIM0->MCR = 0x04;/* stop timer on match */
LPC_TIM0->TCR = 0x01;/* start timer */

/* wait until delay time has elapsed */
while (LPC_TIM0->TCR & 0x01);
}


What's wrong? I followed this code many times but I can't find the bug.

Outcomes