Hallo,
ich habe die Poiter zwar weitgehend verstanden, aber irgendwie stehe ich
gerade auf dem Schlau :-)
Ich will den Inhalt (oder genauer den Pointer auf den Inhalt), der auf
meinem LCD dargestellt werden soll, in einer Globalen Variable
speichern. Die ist notwendig, da ich per ISR (durch einen Taster
ausgelöst) kutzzeitig einen anderen Text auf dem LCD darstellen will,
beim verlassen der ISR soll jedoch der ursprünglich Text wieder
angezeigt werden.
Leider zeigt das Display beim Rücksprung zum ursprünglichen Text nur
"Müll" an.
Könnt Ihr mir helfen??
Hier mal eine Code-Schnipsel:
In display soll der der dargestellte text (bzw. der Pointer dahin)
gespeichert werden:
1
char*display;
Diese Prozedur stellt den Inhalt, der übergeben wurde, auf dem LCD dar
1
/*Sendet den komletten Display-Inhalt zum LCD (Array-Pointer)*/
2
voidlcd_display(constchar*data,uint8_tcenter)
3
{
4
lcd_clear();
5
_delay_ms(5);
6
intstart=1;
7
display=data;//Hier soll in display der anzuzeigende Inhalt gespecihert werden
8
for(inti=0;i<4;i++){
9
intlaenge=strlen(data);
10
if(center&&laenge<20)start=(20-laenge)/2+1;
11
12
lcd_setcursor(i+1,start);
13
14
for(intj=0;j<20;j++)
15
{
16
if(*data!='\0')lcd_data(*data);
17
data++;
18
19
}
20
21
22
}
23
}
aufgerufen wird die Funktion z.B. folgendermaßen
1
charswitch_off[4][20]={"Anlage wird ","heruntergefahren","","Bitte warten..."};
2
lcd_display(*switch_off,1);
Hier noch die ISR
1
/*Interupt-Service-Routine für Power-Taster*/
2
SIGNAL(SIG_INTERRUPT2)
3
{
4
cli();
5
6
if(power_status&(get_taster_zustand(PWR)))
7
{
8
inti=3;
9
charswitch_off[4][20]={"Anlage wird in","3 Sekunden","abgeschaltet....",""};
10
lcd_display(*switch_off,1);//hier soll der neue Text dargestellt werden
11
while((i>0)&get_taster_delay(PWR,1000,0))
12
{
13
i--;
14
lcd_setcursor(2,6);
15
lcd_data(i+48);
16
}
17
if(!i)shutdown();
18
}else{
19
if(get_taster_delay(PWR,1000,0))
20
{
21
sleep_disable();
22
wakeup();
23
}
24
}
25
lcd_display(*display,1);//Hier soll der alte Text wieder angezeigt werden
Das "LCD-Ausgabe innerhalb der ISR" hört sich nicht gut an.
Diese Aufgabe wird üblicherweise aus gutem Grund anders programmiert.
Z.B. Die ISR übergibt dem Anwendungsprogrammteil ein Flag und der
Anwendungsprogrammteil kümmert sich darum.
astroscout schrieb:> char* display;
...
> /*Sendet den komletten Display-Inhalt zum LCD (Array-Pointer)*/> void lcd_display(const char *data ,uint8_t center)> {
...
> lcd_display(*display, 1); //Hier soll der alte Text wieder angezeigt werden
Warum nicht einfach mal lesen, was der Compiler zu sagen hat? Diesen
Fehler hat er ganz bestimmt angemotzt.
Abgesehen davon machst du in lcd_display() selbst eine Zuweisung nach
display. Der vorherige Inhalt von display wird also durch
lcd_display(*switch_off, 1); zerstört und kann an der Stelle
lcd_display(*display, 1); nicht mehr verwendet werden.
Danke für eure schnellen Antworten:
@Stefan B.:
Ich gebe dir da völlig recht, ist nicht sehr schön, aber hier ist der
Interrupt zeitunkritisch, sodass ich das so gelöst habe ;-)
@Andreas B.:
Der kompiler gibt mir folgendes aus:
In file included from lcd.h:88,
from main.c:44:
lcd.c: In function 'lcd_display':
lcd.c:238: warning: assignment discards qualifiers from pointer target
type
In file included from taster.h:61,
from main.c:45:
taster.c: In function '__vector_3':
taster.c:189: warning: passing argument 1 of 'lcd_display' makes pointer
from integer without a cast
leider hilft mir die aber nicht wirklich weiter :-(
Du solltest das Programmkonzept nochmals überdenken.
Nach der Rückkehr aus der ISR musst du die Ausgabe des
Hauptprogramm-Textes komplett neu starten, weil sich ja in der ISR
zwischenzeitlich der Zustand des LCDs geändert hat. Das aber geht mit
deinem Ansatz nicht.
Oliver
Deine
void lcd_display(const char *data ,uint8_t center)
ist überhaupt höchst ungeschickt programmiert.
Du solltest dir zum Ziel setzen, dass du sowas:
1
charswitch_off[4][20]={"Anlage wird in","3 Sekunden","abgeschaltet....",""};
in der Komplexität, gar nicht brauchst.
Das Argument zu lcd_display muss aus 4 Teiltexten bestehen, die
hintereinander im Speicher abgelegt sind, wobei jeder Teiltext aus 20
Buchstaben (+abschliessendem 0 Byte) bestehen muss.
Tut es das nicht, dann machts bei dir kaboom. Da sind Fehler
vorprogrammiert.
Es wäre doch viel schöner, wenn du sowas machen könntest
1
charswitch_off[]={"Anlage wird in\n3 Sekunden\nabgeschaltet...."};
und lcd_display kümmert sich selber darum wieviele Zeilenumbrüche da im
String enthalten sind und wie sie auszuwerten und anzuzeigen sind.
Denkst du nicht?
Kein Aufrufer muss mehr darauf aufpassen, dass er dem lcd_display das
richtige vorwirft. Keine Längenangaben, die stimmen müssen. Und das
beste am Ganzen: ein String - ein Pointer.
Karl heinz Buchegger schrieb:> und lcd_display kümmert sich selber darum wieviele Zeilenumbrüche da im> String enthalten sind und wie sie auszuwerten und anzuzeigen sind.> Denkst du nicht?
ja, das geben ich dir recht, aber wie kann ich das sinnvoll
realisieren??
astroscout schrieb:> Karl heinz Buchegger schrieb:>> Das hier>>>> lcd_display(*switch_off, 1);>>>> kann auch nicht stimmen.>>> okay, wie müsste es denn "sauber" lauten?
Sauber?
Sauber übernimmt lcd_display nicht einfach nur einen String sondern ein
Dein Problem ist hier, dass du einen wilden Mischmasch aus 2D Arrays mit
1D Arrays veranstaltet hast, der nur deswegen 'funktioniert' weil der
Pointer auf den Anfang eines 2D Arrays auch gleichzeitig der Pointer auf
den Anfang der ersten Zeile dieses 2D Arrays ist.
Oder aber natürlich, die wirst diese ganzen 2D Array los, indem du noch
ein wenig Intelligenz in lcd_display steckst. Dann kannst du dem einen
beliebigen String vorwerfen, mit Formatierzeichen (dem \n) und
lcd_display macht das Richtige damit.
astroscout schrieb:> Karl heinz Buchegger schrieb:>> und lcd_display kümmert sich selber darum wieviele Zeilenumbrüche da im>> String enthalten sind und wie sie auszuwerten und anzuzeigen sind.>> Denkst du nicht?>> ja, das geben ich dir recht, aber wie kann ich das sinnvoll> realisieren??
Im Prinzip ist gar nicht mal soviel Unterschied zu dem was du hast.
Nur kannst du nicht mehr strlen zur Bestimmung der Länge einer Zeile
benutzen. :-)
Und natürlich überall, wo in deinem jetzigen Code 4 oder 20 steht musst
du auf die tatsächlichen Gegebenheiten Rücksicht nehmen und nicht
einfach nur Zahlenwerte voraussetzen. Aber ist ja kein Problem: while
Schleifen sind ja schon erfunden :-)
astroscout schrieb:> taster.c:189: warning: passing argument 1 of 'lcd_display' makes pointer> from integer without a cast>> leider hilft mir die aber nicht wirklich weiter :-(
Um das spezielle Problem noch mal aufzulösen (warum man das alles
sowieso anders macht haben schon andere erläutert):
astroscout schrieb:> char* display;
Display ist ein Zeiger auf char…
> lcd_display(*display, 1); //Hier soll der alte Text wieder angezeigt werden
…also ist *display ein char (das * folgt dem Zeiger), in diesem Fall das
erste Zeichen im String, auf den display zeigt. Das erste Argument von
lcd_display ist aber ein Zeiger auf einen String, also wird das Zeichen
als Zeiger interpretiert — und davor hat der Compiler gewarnt.
Dass dann Müll angezeigt wird ist nicht verwunderlich, es werden ja
Daten ab einer Startadresse zwischen 0 und 255 (der Wertebereich eines 8
bit char in Zeiger umgewandelt) als String interpretiert.
Danke für Eure schnelle Hilfe
Ich habe mir jetzt die Display-Funktione so ungeschrieben, dass ich sie
z.B. mit
1
lcd_display("Anlage wird in\n3 Sekunden\nabgeschaltet....",1);
aufrufen kann.
Auch das speihern des Displayinhaltes funktioniert nun einwandfrei.
Eine Frage habe ich aber noch.
Wie kann ich zwei Teilstring miteinander verbinden?
In php gibt es ja dafür den Punktoperator, ich kann aber in C nichts
dazu finden!