Hallo Leute!
Wir arbeiten mit dem ATmega 32 mit der Taktfrequenz von 3,6864 Mhz und versuchen ein Display Powerdip Pc1602d a anzusteuern. Dazu haben wir uns ein Testprogramm heruntergeladen.
Wir lassen folgendes im Main.c ausgeben:
LCD_Print(0,0,"Servas");
_delay_ms(5000);
das ist das C File dazu
Code:
/*
Copyright: Radig Ulrich mailto: mail@ulrichradig.de
Author: Radig Ulrich
Remarks:
known Problems: none
Version: 28.05.2004
Description: Programm zur Ansteuerung eines Standart LCD
(HD44870),(SED1278F) und kompatible
*/
#include <lcd.h>
//Prototypes
void Write_LCD (char,char);
char Read_LCD (char);
void LCD_Init (void);
void LCD_Clear (void);
void LCD_Print (char,char,char *Buffer,...);
void LCD_Init (void)
{
char tmp = Init_LCD_Zeilen;
//Set Port Direction Register to Output for LCD Databus und LCD Steuerbus
LCD_Port_DDR = LCD_DataOutput+(1<<LCD_RS | 1<<LCD_RW | 1<<LCD_E);
//Wait a short Time afer Power on
for (int a=0;a<3000;a++)
{
}
Write_LCD (0x22,0); //Init in 4 Bit Mode
//Wait a short Time afer Power on
for (int a=0;a<3000;a++)
{
for (int b=0;b<100;b++);
}
Write_LCD (0x22,0); //Init in 4 Bit Mode (Zur Sicherheit nochmal)
if (tmp == 1)
{
Write_LCD (0x20,0); //1 Zeilen
}
else
{
Write_LCD (0x28,0); //mehrere Zeilen
}
Write_LCD (0x0C,0); //Display On
Write_LCD (0x80,0); //Set DD-Ram Adresse = 0
}
void Write_LCD (char Data,char CD)
{
//Set Port Direction Register to Output for LCD Databus und LCD Steuerbus
LCD_Port_DDR = LCD_DataOutput+(1<<LCD_RS | 1<<LCD_RW | 1<<LCD_E);
//Soll ins Seuer oder Datenregister geschrieben werden?
if (CD == 0)
{
cbi(LCD_Port_Write,LCD_RS); //RS = 0 Steuerregister
}
else
{
sbi(LCD_Port_Write,LCD_RS); //RS = 1 Dataregister
}
//Schreibsignal setzen
cbi(LCD_Port_Write,LCD_RW); //Zum Schreiben RW-Pin = Low
//Schreiben der 1. 4Bit an das LCD Display
LCD_Port_Write = (LCD_Port_Write&0xF0) + ((Data&0xF0)>>4); //Write Nibbel MSB
sbi(LCD_Port_Write,LCD_E);
cbi(LCD_Port_Write,LCD_E);
//Schreiben der 2. 4Bit an das LCD Display
LCD_Port_Write = (LCD_Port_Write&0xF0) + (Data&0x0F); //Write Nibbel LSB
sbi(LCD_Port_Write,LCD_E);
cbi(LCD_Port_Write,LCD_E);
}
char Read_LCD (char CD)
{
char Data;
//Set Port Direction Register to Output for LCD Databus und LCD Steuerbus
LCD_Port_DDR = LCD_DataInput+(1<<LCD_RS | 1<<LCD_RW | 1<<LCD_E);
//Lesesignal setzen
sbi(LCD_Port_Write,LCD_RW); //Zum Lesen RW-Pin = High
//Soll ins Seuer oder Datenregister geschrieben werden?
if (CD == 0)
{
cbi(LCD_Port_Write,LCD_RS); //RS = 0 Steuerregister
}
else
{
sbi(LCD_Port_Write,LCD_RS); //RS = 1 Dataregister
}
sbi(LCD_Port_Write,LCD_E); //Daten stehen an wenn Enable = High
for (int a=0;a<100;a++) //Wartet ein bisschen bis daten anliegen
{
}
Data = (LCD_Port_Read&0x0F)<<4; //Lesen des 1. Nibble (MSB)
cbi(LCD_Port_Write,LCD_E);
sbi(LCD_Port_Write,LCD_E); //Daten stehen an wenn Enable = High
for (int a=0;a<100;a++) //Wartet ein bisschen bis daten anliegen
{
}
Data += (LCD_Port_Read&0x0F); //Lesen des 2. Nibble (LSB)
cbi(LCD_Port_Write,LCD_E);
return(Data);
}
void LCD_Print (char zeile,char spalte,char *Buffer,...)
{
// Hilfsvariable zum Zählen der ausgegebenen Zeichen
char nFieldWidth = 0;
struct {
char fLeftJust:1; // Feldausrichtung links oder rechts
char fNegative:1; // Auszugebende Zahl ist negativ.
} flags;
#define SCRATCH 16
unsigned char scratch[SCRATCH];
unsigned char format_flag;
unsigned int u_val=0, base=0;
unsigned char *ptr;
char hexA = 'a';
char *p;
int n;
int nLen;
va_list ap;
va_start (ap, Buffer);
//Berechnet Adresse für die Zeile und schreibt sie ins DD-Ram
if (zeile >= Init_LCD_Zeilen) //wurden mehr Zeilen angegeben als Initialisiert
{
zeile = Init_LCD_Zeilen - 1;
}
zeile = 0x80/Init_LCD_Zeilen*zeile;
zeile += spalte;
if (zeile >= 0x80) //ist der Wert ausserhalb des DD-Ram Adresse
{
zeile = 0x7F;
}
zeile += 0x80;
Write_LCD (zeile,0);
while (*Buffer != 0)
{
if (*Buffer == '%')
{
*Buffer++;
switch (format_flag = *Buffer++){
case 'c':
format_flag = va_arg(ap,int);
Write_LCD (format_flag++,1);
case 'i':
case 'd':
case 'u':
base = 10;
goto CONVERSION_LOOP;
case 'o':
base = 8;
goto CONVERSION_LOOP;
case 'X':
hexA = 'A';
// Weiter wie 'x'
case 'x':
base = 16;
}
CONVERSION_LOOP:
u_val = va_arg (ap, int);
n = u_val;
flags.fNegative = 0;
if (format_flag == 'd' || format_flag == 'i') {
// Negative Werte auswerten
if (((int) u_val) < 0) {
flags.fNegative = 1;
u_val = -u_val;
}
}
// Der Scratchpuffer wird von rechts nach links aufgefüllt
// beginnend mit dem niederwertigsten Digit.
ptr = scratch + SCRATCH;
*--ptr = 0; // Abschliessendes NULL-Byte eintragen
do
{
char ch = u_val % base + '0';
if (ch > '9') ch += hexA - '9' - 1;
*--ptr = ch;
u_val /= base;
} while (u_val);
if (n < base) *--ptr = '0';
if (flags.fNegative) *--ptr = '-';
// Länge bestimmen
p = ptr;
nLen = 0;
while (*p++) nLen++;
// Feld bei Bedarf links auffüllen
if (!flags.fLeftJust) {
for (n=nLen; n < nFieldWidth; n++) Write_LCD (' ',1);
}
// Pufferinhalt schreiben
for (n=0; n < nLen; n++) Write_LCD (*ptr++,1);
// Feld bei Bedarf rechts auffüllen
if (flags.fLeftJust) {
for (n=nLen; n < nFieldWidth; n++) Write_LCD (' ',1);
}
}
Write_LCD (*Buffer++,1);
}
va_end(ap);
}
void LCD_Clear (void)
{
Write_LCD (1,0); //Clear Display
Write_LCD (0x80,0); //Set DD-Ram Adresse = 0
}
Die Header DAtei zum festelgen der Ports und so
Code:
//LCD_D0 - LCD_D3 connect to GND
//Im 4Bit Mode LCD_D4-->PORTx.0 ........ LCD_D7-->PORTx.3
//LCD_RS --> PORTx.4 | LCD_RW --> PORTx.5 | LCD_E --> PORTx.6 | PORTx.7-->NotConnect
#define Init_LCD_Zeilen 2 //Anzahl der Zeilen 1,2 oder 4
#define LCD_Port_DDR DDRA //Port an dem das Display angeschlossen wurde
#define LCD_Port_Write PORTA
#define LCD_Port_Read PINA
#define LCD_RS 4 //Pin für RS
#define LCD_RW 5 //Pin für Read/Write
#define LCD_E 6 //Pin für Enable
#define LCD_DataOutput 0x0f
#define LCD_DataInput 0x00
#define BusyBit 7
Das Programm funktioniert soweit, dass wir am Display was sehen, aber es gibt folgendes aus:
evs<--<--0_HxWWt0__Unterstrich
<-- ist ein Zeichen und ein Pfeil nach links
_ist ein Abstand am Display
Unterstrich ist ein Unterstrich am Display
Danke für eure Hilfe
MfG
saschisch
Lesezeichen