Elektronik

Democode: serielle LCD Ansteuerung (bit bang)

Optimierter Code für die parallele Ansteuerung eines LCD Moduls über 2 Leitungen und ein Schieberegister (Autor: Roland Elmiger).

//-------------------------------------------------------------------------
// LCD-Routine für LC-Meter (2-Bit)
//-------------------------------------------------------------------------
// Roland Elmiger, HB9GAA
// Letzter Update : 25.09.2007
//-------------------------------------------------------------------------
#include "Includes.h"

#define		LCD_Daten	LATBbits.LATB5		//LCD-Daten Ausgang
#define		LCD_Clock	LATBbits.LATB4		//LCD-Clock Ausgang

#define		Zeile1			0x00					//1. LCD-Zeile
#define		Zeile2			0x40					//2. LCD-Zeile

#define		Func_Set		0b00101000		//2 Zeilen und 5x7 Zeichen, 4 Bit
#define		Disp_On			0b00001100		//Anzeige ein
#define		Disp_On_C		0b00001110		//Anzeige ein, Cursor ein
#define		Disp_On_B		0b00001111		//Anzeige ein, Cursor ein und blinken
#define		Disp_Off		0b00001000		//Anzeige aus
#define		Clr_Disp		0b00000001		//Anzeige löschen
#define		Entry_Inc		0b00000110		//Auto-Inkrement
#define		Entry_Inc_S	0b00000111			//Auto-Inkrement, Anzeige schieben
#define		Entry_Dec		0b00000100		//Auto-Dekrement
#define		Entry_Dec_S	0b00000101			//Auto-Dekrement, Anzeige schieben
#define		CGRAM				0b01000000	//CGRAM, Least Significant 6-bit are for address
#define		DD_Ram_Addr	0b10000000			//Least Significant 7-bit are for address
#define		DD_Ram_UL		0b10000000		//Upper Left coner of the Display


// Ein Clock senden
//-------------------------------------------------------------------------

void Clock (void)
	{
	  LCD_Clock=1;
		Nop();
	  LCD_Clock=0;
	}


// Ein Nibble senden (unteres Nibble von n, c=0 als Cmd, c=1 als Char)
//-------------------------------------------------------------------------

void NibbleOut(unsigned char n, unsigned char c)	//ein nibble an LCD senden
	{		
	char Temp, i;
	Temp=n & 0x0F;								//das nibble speichern und hinausschieben
	
	for (i=8; i>0; --i)							//das Shift Register löschen
	{
  Clock();										//Clock ausgeben
	}
		
//Bit-7 -----------------------------------------
	LCD_Daten=1;								//das Gate Bit setzen			
  Clock();										//Clock ausgeben
		  	
//Bit-6 -----------------------------------------
	LCD_Daten=0;								//das Lamp-Bit zurücksetzen
	if (Flag1bits.Lamp_On==1u)					//Test, ist LAMP-Bit 1 oder 0?
	  LCD_Daten=1;								//das Lamp-Bit setzen
  Clock();										//Clock ausgeben
		  	
//Bit-5 -----------------------------------------
	LCD_Daten=0;								//das PowerOnOff-Bit zurücksetzen
	if (Flag1bits.PowerOnOff==1u)				//Test, ist PowerOnOff-Bit 1 oder 0?
	  LCD_Daten=1;								//das PowerOnOff-Bit setzen
  Clock();										//Clock ausgeben
		  	
//Bit-4 -----------------------------------------
	LCD_Daten=0;								//das RS Bit setzen
	if (c==1u)									//wenn c = 1
	  LCD_Daten=1;
  Clock();										//Clock ausgeben
	
//Bit-3 bis 0 ------------------------------------
	for (i=4;i>0;--i)
		{
	  LCD_Daten=0;	  
	  if (Temp & 0x08)							//das nibble zum Output schieben
	    LCD_Daten=1;		
		Temp=Temp<<1;
  	Clock();									//Clock ausgeben
		}	

	LCD_Daten=1;								//Clock auf der Datenleitung ausgeben
	Nop();
	LCD_Daten=0;
}
  

// Ein Kommando an das LCD-Modul senden
//-------------------------------------------------------------------------
	
void Send_Cmd(char c) {
												//zuerst den obere Nibble des Bytes senden
	NibbleOut(c>>4,0);							//RS = 0, Kommandomodus
	NibbleOut(c,0);								//sende das untere Nibble des Bytes
	}


// Ein Zeichen an das LCD-Modul senden
//-------------------------------------------------------------------------

void Send_Clr_Disp(void) {    
	Send_Cmd (Clr_Disp);  						//Display löschen
	Delay100TCYx(164);							//mindestens 4.1ms warten
	}

void Send_Dot(void) {
	Send_Cmd ('.');  							//Punkt ausgeben
	}

void Send_Space(void) {
	Send_Cmd (' ');  							//Leerzeichen ausgeben
	}
	
void Send_Char(char c) {
												//zuerst den obere Nibble des Bytes senden
	NibbleOut(c>>4,1);							//RS = 1, Datenmodus
	NibbleOut(c,1);								//sende das untere Nibble des Bytes
	}


// Cursor auf LCD setzen (Adresse in W, 0-27h und 40h-67h
//-------------------------------------------------------------------------

void Set_Cursor(unsigned char x, unsigned char y) 
	{
	unsigned char pos;	
	pos = (y*0x40 + x)|0x80;			/		/Adresse aufbereiten
	Send_Cmd(pos);								//und als Command senden
	}


// Data an LCD senden
//-------------------------------------------------------------------------

void Data2Disp(rom char*putstr) 
	{
	unsigned char ps;
		
	while((ps = *putstr) != 0xFF)
		{
	  putstr++;
	  if (ps== 0xFF) break;
	
	  Send_Char(ps);
		}
	}


// Text an aktueller Cursorposition ausgeben
//-------------------------------------------------------------------------

void DispMsg(char*putstr) 
	{
	char ps;
		
	while((ps = *putstr))
		{
	  putstr++;
	  if (ps== 0) break;
	
	  Send_Char(ps);
		}
	}

void DispROMMsg(rom char*putstr) 
	{
	char ps;
		
	while((ps = *putstr))
		{
	  putstr++;
	  if (ps== 0) break;
	
	  Send_Char(ps);
		}
	}


// Text an Position x,y ausgeben (x = 0..15, y = 0..1
//-------------------------------------------------------------------------

void DispMsg2Pos(char *putstr, unsigned char x, unsigned char y)	
	{
	char ps;

	Set_Cursor(x, y);

	while((ps = *putstr))
		{
	  putstr++;
	  if (ps== 0) break;
	
	  Send_Char(ps);
		}
	}
	

void DispROMMsg2Pos(rom char *putstr, unsigned char x, unsigned char y)	
	{
	char ps;

	Set_Cursor(x, y);

	while((ps = *putstr))
		{
	  putstr++;
	  if (ps== 0) break;
	
	  Send_Char(ps);
		}
	}


// LCD initialisieren (2 Zeilen)
//-------------------------------------------------------------------------

void Init_LCD() {

    Delay100us(150);							//15ms warten
	NibbleOut(0b00110011,0);					//Reset als Command senden
    Delay100TCYx(164);							//mindestens 4.1ms warten

	NibbleOut(0b00110011,0);					//Reset als Command senden
    Delay10TCYx(40);							//100us warten

	NibbleOut(0b00110011,0);					//Reset als Command senden
    Delay10TCYx(40);							//100us warten

	NibbleOut(0b00100010,0);					//4-Bit Mode setzen
    Delay10TCYx(40);							//100us warten

	Send_Cmd(Func_Set);							//Befehl für 2 Zeilen und 5x7 Zeichen
	Send_Cmd(Disp_On);							//Anzeige einschalten
	Send_Cmd(Entry_Inc);						//jedes neue Zeichen wird hinter das letzte

	Send_Cmd(CGRAM);					
	Data2Disp(Text3);							//Spezial Zeichen in LCD laden
	Send_Clr_Disp();							//Anzeige löschen

    Delay100us(41);								//mindestens 4.1ms warten
}


// Verzögerungsroutinen
//-------------------------------------------------------------------------

// Verzögerung ca. n x 100us
//-------------------------------------------------------------------------

void Delay100us(char time)
	{
	unsigned char i;
	for (i=time;i>0u;i--)
    Delay10TCYx(40);							//n x 100us warten
	}


// Verzögerung ca. n x 0.1s
//-------------------------------------------------------------------------

void Delay0s1(char time)
	{
	unsigned char i;
	for (i=time;i>0u;i--)
    Delay10KTCYx(40);					 		//n x 100ms warten
	}

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.