/*******************************************************************************
Titel: LCD-Ansteuerung (4-Bit)
File: LCD.c
Hardware: Geeignet für den Charakter-Displaykontroller HD44780
(Es funktionieren mit der grössten Wahrscheinlichkeit
auch andere kompatible Kontroller)
Datum: 07.05.2009
Aktuelle Version: 1.6
Session Log: Version 1.6 07.05.2009 Fehler bei Variabel akt_XPosition behoben
Version 1.5 05.05.2009 Funktion LCD_int_to_ASCII() entfernt
Version 1.4 13.03.2009 Funktion LCD_uint_to_ASCII() umgewandelt in LCD_int_to_ASCII(),
LCD_Make_Own_Pattern() unterstützt nun nur noch Flash-Variablen
Version 1.3 08.02.2009 Funktion LCD_uint_to_ASCII() hinzugefügt
Version 1.2 31.01.2009 Funktionen LCD_Delay_ms() und LCD_Make_Own_Pattern() hinzugefügt,
Fehler bei X-Position des Cursors behoben
und Timing Überarbeitet
Version 1.1 03.01.2009 Fehler in der Funktion String behoben
Version 1.0 27.12.2009 erste stabile Version
Lizenz: Licence for the LCD.c and LCD.h files
The both flies are a part of a LCD library. You can use it with the HD44780 controller.
Copyright (C) 2009 Simon Grossenbacher
This program is free software; you can redistribute it and/or modify it under the terms of
the GNU General Public License as published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program;
if not, see .
*******************************************************************************/
/*******************************************************************************
* Nötige Include Dateien und globale Variabeln
******************************************************************************/
#include
#include
#include "LCD.h"
#ifndef F_CPU
#define F_CPU 18432000UL
#endif
/////////////////////
//Globale Variabeln//
/////////////////////
volatile unsigned char akt_Cursor_AddressPosition = SET_CURSOR;
volatile unsigned char akt_Cursor_XPosition = 0;
#if( (NUMBER_OF_DISPLAY_LINES == 2) || (NUMBER_OF_DISPLAY_LINES == 4) )
volatile unsigned char akt_Cursor_YPosition = 0;
#endif
/*******************************************************************************
* Delay für Initialisierung
* Input: - Zeit in ms (max. 255ms)
******************************************************************************/
void LCD_Delay_ms(unsigned char Time)
{
unsigned char i;
unsigned short j;
//Anzahl ms warten (je nach Variabel Time)//
for( i=0; i < Time; i++)
{
//ca 1ms warten//
for( j=0; j <= (F_CPU/1000); j++)
{
asm volatile("nop");
}
}
}
/*******************************************************************************
* Enable Impuls erzeugen
*******************************************************************************/
void LCD_Enable(void)
{
//Enable Impuls geben//
LCD_CONTROL_PORT |= (1<>4)<>4)< muss 3x gesendet werden
LCD_Enable();
//2.//
LCD_Delay_ms(5); //mehr als 4.1ms warten
LCD_Enable();
//3.//
LCD_Delay_ms(1); //mehr als 100us warten
LCD_Enable();
LCD_Wait_for_Busy_Flag();
//4-Bit Modus setzen//
LCD_DATA_PORT_PUT &= ~((1< Zeichen so lange ausgeben bis dies erreicht ist//
while(*String)
{
if( akt_Cursor_AddressPosition <= (CHARACTER_PER_LINE+SET_CURSOR+FIRST_LINE_ADDRESS) )
{
LCD_Data(*String); //akt. Zeichen ausgeben
}
String++; //String Adresse erhöhen
}
}
#elif( (NUMBER_OF_DISPLAY_LINES == 1) && (CHARACTER_PER_LINE <= 80) )
////////////////////////////////////////////////////////
//1-Zeilen Display mit mehr als 40 Charakter pro Linie//
////////////////////////////////////////////////////////
void LCD_Set_Cursor( unsigned char X_Position )
{
if( X_Position <= CHARACTER_PER_LINE )
{
akt_Cursor_XPosition = X_Position;
if( X_Position < (CHARACTER_PER_LINE/2) )
{
akt_Cursor_AddressPosition = SET_CURSOR + FIRST_LINE_ADDRESS + X_Position;
}
else
{
akt_Cursor_AddressPosition = SET_CURSOR + SECOND_LINE_ADDRESS + X_Position - (CHARACTER_PER_LINE/2);
}
LCD_Command(akt_Cursor_AddressPosition);
}
}
void LCD_String(char *String)
{
//Am Ende eines Strings befindet sich '\0' -> Zeichen so lange ausgeben bis dies erreicht ist//
while(*String)
{
if( akt_Cursor_AddressPosition <= (CHARACTER_PER_LINE/2+SET_CURSOR+SECOND_LINE_ADDRESS) )
{
LCD_Data(*String); //akt. Zeichen ausgeben
}
String++; //String Adresse erhöhen
if( akt_Cursor_AddressPosition == (CHARACTER_PER_LINE/2+SET_CURSOR+FIRST_LINE_ADDRESS) )
{
LCD_Set_Cursor(CHARACTER_PER_LINE/2);
}
}
}
/*#elif( (NUMBER_OF_DISPLAY_LINES == 2) && (CHARACTER_PER_LINE <= 20) )
///////////////////////////////////////////////////////////
//2-Zeilen Display mit weniger als 20 Charakter pro Linie//
///////////////////////////////////////////////////////////
void LCD_Set_Cursor( unsigned char X_Position, unsigned char Y_Position )
{
if( X_Position <= CHARACTER_PER_LINE )
{
akt_Cursor_YPosition = Y_Position;
switch(Y_Position)
{
case 0:
akt_Cursor_XPosition = SET_CURSOR + FIRST_LINE_ADDRESS + X_Position;
break;
case 1:
akt_Cursor_XPosition = SET_CURSOR + CHARACTER_PER_LINE + X_Position;
break;
default:
return;
}
LCD_Command(akt_Cursor_XPosition);
}
}
void LCD_String(char *String)
{
//Am Ende eines Strings befindet sich '\0' -> Zeichen so lange ausgeben bis dies erreicht ist//
while(*String)
{
if( akt_Cursor_XPosition < (2*CHARACTER_PER_LINE+SET_CURSOR+FIRST_LINE_ADDRESS) )
{
LCD_Data(*String); //akt. Zeichen ausgeben
}
String++; //String Adresse erhöhen
if( akt_Cursor_XPosition == (CHARACTER_PER_LINE+SET_CURSOR+FIRST_LINE_ADDRESS) )
{
LCD_Set_Cursor(0,1);
akt_Cursor_YPosition = 1;
}
}
}*/
#elif( (NUMBER_OF_DISPLAY_LINES == 2) && (CHARACTER_PER_LINE <= 40) )
////////////////////////////////////////////////////////
//2-Zeilen Display mit mehr als 20 Charakter pro Linie//
////////////////////////////////////////////////////////
void LCD_Set_Cursor( unsigned char X_Position, unsigned char Y_Position )
{
if( X_Position <= CHARACTER_PER_LINE )
{
switch(Y_Position)
{
case 0:
akt_Cursor_XPosition = X_Position;
akt_Cursor_YPosition = Y_Position;
akt_Cursor_AddressPosition = SET_CURSOR + FIRST_LINE_ADDRESS + X_Position;
LCD_Command(akt_Cursor_AddressPosition);
break;
case 1:
akt_Cursor_XPosition = X_Position;
akt_Cursor_YPosition = Y_Position;
akt_Cursor_AddressPosition = SET_CURSOR + SECOND_LINE_ADDRESS + X_Position;
LCD_Command(akt_Cursor_AddressPosition);
break;
default:
return;
}
}
}
void LCD_String(char *String)
{
//Am Ende eines Strings befindet sich '\0' -> Zeichen so lange ausgeben bis dies erreicht ist//
while(*String)
{
if( akt_Cursor_AddressPosition < (CHARACTER_PER_LINE+SET_CURSOR+SECOND_LINE_ADDRESS) )
{
LCD_Data(*String); //akt. Zeichen ausgeben
}
String++; //String Adresse erhöhen
if( akt_Cursor_AddressPosition == (CHARACTER_PER_LINE+SET_CURSOR+FIRST_LINE_ADDRESS) )
{
LCD_Set_Cursor(0,1);
akt_Cursor_YPosition = 1;
}
}
}
#elif( (NUMBER_OF_DISPLAY_LINES == 4) && (CHARACTER_PER_LINE <= 20) )
///////////////////////////////////////////////////////////
//4-Zeilen Display mit weniger als 20 Charakter pro Linie//
///////////////////////////////////////////////////////////
void LCD_Set_Cursor( unsigned char X_Position, unsigned char Y_Position )
{
if( X_Position <= CHARACTER_PER_LINE )
{
switch(Y_Position)
{
case 0:
akt_Cursor_YPosition = Y_Position;
akt_Cursor_XPosition = X_Position;
akt_Cursor_AddressPosition = SET_CURSOR + FIRST_LINE_ADDRESS + X_Position;
LCD_Command(akt_Cursor_AddressPosition);
break;
case 1:
akt_Cursor_YPosition = Y_Position;
akt_Cursor_XPosition = X_Position;
akt_Cursor_AddressPosition = SET_CURSOR + SECOND_LINE_ADDRESS + X_Position;
LCD_Command(akt_Cursor_AddressPosition);
break;
case 2:
akt_Cursor_YPosition = Y_Position;
akt_Cursor_XPosition = X_Position;
akt_Cursor_AddressPosition = SET_CURSOR + FIRST_LINE_ADDRESS + CHARACTER_PER_LINE + X_Position;
LCD_Command(akt_Cursor_AddressPosition);
break;
case 3:
akt_Cursor_YPosition = Y_Position;
akt_Cursor_XPosition = X_Position;
akt_Cursor_AddressPosition = SET_CURSOR + SECOND_LINE_ADDRESS + CHARACTER_PER_LINE + X_Position;
LCD_Command(akt_Cursor_AddressPosition);
break;
default:
return;
}
}
}
void LCD_String(char *String)
{
//Am Ende eines Strings befindet sich '\0' -> Zeichen so lange ausgeben bis dies erreicht ist//
while(*String)
{
if( akt_Cursor_AddressPosition < (2*CHARACTER_PER_LINE+SECOND_LINE_ADDRESS+SET_CURSOR) )
{
LCD_Data(*String); //akt. Zeichen ausgeben
}
String++; //String Adresse erhöhen
//Wechseln auf die 2. Linie//
if( akt_Cursor_AddressPosition == (CHARACTER_PER_LINE+FIRST_LINE_ADDRESS+SET_CURSOR) )
{
LCD_Set_Cursor(0,1);
akt_Cursor_YPosition = 1;
}
//Wechseln auf die 3. Linie//
if( akt_Cursor_AddressPosition == (CHARACTER_PER_LINE+SECOND_LINE_ADDRESS+SET_CURSOR) )
{
LCD_Set_Cursor(0,2);
akt_Cursor_YPosition = 2;
}
//Wechseln auf die 4. Linie//
if( akt_Cursor_AddressPosition == (2*CHARACTER_PER_LINE+FIRST_LINE_ADDRESS+SET_CURSOR) )
{
LCD_Set_Cursor(0,3);
akt_Cursor_YPosition = 3;
}
}
}
#endif
/*******************************************************************************
* Eigene Zeichen definieren (bei Font 5x8 8 Zeichen, bei Font 5x10 4 Zeichen)
* input: - Zeichen Array (je nach Font 8 o. 10 Zeilen)
* - Nummer mit der das Muster aufgerufen werden soll(0-7)
******************************************************************************/
void LCD_Make_Own_Pattern( unsigned char* Pattern, unsigned char Pattern_Number )
{
unsigned char i;
#if( CHARACTER_FONT == 0)
if( Pattern_Number < 8) //Überprüfen ob eine korrekte Nummer eigegeben worden ist
{
LCD_Command( SET_PATTERN + (CHARACTER_LEVEL*Pattern_Number) ); //an die richtige Stelle im RAM wechseln
//Zeichen speichern//
for(i=0; i