Hallo, nach langen Versuchen möchte ich hierum Hilfe bitten.
Es geht da drum zu erkennen ob der RS485 Bus noch Daten sendet, in
dieesm Fall ob dieser angeschlossen ist oder nicht.
Der 485 Bus wird für'n Atmega in 232 umgewandelt
Von einen externen Gerät bekomme ich in Sekunden Takt ein Zeichen an
meinen Atmega32 mit LC-Display gesendet :
71,79,82
Was das alles auf sich hat ist unwichtig. Das System funktioniert. Wenn
ich den Bus angeschlossen habe gibt der Atmega immer das richtige aus.
Nun möchte ich das dieser erkennt ,dass wenn 2 Sek kein Zeichen kommt
ein Fehler ausgibt. Die funktioniert bislang nur wenn ich den Atmega
Resete und den Bus nicht angeschlossen habe. Schließe ich nun den Bus an
springt er sofort auf die jeweilige Anzeige. Ziehe ich diesen wieder ab,
erkennt der Atmega aber trotzdem das letzte Zeichen und springt in die
dazu gehörige Routine.
Durch das Debuggen hab ich raus gefunden ,dass troz nicht anliegen Bus
das RXC Bit im UCSRA gesetzt ist und deshalb nicht in meine Routine
springt die nach 2 Sek anzeigen soll das nichts anliegt. Kann ich dieses
Bit "clearen" oder etc ? Damit er erkennt das nichts anliegt oder
übersehe ich etwas offensichtliches ?
Er springt also in :
1
if(UCSRA&(1<<RXC))
2
{
3
Zeichen=uart_getchar();//Empfängt Zeichen am UART Eingang und überträgt dieses an die Variable Zeichen
4
}
obwohl der Bus abgezogen wurde.(Immo. mit Steckverbinder)
Hier mal der Code , Code wird noch aufgeräumter (bitte keine Kommentare
zum printf Befehl =) )
1
//_________________Main____________________
2
ISR(TIMER1_COMPA_vect)//Timer1 Routine
3
{
4
PORTA^=0x20;//Dieser Pin wird durch die Exklusiv Oder Verknüpfung getoggelt
5
}
6
7
ISR(TIMER0_COMP_vect)
8
{
9
mS++;
10
if(mS==1000)
11
{
12
Sek++;
13
mS=0;
14
}
15
}
16
17
intmain(void)
18
{
19
DDRA=0b00100000;//Deklaration 11110000 1=Ausgang 0=Eingang // X1-4a bis 7c
Deine Timeout Sache.
Grundsätzlich solltest du von derartigen Timer Start/Stop Dingen Abstand
nehmen. Das ist meistens viel zu kompliziert.
Einen Timer startet man einmalig beim Programmstart und dann lässt man
ihn im Normalfall durchlaufen.
Deine ISR sieht so aus
1
volatileuint8_tms;
2
3
ISR(...)
4
{
5
if(ms<2000)
6
ms++;
7
}
d.h. der Timer versucht ständig ms zu erhöhen, bis er bei 2000
angekommen ist.
Was ihn daran hindert, die 2000 zu erreichen, das ist das Eintreffen
eines Zeichens, welches die Variable ms wieder auf 0 zurück setzt.
1
while( 1 ) {
2
3
Sieh nach ob ein Zeichen da ist und wenn ja {
4
hole es
5
werte das zeichen aus
6
cli();
7
ms = 0;
8
sei();
9
}
10
11
andernfalls
12
mach irgendwas mit dem Timeout-Timer
13
}
und natürlich wird dann im Falle, das kein Zeichen eingetroffen ist,
diese Variable untersucht, ob sie die 2000 erreicht hat. Wenn ja, dann
sind 2 Sekunden seit dem letzten Zeichen vergangen. Wenn nein, dann ist
die Wartezeit noch nicht abgelaufen
1
while( 1 ) {
2
3
Sieh nach ob ein Zeichen da ist und wenn ja {
4
hole es
5
werte das zeichen aus
6
cli();
7
ms = 0;
8
sei();
9
}
10
11
andernfalls {
12
cli();
13
if( ms == 2000 )
14
Timeout ist aufgelaufen!
15
sei();
16
}
17
}
(da ms eine uint16_t Variable ist, müssen Zugriffe aus main mit cli()
bzw. sei() gekapselt werden.)
Hallo, tue ich dies nicht im nachfolgen Code ?
Das Zeichen was ankommt wird auf die Variable Zeichen geschrieben und
dann dementsprechend reagiert.
Der ATmega erkennt aber ein Zeichen obwohl Keins kommt und aber er
springt in diese Routine.
Jakob schrieb:> Hallo, tue ich dies nicht im nachfolgen Code ?
Nein.
Ich hab dir extra eine Codezusammenfassung geschrieben.
Du versuchst Zeichen IMMER auszuwerten. Egal ob was reingekommen ist
oder nicht.
> Das Zeichen was ankommt wird auf die Variable Zeichen geschrieben und> dann dementsprechend reagiert.
nicht dementsprechend.
Du reagierst immer, egal ob was reingekommen ist oder nicht.
Deine Zeichenauswertung hängt in keinster Weise davon ab, OB ein Zeichen
eingetrudelt ist oder nicht.
> Der ATmega erkennt aber ein Zeichen obwohl Keins kommt und aber er> springt in diese Routine.
In welche Routine?
Der Teil hier
1
...
2
switch(Zeichen)
3
{
4
case79:// O in Ascii = 79. Die Zeichen werden in Ascii übermittelt
5
LCD_xy(0,1);
6
printf("---FBE-System---");
7
LCD_xy(0,2);
8
printf("Signalausfall!!!");
9
Startclock=0;
10
Sek=0;
hängt bei dir nicht davon ab, ob ein Zeichen angekommen ist oder nicht.
Was jetzt natürlich noch sein kann, dass ist das du ja einen offenen
Eingang hast, wenn du das Kabel abziehst. Und dann fängt sich der offene
Eingang jedes elektromagnetische Feld aus der Umgebung ein, das er
kriegen kann.
Karl Heinz schrieb:> Was jetzt natürlich noch sein kann, dass ist das du ja einen offenen> Eingang hast, wenn du das Kabel abziehst. Und dann fängt sich der offene> Eingang jedes elektromagnetische Feld aus der Umgebung ein, das er> kriegen kann.
Würde dann doch auch beim Start tun, wenn der Stecker gezogen ist.
Ich werde mich später noch mal damit beschaffen und den Kopf frei
kriegen.
1
if(UCSRA&(1<<RXC))
2
{
3
Zeichen=uart_getchar();//Empfängt Zeichen am UART Eingang und überträgt dieses an die Variable Zeichen
4
}
Hier erkennt er doch ob ein Zeichen ankommt oder nicht ? Andernfalls
springt er in die else Routine. Dies macht er aber nicht da er noch
etwas im UCSRA gesetzt hat.
Naja ich hoffe ich bekomme es nachher hin.
mfg.
>Zeichen=uart_getchar();//Empfängt Zeichen am UART Eingang und
4
>überträgtdiesesandieVariableZeichen
5
>}
>> Hier erkennt er doch ob ein Zeichen ankommt oder nicht ? Andernfalls> springt er in die else Routine. Dies macht er aber nicht da er noch> etwas im UCSRA gesetzt hat.
Woher weisst du, das er das nicht macht?
In deinem Else Zweig machst du nur dann irgendwas sinnvolles, wenn die
zeit abgelaufen ist. Und genau die setzt du aber in den nachfolgenden
switch-case immer wieder auf 0 zurück. Hat der µC einmal ein gültiges
zeichen dann hat er das auch weiterhin und setzt dann auch weiterhin die
Zeit immer wieder zurück.
> Naja ich hoffe ich bekomme es nachher hin.
Bau erst mal deinen Code vernünftig auf. Ich denke, du hast dich da
jetzt ganz einfach nur planlos verrannt. Und dein geschwätziger Code tut
sein übriges, dir den Überblick schwer zu machen.
1
volatileuint16_tms;
2
3
#define TIMEOUT_TIME 2000 // in Millisekunden
4
5
ISR(...)
6
{
7
if(ms<TIMEOUT_TIME)
8
ms++;
9
}
10
11
voidProcessCharacter()
12
{
13
charc=getchar();
14
15
cli();
16
ms=0;
17
sei();
18
19
LCD_xy(0,2);
20
21
// kein Grund da jetzt 79 hinzuschreiben.
22
// Wenn du 'O' meinst, dann schreib auch 'O'
23
// Schreib nicht im Kommentar hin, dass 79 der ASCII Code von 'O'
24
// ist, sondern schreib direkt im Code hin, dass hier ein 'O' gefragt
Danke, ich werde jetzt den Code aufräumen. Er war/ist wirklich
"vermüllt". Ich werde mich jetzt nach deinen Beispiel orientieren.
So jetzt funktioniert es erst mal :
1
if(UCSRA&(1<<RXC))
2
{
3
Zeichen=uart_getchar();//Empfängt Zeichen am UART Eingang und überträgt dieses an die Variable Zeichen