PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : UART empfangen geht nicht



i-wizard
08.06.2008, 21:51
Hallo Zusammen!

Meine Funktion getch() soll ein Zeichen über die UART-Schnittstellte einlesen. Jedoch passiert nichts.
Die Funktion putch() zum senden eines Zeichen geht einwandfrei.

Kann den Fehler einfach nicht finden. Vielleicht hat ja einer von euch eine Idee?

Vielen Dank!



#define TAKT 16000000UL
#define BAUD 9600UL
#define US1 0xE0
#define IRM 0
#define IRR 1
#define IRL 2



#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include "Motor/motor.h"
#include "IR/irmessung.c"
#include "US/usmessung.c"


//----------------------------Fuktionen-----------------------------------------------------------------//


//------------UART-Konfig---------------------//

void initusart (void){
unsigned char x;

UBRRL = (TAKT / (16UL * BAUD)) -1;
UCSRB |= (1 << TXEN) | (1 << RXEN);
UCSRC |= (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);


x = UDR;
}


//------------Char senden---------------------//

void putch (unsigned char x){

while ( ! (UCSRA & (1 << UDRE)));

UDR = x;
}

//------------Char emfangen---------------------//

unsigned char getch(void){

while (!(UCSRA & (1 << RXC)));

return UDR;
}

//------------Befehl einlesen---------------------//
void befehleinlesen (unsigned char *pbefehl, unsigned int anz){


unsigned char zwbef=0;
unsigned char zwerg=0;


zwbef=0xFF;


*pbefehl = zwbef >> 7;


//Motorbefehl
if(*pbefehl == 0x01){

zwerg=zwbef;
zwerg= zwerg & 0x60;
*(pbefehl+1)= zwerg >> 5;

zwerg=zwbef;
zwerg=zwerg & 0x10;
*(pbefehl+2)= zwerg >> 4;

zwerg=zwbef;
zwerg=zwerg & 0x0F;
*(pbefehl+3)= zwerg;

zwbef=0xFF;
*(pbefehl+4)= zwbef;
}



//Sensorbefehl
if(*pbefehl == 0x00){

zwerg=zwbef;

zwerg= zwerg & 0x70;
*(pbefehl+1)= zwerg >> 4;
}

}








//----------------------------Hauptprogramm-------------------------------------------------------------//


int main (void){

// Variablen
unsigned char i=0;
unsigned char vor=1; //Motorrichtung
unsigned char rck=0; //Motorrichtung
unsigned char wert=0; //IR Messwert
unsigned char befehl[5]; //Befehlsspeicher
unsigned char empfang
// Programmstart
initusart();


while(1){
empfang=getch();
getch();
befehleinlesen(befehl,5);
_delay_loop_2 (6000);
_delay_loop_2 (6000);
for(i=0;i<=4;i++) putch(befehl[i]);

/* //IR-Messen
wert=irmessung(1);
putch(wert);
_delay_loop_2 (6000);


*/

}

return 0;
}

McJenso
09.06.2008, 09:08
Hallo,

beim ersten drüber schauen fällt auf, dass getch() nie aufgerufen wird.
Hast du die Hardware geprüft.

Gruß

Jens

oberallgeier
09.06.2008, 09:54
Hallo i-wizard,


... Funktion getch() ... passiert nichts ... putch() zum senden ... geht einwandfrei ...Ach wie klingt mir das vertraut. Vor ´nem halben Monat hatte ich ganz genau den gleichen Stand (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=375334#375334). Trotz meiner Einschätzung, dass mein damaliger Thread nicht lesenswert ist (der Fehler war einfach zuuuuu doof) hilft er Dir vielleicht weiter. Damit will ich nicht sagen, dass Dein Problem doof ist ! ! !

i-wizard
09.06.2008, 10:15
Wenn ich am Controller den Rx Pin mt einem Oszi beobachte kommt dort ein Signal an. Es muss also ein Softwareproblem sein.

Ceos
09.06.2008, 10:22
wie Jenso schon bemerkt hat, WO und WIE hast du dein getch denn eingesetzt ? in deinem Quellcode jedenfalls wird es nie verwendet, dein problem ist SO nicht verständlich, poste mal bitte etwas code zu dem wie du es getestet hast

i-wizard
09.06.2008, 20:09
So habe mal 2 Variant wie ich getch() einsetzen will eingefügt. Wenn ich es nach der for-SChleife einfüge wird diese 1x durchlaufen.

Ceos
09.06.2008, 20:22
naja klar, wenn getch() da in der schleife steht wartet er jedesmal das ein byte ankommt, aber WO wertest du denn den "empfang" aus ?

mach doch mal testhalber ne simple echoschleife


while(1){
byte empfang = getch();
putch(empfang);
}

i-wizard
09.06.2008, 20:49
Es soll ja warten bis ein Byte kommt und ganau da liegt das Problem.

Wenn ich ein Byte sende macht er nicht weiter.


Das mit der Echo schleife habe ich schon probiert, da kommt nix.


Das Byte kommt aber elektrisch am Port an, hab das mit dem Oszi nachgemessen.

Die Fuktion putch() geht einwandfrei!

Ceos
09.06.2008, 21:44
mir ist grade bei deiner init() eine unstimmigkeit aufgefallen, kannst du SICHER sagen das gesendete bytes auch SO ankommen wie sie sollen ?


UBRRL = (TAKT / (16UL * BAUD)) -1;

in

UBRR = (TAKT / (16UL * BAUD)) -1;

ändern , ist schliesslich ein 16bit register und du spricht nur das low-byte an

versuch auch mal alternativ

UBRRH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;

so wird es im datenblatt EMPFOHLEN

wenn jetzt nix geht, sag mir noch fix welchen prozessor du hast, dann probier ichs selber, prüfe nochmal deine hardware, by the way ... wie sieht DIE eigentlich aus ?

i-wizard
10.06.2008, 07:06
Es handelt sich um einen ATmega32 mit 16Mhz.
Verdrahtungstechnisch scheint alles ok zu sein da ich die Bytes ja am RX -Pin des ATmega32 mit dem Oszi messen kann.

UBRR geht nicht direkt zu beschreiben. Habe es dann mit deiner Idee des schiebens Probiert also URBBL und URBBH. Wie bisher senden geht immer aber empfangen nicht.

Was ich noch nicht angemerkthabe: Es hat schon mal funktioniert!

Danke für die Tipps!!

Ceos
10.06.2008, 08:54
hm na wenn es schonma funktioninert hat, teste deine hardware,

wenns n max232 zum PC ist, verbinde mal die rx und tx die zum µC gehen und klimper im hyperterminal mal rum, wenn das nich geht iss der max232 im eimer, verwendest du auch DIESELBEN EINSTELLUNGEN im HT wie im µC? also 9600BAUD, 8 datenbit, 1 stoppbit ? ich hab auch ewig nach m fehler gesucht weil irgendwann das HT mal automatisch auf 2 stoppbit geschalten hat, keine ahnung warum ... wenn du KEINEN max232 verwendest mal bitte die schaltung posten die du verwendest .... wenn des mit dem verbinden von RX TX geht, wirds schwer mit ferndiagnose

McJenso
10.06.2008, 08:58
Hallo,

wenn das Senden funktioniert, wird die Baudrate richtig eingestellt sein. Hast du mit dem Oszi direkt am Pin gemessen? Was war anders als es schon einmal funktioniert hat. Software nutzt sich nicht ab :-)
Schreib den Empfang mal auf Interrupt um. Sprich RXCIE im UCSRB setzen. Globale Interrupts via sei(); einschalten und in der Interruptroutine ISR (USART1_RX_vect){ LED_EIN } einfach eine LED einschalten. Dann läuft das Programm weiter bis er etwas empfangen hat.

Gruß


Jens

Ceos
10.06.2008, 09:03
nicht ganz, mit 2 stopbit im µC und nur EINEM am PC hat das senden vom µC zum PC bei mir funktioniert, nur umgekehrt net, ich weis aber nciht wie sich das verhalten würde, wenn ich am PC 2 stopbit und am µC nur eins habe, aber gut möglich das es auch so n verhalten entwickelt

die idee mitm interrupt ist nich schlecht, zumal dein programm dann nicht unsinnig auf ankommende bytes warten muss sondern fröhlich weiterarbeiten kann bnis wirklich mal ein byte ankommt

oberallgeier
10.06.2008, 09:25
... ATmega32 mit 16Mhz ... UBRR geht nicht direkt zu beschreiben. Habe es dann mit deiner Idee des schiebens Probiert also URBBL und URBBH. Wie bisher senden geht immer aber empfangen nicht ...Dazu gibts doch für die RNControl:
1) eine funktionierende Schaltung im RNControl-Schaltplan
2) im C-code auch die dazugehörige(n) Module zum Initialisieren. Bei mir läuft das.

Aktuell (ohne lang suchen zu müssen) hab ich meine lauffähigen Schnippsel zum mega168:
a) die defines

// 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
b) Aufruf der Initialisierung

init_USART0(MYUBRR); //USART0 initialisieren mit wählbarer Baudrate (s.o.)
c) Initialisierung des USART0 mit Empfangsroutinen:
/* ================================================== ============================ */
/* 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
}
/* ================================================== ============================ */
/* ================================================== ============================ */
/* === 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';
}
/* ================================================== ============================ */
Und das läuft so :)

Ceos
10.06.2008, 09:30
wie kommst du auf RNControl ?

ausserdem glaub ich nicht das er ne fertige softwarelösung sucht sondern versucht ein problem zu beheben, schliesslich hat es schonmal funktioniert!

oder hab ich da was falsch verstanden ??

McJenso
10.06.2008, 19:09
Hallo,
die Baudrate hat erstmal nichts mit den Stopbits oder der Anzahl der Datenbits zu tun. Wenn das Senden funktioniert, sind die UBRR für mich erst einmal richtig.
Hinter dem Interrupt steckt noch etwas anderes. Der RxD Pin des Controllers sitzt neben dem einen Quarz-Pin. Woher wissen wir den, dass der Controller wirklich in der While- Schleife hängt und sich nicht beim Eintreffen der Daten ins Nirwana verabschiedet hat?
Mein Favorit ist die Hardware.

Gruß

Jens

i-wizard
11.06.2008, 14:48
Hallo Zusammen!

Erstmal vielen Dank für eure Hilfe!!!

Ich kann mitteilen das ich die Wurzel des Problem gefunden habe:

ATmega32

Nach längerem suchen mit dem Oszi habe ich einfach den AVR gegen einen neuen ungenutzen ausgetauscht und...

...ohne an Software oder Schaltung etwas zu ändern gehts.

Ich vermute einfach mal das Harwareseitig im ATmega32 etwas kaputt ist bzw. des ja mal ging kaputt gegangen ist.

Nochmal herzlichen Dank für eure Hilfe!!

oberallgeier
11.06.2008, 17:16
... habe ich einfach den AVR gegen einen neuen ungenutzen ausgetauscht und...

...ohne an Software oder Schaltung etwas zu ändern gehts.Aber programmiert hast Du diesen
... neuen ungenutzen ...doch wohl schon ! ? ! ?

i-wizard
24.06.2008, 11:32
Na klar habe ich ihn programiert! ;-)