MSP430 Tutorial


4 Bit Interface MSP430 To an Alpha-Numeric LCD display

    Interfacing NHD-0216HZ-FSW-FBW-33V3C Alpha-Numeric LCD display to MSP430F5529IPNR microcontroller.

4 bit hardware Interface between MSP430F5529IPNR and NHD-0216HZ-FSW-FBW-33V3C Display

CGROM - stands for "Character Graphics Read only Memory". This ROM is part of the display microcontroller on the LCD and holds all the standard patterns for the 5 x 7 dot matrix characters. For instance, if you want to display character "A", you would send ASCII code 65 (decimal) to the DDRAM. The display controller looks up the pattern of dots to display for this code in the CGROM and lights up the ones appropriate for "A". The CGROM contents depend on the particular character set and model of display, US, Chinese etc. and cannot be changed.

CGRAM - stands for "Character Graphics Random Access Memory" allows the user to define special supplementary non-standard character types that are not in the CGROM. You can load your own dot pattern shapes e.g. a rectangle into CGRAM and using certain reserved codes in DDRAM, call these up for display.

DDRAM - stands for "Data Display Random Access Memory" and is the working data buffer of the display. Each character on the display has a corresponding DDRAM location and the byte loaded in DDRAM controls which character is displayed.

In 4 bit mode we send the data one nibble (4bit) at a time, first the upper nibble and then the lower nibble. A nibble is a group of four bits. Each byte of data has two nibbles (MSN and LSN).

MSN - Most Significant Nibble
LSN - Least Significant Nibble


		
#include <msp430x552x.h>
#include <string.h>
#include "driverlib.h"
#include "hal.h"

#include "USB_config/descriptors.h"
#include "USB_API/USB_Common/device.h"
#include "USB_API/USB_Common/usb.h"                     //USB-specific functions
#include "USB_API/USB_CDC_API/UsbCdc.h"
#include "USB_app/usbConstructs.h"

// 4 - bit
void writecom4(char cmd);
void writedata4(char byte);
unsigned char LCDbusy4();

unsigned char i;


void DelayMs1(int Ms)
{

	while(Ms>0)
	{
		__delay_cycles(8000); // Delay 1ms - 8000 000 / 1000 = 8000 counts
		Ms--;
	}
}

void latch(){                           // command to latch E
	GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN3); 	// E = 1; SETB E

	DelayMs1(1);

	GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN3); 	// E = 0; RESETB E
}

/*******************************************************************************
 *
 * GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN7); // RS
 * GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN6); // RW
 * GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN7); // En
 * GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN6); // XRESET
 * __delay_cycles(1000);
*/

/*
 * Write command
 */
void writecom4(char cmd)
{
	char temp;
	temp = cmd;

	// Send High Nybble
	temp = ((temp >> 4) & 0x0F);		//Shift H-Nybble to L-Nybble

	GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN3); 	// E = 0;		RESETB E
	GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN4); 	// RW = 0 - Write	CLR RW
	GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN5); 	// RS = 0 - Command	CLR RS
	DelayMs1(10);
	
	DelayMs1(1);

	P2OUT = (P2OUT & 0xF0) | temp; 	// Apply H-Nybble to 2.0 - 2.3 MOV P1,A

	DelayMs1(1);
	latch();

	//----------------------------------------------------------------------------------------

	// Send Low Nybble	
	DelayMs1(1);
	P2OUT = (cmd & 0x0F);				// Apply L-Nybble to 2.0 - 2.3				MOV P1,A
	
	DelayMs1(1);
	
	latch();
	
	DelayMs1 (2);

}

void writedata4(char byte)
{
	char temp;
	temp = byte;

	temp = ((temp >> 4) & 0x0F);			//Shift variable 'byte' MS nibble to LS nibble

	GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN3); 	// E = 0;	RESETB E
	GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN4); 	// RW = 0 - Write
	GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN5); 	// RS = 1 - Data

	DelayMs1(2);

	P2OUT = (P2OUT & 0xF0) | temp;			//Output HN (P2OUT & 0xF0)|((cmd>>4) & 0x0F)
	latch();
	
	//------------------------------------------------------------------------------------------

	P2OUT = (byte & 0x0F);	//Output LN (P2OUT & 0xF0)|(byte & 0x0F)
	latch();
	
	DelayMs1(1);
}

unsigned char LCDbusy4(){

	unsigned char busy;
	
	GPIO_setAsInputPin(GPIO_PORT_P2, GPIO_PIN3);		//In 2.3

	DelayMs (2);

	GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN5); 	// RS = 0 - Command

	GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN4); 	// RW = 1 - Read

	busy = (P2IN & 0x04);

	GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN3);		//Out 2.3

	DelayMs (2);

	return busy;
}


// Newhaven Initialization Program Code Example (4 Bit Interface) 


void init4() //initialize the LCD
{

	DelayMs1 (1000);
	P2OUT = 0x03;
	latch();
	DelayMs1 (100);
	latch();
	DelayMs1 (100);
	latch();
	DelayMs1 (100);
	P2OUT = 0x02;
	latch();
	DelayMs1 (100);
	
	writecom4_NHD_C0216CU_FSW_GBW_3V3(0x28); //wake up	28H 4 bit,N=1,5*7dot
	DelayMs1 (100);

	writecom4_NHD_C0216CU_FSW_GBW_3V3(0x10); //wake up	29H 4 bit,N=1,5*7dot
	DelayMs1 (100);
	
	writecom4_NHD_C0216CU_FSW_GBW_3V3(0x0F); //Internal OSC
	DelayMs1 (100);
	
	writecom4_NHD_C0216CU_FSW_GBW_3V3(0x06); //Contrast set 78H
	DelayMs1 (100);

}

const unsigned char Msg1[] = " 16x2 LCD Test... ";
const unsigned char Msg2[] = " F2812 EVB BOARD ";


void main(void)
{
	
	volatile unsigned int i;

	WDT_A_hold(WDT_A_BASE); //Stop watchdog timer

	//Set I/O pins
	GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0); //DB4 is conneted to P2.0
	GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1); //DB5 is conneted to P2.1
	GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN2); //DB6 is conneted to P2.2
	GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN3); //DB7 is conneted to P2.3

	GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN5); // RS
	GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN4); // RW
	GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN3); // En	
		
	init4();		// init LCD
	
	DelayMs1(50);
	writecom4(0x80); //Set display to line 1
	DelayMs(5);
	for(i=0;i<16;i++){
		writedata4(Msg1[i]); //Print message
		DelayMs1(5);
	}
	
	writecom4(0xc0); //Set display to line 2
	DelayMs1(5);
	for(i=0;i<16;i++){    	
		writedata4(Msg2[i]);	//Print message
		//while (LCDbusy4());	// Check for busy flag while it is high it is busy
		DelayMs1(5);
	}
}

	




Initializing WS0010 Display - 4 bit mode

void WriteIns(unsigned char instruction) //For WEH1602 4bit
{
	unsigned char temp;

	temp = instruction;//0xHL

	GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN3); 	// E = 0; RESETB - E
	GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN4); 	// RW = 0 - Write CLR - RW 
	GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN5); 	// RS = 0 - Command CLR - RS 

	//Data_BUS = instruction & 0xf0;
	/*
	 * P2.0 - DB4
	 * P2.1 - DB5
	 * P2.2 - DB6
	 * P2.3 - DB7
	 */
	P2OUT = (P2OUT & 0xF0) | temp;//Write 0xHL, writing H to P2OUT

	latch();		//E = 1 DelayMs1(1) E = 0

}

void init4_WS_0010_5V(void) //For WEH1602 4bit
{
	//P2.0 - DB4
	//P2.1 - DB5
	//P2.2 - DB6
	//P2.3 - DB7

	DelayMs1 (1000);// wait for 1 sec

	WriteIns(0x00);
	DelayMs1 (100);

	WriteIns(0x00);
	DelayMs1 (100);

	WriteIns(0x00);
	DelayMs1 (100);

	WriteIns(0x00);
	DelayMs1 (100);

	WriteIns(0x00);
	DelayMs1 (100);

	WriteIns(0x20);//function set //do it only once
	DelayMs1 (100);

	cmdcntr = 0;	//Used to print data on PC
	writecom4_NHD_C0216CU_FSW_GBW_3V3(0x28); //function set
	DelayMs1 (100);

	cmdcntr = 1;	//Used to print data on PC
	writecom4_NHD_C0216CU_FSW_GBW_3V3(0x0C);//display on
	DelayMs1 (100);

	cmdcntr = 2;	//Used to print data on PC
	writecom4_NHD_C0216CU_FSW_GBW_3V3(0x06);//entry mode set
	DelayMs1 (100);

	cmdcntr = 3;	//Used to print data on PC
	writecom4_NHD_C0216CU_FSW_GBW_3V3(0x02);
	DelayMs1 (100);

	cmdcntr = 3;	//Used to print data on PC
	writecom4_NHD_C0216CU_FSW_GBW_3V3(0x01);//clear display
	DelayMs1 (100);


}


//Generic Code ################################################################################
#define	Cword	0x10	//16
#define	one	0x80 // DD RAM Address 
							
#define	two	0xc0 // DD RAM Address
						
#define	Data_BUS	P1


sbit		busy    =P1^7;
sbit		RS      =P3^0; 
sbit	 	RW      =P3^7;
sbit		Enable  =P3^4;

char bdata  flag;
sbit busy_f  = flag^0;

void CheckBusy();
void WriteIns(unsigned char instruction);
void WriteCmd(unsigned char cmd);
void WriteData(unsigned char dat);
void WriteString(unsigned char count,unsigned char * MSG);
void Initial_OLED();
void delay(unsigned char m);
									  
								//0123456789ABCDEF	  
unsigned char code MSG1[Cword]  ="Winstar display ";
unsigned char code MSG2[Cword]  =" WEH1602 4-bit  ";
unsigned char code MSG3[Cword]  ="                ";
unsigned char code CGRAM1[8] ={0x04,0x0E,0x15,0x04,0x04,0x04,0x04,0x04,};  //
unsigned char code CGRAM2[8] ={0x04,0x04,0x04,0x04,0x04,0x15,0x0e,0x04,};  //


void CheckBusy()
{
	Data_BUS = 0xff; //
	RS = 0;
	RW = 1;  
	do
	{
		Enable = 1;
		busy_f = busy;	 
		Enable = 0;
		Enable = 1; //dummy read
		Enable = 0;
		_nop_();	
	 }while(busy_f);
}
//=================================
void WriteIns(unsigned char instruction)
{
	 RS = 0;
	 Enable = 0;
	 RW = 0;
	 Data_BUS = instruction&0xf0;
	 Enable = 1;            //1us
	 _nop_();		//1us
	 Enable = 0;		//1us
}
void WriteCmd(unsigned char cmd)
{
	unsigned char hIns=cmd,lIns=cmd;

	 RS = 0;
	 RW = 0;
	 Data_BUS = hIns&0xf0;
	 Enable = 1;            //1us
	 _nop_();		//1us
	 Enable = 0;		//1us
	  Data_BUS = lIns<<4;
	 Enable = 1;            //1us
	 _nop_();		//1us
	 Enable = 0;		//1us
	CheckBusy();
}
//=================================
//=================================
void WriteData(unsigned char dat)
{
	unsigned char hDat=dat,lDat=dat;

	 RS = 1;
	 RW = 0;
	 Data_BUS = hDat&0xf0;
	 Enable = 1;
	 _nop_();
	 Enable = 0;

	 Data_BUS = lDat<<4;
	 Enable = 1;
	 _nop_();
	 Enable = 0;
	CheckBusy(); 
}

void WriteString(unsigned char count,unsigned char * MSG)
{ 
	unsigned char  i;
	
	for(i = 0; i<count;i++)
	{
		WriteData(MSG[i]);
	}
}

void Initial_OLED()
{
	//need to set five "0x00" cmds
	WriteIns(0x00);
	WriteIns(0x00);
	WriteIns(0x00);
	WriteIns(0x00);
	WriteIns(0x00);
	WriteIns(0x20);//function set - do it only once
	WriteCmd(0x28);//function set
	WriteCmd(0x0c);//display on
	WriteCmd(0x06);//entry mode set
	WriteCmd(0x02);
	WriteCmd(0x01);//clear display
}

void delay(unsigned char m)
{
	unsigned char i,j,k;
	 for(j = 0;j<m;j++)
 	{
	 	for(k = 0; k<200;k++)
	 	{
			for(i = 0; i<100;i++)
			{
			}
		}
 	}	
}

void CGRAM()
{
	unsigned char i,j;

	WriteCmd(0x40);    //CGRAM Address000000(0x00)
					   //CGRAM 0x40+0x00=0x40
	for(i = 0;i<8;i++)
	{
	   	WriteData(CGRAM1[i]);
	}

	WriteCmd(0x48);	   //CGRAM Address 001000(0x08)
					   //CGRAM 0x40+0x08=0x48
	for(j = 0;j<8;j++)
	{
	   	WriteData(CGRAM2[j]); //data write to CGRAM
	}
}

void main(void)
{
	unsigned char i;
	
	delay(1);

	while(1)
	{
		Initial_OLED();
		CGRAM(); 
		WriteCmd(one);
		for(i = 0; i<Cword;i++)
		{
			WriteData(MSG1[i]);
		}
		WriteCmd(two);
		for(i = 0; i<Cword;i++)
		{
			WriteData(MSG2[i]);
		}
		delay(10);

		WriteCmd(one);
		WriteData(0x00);
		delay(10);
		WriteCmd(two+1);
		WriteData(0x01);
		delay(20);
		
		WriteCmd(one);
		for (i=0;i<7;i++)
			WriteData(0xc0+i);
		delay(20);
	}
}




Setting Graphics Mode

The mode is set by way of an instruction sent to the instruction register. DB3 is sometimes the bit assigned for selecting the mode. When DB3 = zero Character Mode is selected, and if DB3 = one then graphics mode is selected. This bit is one of a group of bits DB0, DB1, DB2, so they are set together. DB0 and DB1 are fixed to 1, whilst DB2 is the power bit to control the internal DC-DC power circuitry. This would suggest that the power bit and mode bit are set together.

Keeping things simple, if the DC-DC power circuitry is to remain on and keeping DB2 fixed to logic 1. The command code to send to the instruction register would be the following.

  • Binary "0 0 0 0 0 1 1 1 1 1" sets power ON and graphic mode.
  • Binary "0 0 0 0 0 1 0 1 1 1" sets power ON and character mode.

Using the Graphics Mode

In graphics mode, you would no longer be using any pre-set character tables stored in CGRAM or CGROM, because that is for character mode display. Therefore, you would no longer be sending character codes to the Display RAM. This suggests that in graphics mode what you write to the Display RAM maps directly to the display dots.

This is easily discoverable by sending a byte pattern such as "11111111" to the Display RAM, and seeing where it lands on the display.





Create your Google Account or just sign in and post.