Hallo zusammen
Zur Aufgabenstellung:
Ich muss einen PIC18F452 für eine Überwachung programmieren. (im Grunde
einen kleinen Watchdog).
Dieser muss von der seriellen Schnittstelle die Daten auswerten, welche
er empfängt. Stimmen diese (Status-)Daten nicht mehr, wird einfach ein
Alarmausgang geschaltet. Als Eingang zum PIC verwende ich einen MAX202.
Das Problem liegt daran, dass ich keinen String (mit Abschluss CR)
empfange.
Somit muss ich doch jede Zeichenkette, welche sporadisch an meinen PIC
gesendet werden, auswerten.
Und weil zusätzlich noch andere Daten über die RS232 Schnittstelle
gesendet werden, muss ich auf ein spezielles Muster im Datenstring
ausschau halten.
Wie ich das gesehen habe, werden über die serielle Schnittstelle nur
reine HEX-Werte geschickt.
Das Statusmuster sieht folgendermassen aus: 02 03 00 FF 00 FF
Sollte nach 02 03 00 FF keine 00 erscheinen, muss der Alarmausgang
geschaltet werden.
Nach meinen Kenntnisse benutzt man doch hierfür einen #int_rda und dann
den Befehl getc. Leider bin ich mir nicht sicher, ob ich die Konfig
richtig eingestellt habe.
Hier einmal ein Teil des Codes
Ich nehme an, der Empfang eines Zeichens generiert einen Interrupt und
IntRS ist Deine Interrupt-Service-Routine.
Darin liest Du aber mehrere Zeichen, die ev. noch gar nicht eingetroffen
sind.
Du solltest in IntRS eher eine Statemachine programmieren, jeweils genau
ein Zeichen liest und RSstatus hochzählt.
Ausserdem brauchst Du einen Timer um einen Timeout zu generieren, wenn
nach Empfang von FF innert einer von Dir zu definierenden Zeit kein 00
folgt.
Alles klar?
Severino
Hallo Severino
>Ich nehme an, der Empfang eines Zeichens generiert einen Interrupt und>IntRS ist Deine Interrupt-Service-Routine.
Das stimmt genau. Dies ist meine Interrupt-Service-Routine.
Mein Problem liegt jetzt genau in dieser Statemachine, welche nur 1
Zeichen liest. Nach dürchstöbern von mehreren Literaturen komme ich
nicht auf den Befehl, mit welchem ich nur 1 Zeichen einlesen kann.
Vielleicht kannst du mir hier weiterhelfen.
>Ausserdem brauchst Du einen Timer um einen Timeout zu generieren, wenn>nach Empfang von FF innert einer von Dir zu definierenden Zeit kein 00>folgt.
Dieser Timer für den Timeout habe ich implementiert.
Danke für deine Bemühungen
getc() liest meines Wissens genau ein Zeichen ein.
(Was geschieht, wenn gar kein Zeichen da ist, weiss ich nicht auswendig,
ich denke, getc() wartet dann bis eines eintrifft).
IntRS liest mehrere Zeichen ein, solange es sich um die erwarteten
Zeichen handelt und sie in der richtigen Reihenfolge eintreffen.
Was andernfalls geschieht, bleibt offen (kein else). Alarm ist dann
undefiniert (übrigens, wo wird die Variable definiert?)
Mindestens sollte Alarm vor dem ersten if auf 1 gesetzt werden, damit es
(nur) im korrekten Fall gegen Ende auf 0 zurückgesetzt wird.
Bleibt das Problem, dass Du in der ISR mehrere getc() hast, und das
Programm dort wartet, bis ein weiteres Zeichen eintrifft. In einer ISR
sollte man nie warten.
Prüfe mal in der Doku zu getc(), was geschieht, wenn gar kein Zeichen
ansteht. Wenn getc() ewig wartet, brauchst Du eine Funktion, die Dir
sagt, ob überhaupt ein Zeichen im Empfangspuffer steht. Dann könntest Du
das Ganze sogar ohne Interrupts lösen.
Severino
getc() liest ein Zeichen, dies funktioniert jetzt auch. Schon einmal
hier ein Dankeschön Severino.
Nun habe ich dies folgendermassen gelöst: Ich verwende keinen Interrupt
für die Datenauswertung. Sondern löse dies über eine Schlaufe. Dort
wartet der PIC mit dem Einlesen (getc();) bis Daten auch vorhanden sind.
Das ist für mich so in Ordnung.
Nun habe ich nur noch ein anderes Problem.
Nach dem dritten Einlesen steht der PIC still. Ich kann weder Daten
einlesen, noch welche aussenden. Überhaupt passiert nichts mehr.
Kann es sein, dass die Daten langsamer/schneller empfangen werden
müssen, als dies ich eingestellt habe (RS232 Geschwindigkeit stimmt mit
der anderen überein)?
Hier nochmals der Code von der Schlaufe.
Danke
1
// Von RS232 lesen
2
3
booleanIntRS(void){
4
booleanOK=true;
5
//char RSBuf; // RS232-Zeichenlänge definieren
6
disable_interrupts(int_rda);// Interrupts RS232 aus
7
//enable_interrupts(int_timer2); // Timer2 "Stringlänge empfangen" ein
Bei der vierten Zahl prüfst Du zwar auf ==0x00, schreibst dann aber:
printf("Zahl_4 (FF) OK ");
(Schönheitsfehler?)
Sendest Du dem PIC überhaupt eine vierte (und fünfte) Zahl?
Wenn nicht, "hängt" er in while (!kbhit()).
Hast Du einen ICD2 oder sonst ein Debug-Werkzeug, um zu sehen, was der
PIC macht?
Oder könntest Du das Ding in MPLABs Simulator testen (weiss nicht, wie
weit die UART-Simulation läuft).
Jedenfalls denke ich, dass in der while-Schleife zusätzlich nach einem
Timeout abgefragt werden sollte, z.B.
Hallo Severino.
(sorry die Verspätung, war unvorhersehbar geschäftlich unterwegs)
Nun zu meinem Programm:
Ich habe zwar ein ICD2, kann diese Anwendung jedoch dort nicht
einsetzen. Die Überwachung muss in einem Gerät (mit einer bereits
angefertigten Plattine) eingesetzt werden.
Ich sehe also nur, ob das Programm läuft (oder eben nicht :-( )
Ich habe die serielle Schnittstelle über einen Interrupt eingelesen:
Und wie ich dies gesehen habe, funktioniert das Einlesen bis zur Zahl 03
recht gut. Im Moment habe ich noch zwei Probleme:
1. Wenn ich das Programm laufen lasse, bleibt er mir beim Wert 00
"stehen".
2. Wenn ich die dritte Überprüfung (0x00) nicht vornehme (also
auskommentiert) und ich die Zeile "RS232 Counter reset" gesendet habe,
bleibt das Programm auch stehen.
Es müsste doch mindestens noch den printf("Durchlauf OK"); gesendet
werden, was leider nicht der Fall ist.