PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : getsUSART auf mega168 läuft nicht [gelöst, nicht lesenswert]



oberallgeier
22.05.2008, 23:31
Schönen Abend,

warum sollte denn meine eigene USART-Leseroutine laufen, wenn´s viele andere nicht tun? Ich wollte das selbst schreiben, weil ich bei einer fertigen Lib eben nix lernen kann. Jetzt sitze ich wieder einmal ziemlich lang dran, und es geht und geht nicht.

Bitte kann mir jemand helfen?

Mega168, 20 MHz, sendUSART läuft bei 57600 Baud einwandfrei. Bei der gleichen Konfiguration (aber auch bei z.B. 9600 Bd) kann ich keine Daten an den Controller senden.

Aufgabe:
1) Sende vom Controller an das Terminal einige Zeilen, u.a. mit Mess- und Steuerwerten.
2) Lies mit dem Controller den vom Terminal kommenden String aBc322xy ein, extrahiere die drei Ziffern und weise die Zahl der Variablen Ipwmsrv zu, die bei der Anzeige der nächsten Zeile mit Messwerten ans Terminal gesendet wird.

Lösung:
1) Läuft (seit langem, störungsfrei)
2) Läuft nicht.

Initialisierung des USART und Sende- bzw. Leseroutinen
/* ================================================== ============================ */
/* Initialisiere USART0 mit vorgegebener Baudrate Neu am 07jan2008
Zum Senden von Zeichen im Hauptprogramm entweder nach doc2545, S179
char irgendwas[] = "meintext";
sendUSART(irgendwas); oder direkt
sendUSART("meinText"); verwenden. */
void init_USART0( unsigned int ubrr )
{ // Set baud rate
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr; // Enable receiver and transmitter
UCSR0B = (1<<RXEN0)|(1<<TXEN0); // Set frame format: 8data, 2stop bit
UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00); // 8 Data, (async: UMSELnx empty, doc S193)
// no parity weil UPMn1:0 empty, 1 Stop, weil UPMn1:0 empty
}
/* ================================================== ============================ */
void sendchar(unsigned char c) // ... vgl. code sample in doc2545, S 180
{ // Wait for empty transmit buffer
while(!(UCSR0A & (1<<UDRE0))) //Warten, bis Senden möglich ist
{ }
UDR0 = c; //schreibt das Zeichen aus 'c' auf die Schnittstelle
}
/* ================================================== ============================ */
void sendUSART(char *s) // *s funktiniert wie eine Art Array - auch bei
// einem String werden die Zeichen (char) einzeln ausgelesen - und auf die
// Sendeschnittstelle übertragen
{
while(*s)
{
sendchar(*s);
s++;
}
}
/* ================================================== ============================ */
/* === Hole Daten vom USART0 ======================== Neu am 22mai2008
=== vgl. dazu doc2545 und AVR-Gcc-Tutorial.... =================== */
char getchar(void) // ... vgl. code sample in doc2545, S 183
{ // Wait for data to be received
while(!(UCSR0A & (1<<RXC0))) //Warten, bis Empfang möglich ist
{ } // Get and return received data from buffer
return UDR0; //hole das Zeichen vom Puffer und return
}
/* ================================================== ============================ */
void getsUSART(char* Buffer, uint8_t MaxLen)
{
uint8_t NextChar;
uint8_t StringLen = 0;

NextChar = getchar(); // Warte auf und empfange das nächste Zeichen
// Sammle solange Zeichen, bis:
// * entweder das String Ende Zeichen kam
// * oder das aufnehmende Array voll ist
while( NextChar != '\n' && StringLen < MaxLen - 1 ) {
*Buffer++ = NextChar;
StringLen++;
NextChar = getchar();
} // Noch ein '\0' anhängen um einen Standard
// C-String daraus zu machen
*Buffer = '\0';
}
/* ================================================== ============================ */

Das GAnze wird vom main aus aufgerufen:
// div. zur Dokumentation, Deklarationen, Includes ...

#define MCU = AVR_ATmega168

// Mit Quarz 20 Mhz-CPU
#define F_CPU 20000000
#define BAUD 57600
#define MYUBRR (unsigned int)(F_CPU/16/BAUD-1) //nach doc2545, S 179

// - - - diverse Subroutinen - - - - - - - - - - - - -

int main(void)
{

char wortadc[10], instrng[10], izahl[4];
uint8_t i;

// verschiedene Initialisierungen (Ports, Timer etc).

init_USART0(MYUBRR); //USART0 initialisieren mit wählbarer Baudrate (s.o.)

// - - - verschiedene Aktionen - - - - - - - - - - -

// ================================================== ==============================
// Vierter Testabschnitt Abstandserkennung mit SFH5110-36 / SFH415
// modifiziert aus Rev x20b => x21, siehe oben
// Aufgabe: Ausgabe der PWM-Ansteuerung bei der der 5110 schaltet auf USART

uint8_t mecho = 50; //, nz = 0;
uint16_t istaus=0; // uint16_t istaus=0, inix=0;

sendUSART("\t Freies Messen ca. Sekundentakt, 120 => 0\r\n"); // Meldung ausgeben

for (;;)
{
mecho = ReDiM();

waitms(1000); //

sendUSART("\tAR \t"); // Ausgabezeile eröffnen
utoa(mecho, wortadc, 10); //aktuellen Rampensteuerwert ...
sendUSART(wortadc); // ... ausgeben
sendUSART("\t"); // Tabulator senden

utoa(Isvs1, wortadc, 10); //aktuellen Servosteuerwert ...
sendUSART(wortadc); // ... ausgeben
sendUSART("\t"); // Tabulator senden

utoa(Ipwmsrv, wortadc, 10); //aktuellen Servosteuerwert ...
sendUSART(wortadc); // ... ausgeben
sendUSART("\t"); // Tabulator senden

sendUSART("\r\n"); // Zeilenabschluss ausgeben

// Hier testweise einen String mit 8 (0 .. 7) Zeichen einlesen.
// Die Zeichen 3-5 enthalten einen Zahlenwert in ASCII. Dieser Wert wird nach
// dem Einlesen der Variablen Ipwmsrv zugewiesen und beim nächsten
// Mal angezeigt.
/*

getsUSART(instrng, 8);

for (i = 0; 2; i++)
{
izahl[i] = instrng[i+3];
}
izahl[3] = '\0';

Ipwmsrv = atoi(izahl);
*/
// ######## Hier testweise einen String mit 6 (0 .. 5) Zeichen einlesen. Ende

mecho = 0;
istaus = 0;

}
// ===== Ende des vierten Testabschnittes ======================================
... und wenn getsUSART aktiviert wird, dann hängt der Controller nach der ersten Zeile Messwertausgabe. Ohne getsUSART läuft die Ausgabe und läuft und läuft, siehe folgende Ausgabe (Tabs werden nicht angezeigt):

Platine m168D/20 bzw. Flex168
m168D_10x15.c 22mai08 2223 + m168D-libs-10x01/2.h
- - -
mecho Isvs1 Ipwmsrv
- - -
Freies Messen ca. Sekundentakt, 120 => 0
AR 120 29 0
AR 120 31 0
AR 120 33 0
AR 120 35 0
AR 120 37 0
AR 120 17 0
AR 120 19 0
Bitte findet jemand einen Fehler oder mehrere? Danke im Voraus

SprinterSB
23.05.2008, 00:09
#define MYUBRR ((unsigned int)((unsigned long) F_CPU/16/BAUD-1))

oberallgeier
23.05.2008, 00:24
Hallo Georg-Johann,

vielen Dank für die schnelle Antwort. Leider hat´s das nicht gebracht - die Ausgabe bleibt stehen nach der ersten Zeile (wie vorher):


Platine m168D/20 bzw. Flex168
m168D_10x15.c 23mai08 0022 + m168D-libs-10x11.h
- - -
mecho Isvs1 Ipwmsrv
- - -
Freies Messen ca. Sekundentakt, 120 => 0
AR 120 29 0
Aber danke für Deine Mühe

McJenso
23.05.2008, 14:44
Hallo,



for (i = 0; 2; i++)


:shock:

Gruß

Jens

oberallgeier
23.05.2008, 18:07
Hallo Jens, danke ich habs geändert (ich mach ziemlich viel Fehler und nenne die Anfängerfehler), war erst verwundert, aber ich hatte ja nach Fehlern gefragt - und der Schock-smiley war deutlich! Hmmm, aber auch ein
i = <=2;
hilft nicht. Ich kann ja nicht mal EIN Zeichen empfangen:

sagt die Ausgabe am Terminal

Platine m168D/20 bzw. Flex168
m168D_10x15.c 23mai08 0022 + m168D-libs-10x11.h
- - -
mecho Isvs1 Ipwmsrv
- - -
Freies Messen ca. Sekundentakt, 120 => 0
AR 120 29 0
Aufruf getchar folgt... und es folgt eben GARNIX, obwohl ich mehrere Zeichen an den Controller gesandt hatte. Dabei hatte ich folgenden Aufruf im main:

...
utoa(Isvs1, wortadc, 10); //aktuellen Servosteuerwert ...
sendUSART(wortadc); // ... ausgeben
sendUSART("\t"); // Tabulator senden

utoa(Ipwmsrv, wortadc, 10); //aktuellen Servosteuerwert ...
sendUSART(wortadc); // ... ausgeben
sendUSART("\t"); // Tabulator senden

sendUSART("\r\n"); // Zeilenabschluss ausgeben

sendUSART ("\tAufruf getchar folgt\r\n");

k = getchar();

sendUSART ("\tAufruf getchar ist erfolgt\r\n");
Und ich hab das gerade eben nochmal geprüft - der code, siehe oben bei Initialisierung, stimmt mit dem Schnippsel im doc 2545 überein :(
Und einen Vergleich mit der entsprechenden Function "uart_getc()" bei pfleury übersteigt meine C-Kenntnisse.

McJenso
23.05.2008, 19:03
Hallo,

sorry für die kurze Antwort. Ich nenne so etwas bei mir dann zu spät, zu müde, blind ...
So hat jeder seine Ausreden ;-)
So jetzt im ernst, kannst du einen Hardwarefehler ausschließen? Du hast doch sicher einen MAX 232 zwischen Controller und PC. Wenn du den Controller vom MAX trennst und dafür eine Brücke einsetzt, solltest du beim Senden vom PC aus dein Echo empfangen.
Mit einer LED am Controller kannst du den Punkt finden, an dem er hängen bleibt. Einfach eine Anweisung zum Einschalten der LED durch den Code schupsen. Irgendwann sollte sie dann ja nicht mehr an gehen.

Gruß

Jens

oberallgeier
23.05.2008, 20:35
Hallo Jens,


... sorry für die kurze Antwort... Um alles in der Welt - ich bitte Dich. Ich hatte es doch schon verstanden. Und ich bin froh um Deine Antworten, siehe gleich.

... kannst du einen Hardwarefehler ausschließen? ... MAX 232 zwischen Controller und PC ... Brücke ... Echo ... LED am Controller ...Nun, ich hatte die Diagnostik etwas abgewandelt. Mit Kanonen auf ... Wolln mal so sagen, der, nein die Fehler sind behoben, bitte nicht weiterlesen.

1. Es fehlte EINE Lötverbindung von der RS232 zum MAX 232. Die wurde nach einem Test am Controllerpin und MAX232-Pin beim "Empfangen" anhand des Oszilloskopbildchens festgestellt (und weils kein DSO ist, hatte ich 600 Baud gewählt ...). Kein Wunder, dass frühere Versuche so danebengingen . . . .
2. Dann testete ich ja eingangs mit Eingabe der Zeichenfolge abc321xy. Den ausgeblendeten String "321" wandelte ich in die unsigned integer "Ipwmsrv" . . . und wunderte mich, dass dauernd 65 rauskam :(.

Aber jetzt läufts:

Platine m168D/20 bzw. Flex168
m168D_10x15.c 23mai08 2008 + m168D-libs-10x11.h
- - -
mecho Isvs1 Ipwmsrv
- - -
Freies Messen ca. Sekundentakt, 120 => 0
AR 120 29 0
Aufruf getsUSART folgt
Aufruf getsUSART ist erfolgt
aBc128x
128
AR 120 31 128
Aufruf getsUSART folgt
Aufruf getsUSART ist erfolgt
aBc128x
128
AR 120 33 128
Aufruf getsUSART folgt
Und nun muss ich bei meinem Alter überlegen, ob das noch Anfängerfehler sind oder beginnende Demenz.

DANKE Jens, danke Georg-Johann

Sternthaler
24.05.2008, 20:47
bitte nicht weiterlesen.
Kommt gar nicht in Frage ;-)

Gruß Sternthaler