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
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