PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeichenkette über UART empfangen



Reeper
29.08.2007, 18:45
Hallo,

ich werde noch wahnisinnig bei dieser Programmiersprache. Aber naja, wollte es ja unbedingt wissen....

Zu meiner Frage:

Es geht darum, eine Zeichenkette auf einem LCD auszugeben.
Das senden vom Controller funktioniert mittlerweile einwandfrei (Dank an das Forum und an izaseba).
Wenn ich nun vom PC zB. "Hallo" sende, kann ich mit dem "Echo-Code" vom Wiki dies problemlos zurückschicken.
Mich wundert da erstmal schon die Deklaration von bZeichen als char. Wobei "Hallo" ja eigentlich aus 5 Zeichen besteht.

Die Lib von Peter Fleury ist die Grundlage für's Display und hier ist der wichtige Code-Teil:


void usart_init(void);
char receive_UART[20];


int main(void)
{
usart_init();
lcd_init(LCD_DISP_ON);
lcd_clrscr();
while (1)
{
while ( !(UCSRA & (1 << RXC)) )
{}
receive_UART[0] = UDR;
receive_UART[19] = '\0';
lcd_clrscr();
lcd_gotoxy(0,0);
lcd_puts(receive_UART);
}
}

Ich habe somit in der Variable "receive_UART" Platz für 19 Zeichen, das 20. und somit letzte (19. Stelle) beschließt das Ende der Zeichenkette.

Jedoch wird nur das letzte empfangene Zeichen ausgegeben.
Wie funktioniert das UDR - Register, als was wird der Inhalt gespeichert.
Wenn ein ASCII Code gesendet wurde, müsste dieser ja auch sich dort befinden, zumal ja im Echo Programm mit einer char Variable darauf zugegriffen werden konnte.


Was mache ich nur falsch, es ist deprimierend.
Kann mir jemand helfen?

Gruß
Stefan

linux_80
29.08.2007, 20:23
Hallo,

ich würde sagen es werden schon alle Zeichen ausgegeben, nur kannst du nicht so schnell schauen, wie die angezeigt werden :-)

Wie bei einer seriellen Übertragung üblich, kommen die Zeichen eins nach dem anderen, evtl. sollten die Zeichen erst alle in das Array, nach ende der Übertragung auf das LCD geschrieben werden.

Reeper
30.08.2007, 14:34
OK, dann werde ich mich mal daran machen.
Merke, dass das LCD eh sehr langsam ist und meine ganzen Timings durcheinander bringt (muss wirklich vorher die Interrupts ausschalten).

Reeper
31.08.2007, 17:57
So, habe arg rumprobiert.
Heraus gekommen ist ein Teilerfolg.
Die 1.Eingabe bis '#' wird korrekt ausgegeben.




// includes
//-----------------------------------------------------
//-----------------------------------------------------

#include <avr/io.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.h"

// Variable
//-----------------------------------------------------
//-----------------------------------------------------

char data[20]; // für alle Fälle ausreichend groß
char c;
int a=0, s=0, i;

// Prototypen
//-----------------------------------------------------
//-----------------------------------------------------

void usart_init(void);
void string_senden(char *string);
void zeichen_senden(char zeichen);
void USART_interrupt (char temp);
void str_uebergabe (char data[], int a);

// Main
//-----------------------------------------------------
//-----------------------------------------------------

int main(void)
{
usart_init();
lcd_init(LCD_DISP_ON);
lcd_clrscr();
lcd_gotoxy(0,0);
DDRA |= (1<<2);
while (1)
{
sei();
if (c=='1')
{
c=0;
zeichen_senden(c);
lcd_putc(c);
PORTA |= (1<<2);
}
if(c=='2')
{
c=0;
zeichen_senden(c);
lcd_putc(c);
PORTA &=~ (1<<2);
}
cli();
}
}

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


ISR(USART_RXC_vect)
{
char temp;
temp = UDR; // speichere UDR-Wert in temp
USART_interrupt(temp);
}

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

void USART_interrupt (char temp)
{
data[a]+=temp; // hänge neues byte an data an
a++; // erhöhe Index a (Stelle) um 1
if (temp=='#')
{
str_uebergabe(data,a);
}
}

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

void str_uebergabe (char data[], int a)
{
while(s!=a)
{
zeichen_senden(data[s]);
lcd_putc(data[s]);
s++;
}
for(i=0; i<a; i++)
{
data[i] = '\0';
}
s=0;
a=0;
}

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

void usart_init(void)
{
UBRRH = 0;
UBRRL = 7;
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}


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

void string_senden(char *string)
{
while (*string)
{
while (!(UCSRA & (1<<UDRE)))
{}
UDR = *string++;
}
}

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

void zeichen_senden(char zeichen)
{
while (!(UCSRA & (1<<UDRE)));
UDR = zeichen;
}

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


(Wenn man den Code kopiert, wird dieser korrekt und nicht verschoben dargestellt).

Müsste die Zeichenkette "data" nicht wieder überschrieben werden, wenn der Index "a" genullt wird?

Mit dieser Schleife wird die Zeichenkette geleert.


for(i=0; i<a; i++)
{
data[i] = '\0';
}

Warum wird die Zeichenkette nicht überschrieben und gibt es bessere Lösungen (auch für das Leeren von Zeichenketten)?

Das LCD ist nun wesentlich schneller, wenn man die R/W Leitung benutzt und nicht nur kurz wartet :-b .

linux_80
31.08.2007, 21:03
Hallo,

wenn Du die Ausgabe auf dem LCD löschen willst, heisst Das eigentlich, das dort lauter Leerzeichen hin müssen.
Wenn Du einen String erstellst, der nur \0 hat, ist dieser eigentlich leer, denn das \0 ist das Endekennzeichen.
Du musst hier Leerzeichen in den String schreiben, und am Ende das \0.

Edit:
wegen dem String löschen:

strcpy(data, "ichwilldarein");
Das \0 wird auch mit angehängt.

Reeper
01.09.2007, 02:03
Das komische ist halt, dass der String nicht geleert wird.
Die Zeichen werden zwar gelöscht, doch dahinter werden die neuen geschrieben.
ZB. Hallo und als zweites wieso:

Hallo
wieso

So sieht das aus (auf dem Hyperterminal, sowie dem LCD). Wenn jedoch der Laufindex der Zeichenkette (bei mir "a") genullt wird, müsste die Zeichenkette doch wieder überschrieben (wieder beu null anfangen) und nicht fortgesetzt werden.?

Reeper
01.09.2007, 19:41
Habe es hinbekommen:


ISR(USART_RXC_vect)
{
temp = UDR; // speichere UDR-Wert in temp
data[a]=temp;
if (temp=='#')
{
str_uebergabe(data,a);
a=-1; // Zeichen '\0' weg
}
a++;
}

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

void str_uebergabe (char data[],int a)
{
s=0;
while(s!=a)
{
zeichen_senden(data[s]);
lcd_putc(data[s]);
s++;
}
for (i=0; i<100; i++)
{
_delay_ms(10);
}
lcd_clrscr();
strcpy(data,""); // String löschen bzw. leeren
}

@ linux_80

Ja, strcpy ist wesentlich besser geeignet 8-[