PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeichenketten Auf ATmega übertragen und vergleichen



BomberD
10.11.2004, 12:30
Hi,

ich versuche mehrere Zeichen(Strings unterschiedlicher Länge) per rs232 vom PC auf den AtMega und zurück zu übertragen.
Leider hab ich keine Ahnung woran ich erkenne wann das letzte Zeichen übertragen wurde. Deshalb hab ich einfach gesagt die '#' solls sein.
Leider läuft das so nicht.
Anbei der Quellcode. Neben dem Interrupt gesteuerte Zeicehempfang läuft noch ein Timer mit dem ich ne Led Blinken lasse.

Ich bin für jeden Tipp dankbar der Licht in mein Dunkel bringt. :/


#include <avr/io.h>
#include "SeriellBiblio.h"
#include <progmem.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/string.h>
//Arbeitstakt angeben
#define SYSCLK 8000000UL

//usart ansprechen

volatile unsigned char *data;
volatile int count=0;
volatile unsigned char b;

void timer (void){
TIMSK=_BV(TOIE0); //overflow flag setzen--> ab jetzt kan overflow interrupt ausgelöst werden
TCNT0 = 0; //Rücksetzen des Timers
TCCR0 = _BV(CS02); //Prescaler 256
sei (); //interrupts ein
}

int main(void) {
USART_Init ();
timer ();
//sei();
//unsigned char data = 0;
DDRB = 0xff;
PORTB=0xff;
for (;;) {
//data = USART_receive ();
//darf erst vergleichen wenn nicth mehr gesendet wird... hmmm
if(b=='1'){
if (strstr((char*)data, "1#")){
PORTB = 0x00;
data="";
}
else if (strstr((char*)data, "0#")){
PORTB = 0xff;
data="";
}
else if (strstr((char*)data, "Steffen#")){
USART_transmit_string("Hallo Steffen");//(char*)data
data="";
}
else if (strstr((char*)data, "Jana#")){
USART_transmit_string("Hallo Jana");//(char*)data
data="";
}
b='0';
}
}
return 0;
}
//intterrupt wenn byte empfangen
SIGNAL (SIG_UART_RECV){
data+=UDR;//hänge neues byte an
if (UDR=='#')b='1'; //prüft ob Receive complete
}

//lässt led blinken
SIGNAL (SIG_OVERFLOW0) {
count++;
if (count==4){
if(PORTB & (1<<PB0)){
PORTB&=~(1<<PB0);
count=0;
}
else{
PORTB|=(1<<PB0);
count=0;
}
}
}

10.11.2004, 12:52
Hallo

Versuch es mal so. Ich meine, das UDR Register wird beim ersten Lesezugriff gelöscht.


//intterrupt wenn byte empfangen
SIGNAL (SIG_UART_RECV){
unsigned char temp;
temp = UDR;
data+=temp;//hänge neues byte an
if (temp=='#')b='1'; //prüft ob Receive complete
}


MFG
Dieter

BomberD
10.11.2004, 13:35
hi,

leider mag er noch nicht.
Ich werd erstmal irgendwo ne led blinken lassen wenn er was empfängt.
Irgendwo musses noch haken.
Unter Bascom war die Kommunikation ganz easy möglich. Aber wer weis was ich mir da wieder zusammengeschrieben hab ;)

BomberD
10.11.2004, 13:48
Hi,
Ichhab mal ne LED blinken lassen. Also er scheint zu empfangen LED an.
Auch setzt er den Ausgang wieder Zurück # erkannt.
Also muss das Problem bei den Stringvergleichen hängen.
Ich hab für die Stringvergleiche die string.h eingebunden.
Ich hab irgendwo gelesen das mit der strstr Fkt. ein Stringvergleich realisierbar ist.
Vielleicht hab ich da was nicht beachtet oder falsch verstanden?Hmm...

martin
10.11.2004, 15:27
Hallo,


else if (strstr((char*)data, "Steffen#"))

Wenn ich mich recht erinnere, vergleicht strstr() bis zum \n-Zeichen (0x00).

Da das in deiner Zeichenfolge aber nicht vorkommt, vergleicht er bis weißgott wohin, und es wäre reiner Zufall, wenn der Vergleich positiv ist.

Ich würde das #-Zeichen durch das übliche 0x00 bzw. \n ersetzen.

Es gab aber auch eine Funktion, die nur n Zeichen vergleicht, mir fällt aber der Name nicht mehr ein :-(

Ich hoffe es hilft, Martin

EDIT: Nachtrag

Du kannst dann auch schreiben:


if (!UDR) b='1';

10.11.2004, 15:36
Hallo

Ich bin zwar nicht der Pointer Spezi, aber nach meiner Ansicht fehlt erstmal ein String, auf den der Pointer zeigen kann. Data ist ja nur als char definiert.
Von daher kann es auch immer nur ein Zeichen enthalten.

MFG
Dieter

martin
10.11.2004, 15:37
Stimmt eigentlich!

es müsste zumindest heißen:

volatile unsigned char *data[];

Und ich glaube, den Typecast auf char* kann man sich sparen.

Bitte jetzt nicht mit malloc() etc. anfangen, dann krieg ich die Krise :mrgreen:

10.11.2004, 16:23
Hi,

danke für die tips. werde die morgen in aller früh in die tat umsetzen.
Das mit dem *char[] ging glaub ich nicht(oder hatte ich nur char[] probiert?). man muss ne feste größe angeben oder?
Soweit ich weis kann man nur in java wirklich dynamische Felder anlegen.
man müsste in ca also sowas wie volatile unsigned *char[5] oder so schreiben.
nun gut. Ich probiers morgen nochmal. Neuer Tag neues Glück ;)

martin
10.11.2004, 21:22
Hallo Gast,

Ohne Größenangabe gehts nur, wenn du die Variable gleich initialisiert, z.B.


volatile unsigned char *data[] = "Steffen";


Ansonsten mach die Zahl so groß, dass alles vorkommende reinpasst. Aber dann wieder mit \n abschließen, sonst gehts mit strstr() schief.

Also:



volatile unsigned char *data[12];
oder
volatile unsigned char *data[] = "Steffen\n";


Du musst natürlich das gleiche vom PC senden.


Grüsse, Martin

BomberD
11.11.2004, 05:29
Hallo,

jetzt wieder mal angemeldet :).
Hab ich mir schon gedacht das der Wert fest vorgegeben sein muss.
ui ui, da kommt ne ganze menge Speicherverschwendung auf mich zu,
da wie gesagt ja ne variable Anzahl an Zeichen 'rüberkommen' kann.
Dennoch danke ich probiers gleich aus;)

BomberD
11.11.2004, 06:23
Hi,

Bin schon n bissel C eingerostet. Warum gehts dann aber hier?
Ich würds schön finden wenn ich einfach meinen Pointer weitersetzen kann.

void SendeString (char *szBuf)
{
while (*szBuf) {
loop_until_bit_is_set (USR, UDRE); /* warten bis Senden moeglich */
UDR=*szBuf;
szBuf++;
}
}

wenn ich jetzt einen char pointer array anlege sondern ein char array und nen pointer der auf ein element des arrays zeigt?
Dann müsst ich nur noch wissen wie man nen pointer auf etwas zeigen lässt :/

Wie Leere ich denn ein char Array? Muss ich durch alle Elemente laufen und 0x00 reinschreiben? oder gibts da wat schöneres?