Hallo folks, ich bin auf Euren Rat bzw Eure Hilfe dringend angewiesen. ich schreibe für einen PIC16F887 ein Programm, welches mit einem GSM-Modem mc35i (Siemens/Cinterion) kommuniziert. Reines Senden PIC > Modem (zB 'ATDTnnnnnnnnn') funktioniert einwandfrei. Beim Empfang haperts jedoch gewaltig. Hier der relevante Codeausschnitt: rs232-settings: BRGH=1; // Baudrate 9600 Bits/s @ 4MHz SPBRG=25; SYNC=0; // USART Empfaenger enablen SPEN=CREN=TXEN=1; // USART Sender enablen wenn ich jetzt folgendes mache PIC > Modem sendet: 'ATI[CR]' krieg ich bei einem normalen Terminalprogramm (hyperterminal) die normale Antwort (drei Zeilen 'Selbstgespräche' des Modems ;.)) mit meinem Programm/schnipsel/ (im Anschluss an obiges ATI-command) while(1) { if(RCIF) { // interrupt gesetzt? z=RCREG; // Empfangsregister auslesen lcd_dat(z); // Ausgabe am LCD } } erhalte ich jedoch nur ZWEI buchstaben ("AT"). Das ist genau die Anzahl von Zeichen, die der USART aufnehmen kann, ohne ausgelesen werden zu müssen. In der Doku zum USART steht weiters, dass nach dem Lesen des RCREG das RCIF Interruptflag gelöscht wird. Hab auch schon versucht, nach dem Lesen von RCREG das RCIF 'händisch' im Prog zu löschen - erfolglos. Kann mir jemand einen Tipp oder eine funktionierende C-routine geben? Vielen Dank schon mal jetzt!! Rudi Ratlos
mal über den Rx-Interrupt die empfangenen Zeichen in einen Buffer schreiben. gruss
Danke für die schnelle Antwort! Interrupt wollt ich mir dafür eigentlich sparen.... Geht es auch anders? RudiR
du weisst schon, dass Deine Variable z immer den Wert des aktuell empfangenen Zeichens annimmt. Was "lcd_dat()" macht weiss ich nicht. Wenn Du das Flag von Hand gelöscht hast (richtig ;-)) und Du nicht alle Zeichen empfängst..., hmmm wie lange dauert "lcd_dat()" ?
> du weisst schon, dass Deine Variable z immer den Wert des aktuell > empfangenen Zeichens annimmt. ja, dieses will ich ja auslesen. Oder willst Du mir damit etwas anderes sagen? > Was "lcd_dat()" macht weiss ich nicht. sorry, dachte, geht aus dem comment hervor. es gibt das zeichen am lcd-display des uC aus. > Wenn Du das Flag von Hand gelöscht hast (richtig ;-)) wobei mir die Doku in dem Moment sagt: das RCIF ist readonly.... > und Du nicht alle Zeichen empfängst..., hmmm wie lange dauert "lcd_dat()" ? hmm, schwer zu sagen. Bin kein timing-experte. Sind insgesamt 18 einfache C-Zuweisungen, ein nop() in C sowie ein delay von 1ms. Hilft das weiter? Denke mal, mit den 9600 baud sollte das aber mithalten können... LG Rudi
RudiR schrieb: > Interrupt wollt ich mir dafür eigentlich sparen.... > Geht es auch anders? Nein geht es nicht. Zumindest nicht sinnvoll. Das wird sonst nur so ein hingekrempeltes Zeug. Interrupts sind garnicht so schlimm wie man als Anfänger denkt. Ein paar Register und fertig ... ich helf dir gerne ...
Danke für Dein Angebot, Michael! Ich bin schon mal dran, das auf interrupts umzuschreiben, im Mom kämpf ich noch mit Compilerdirektiven, damit er die richtigen Register rettet (ich arbeite mit dem cc5x). Ich komm sicher wieder auf Dich zu! LG Rudi
Und da bin ich auch schon wieder... meine int-routine sieht jetzt so aus: interrupt ISR(void) { // Interruptroutine int_save_registers // W, STATUS (und PCLATH) retten if(RCIF) { usartbuff[usartind]=RCREG; usartind++; } // und hier weiterer code, der interruptmäßig abgefackelt wird.... ... ... int_restore_registers // W, STATUS (und PCLATH) wiederherstellen } also will ich bei einem INT das RCREG in den 80-stelligen usartbufffer schreiben... mein hauptprogramm: for(i=0; i<=79; i++) usartbuff[usartind]='.'; // usartbuffer sicherheitshalber löschen usartind=0; // rs232_print("ATI"); delay(100); // Modeminfo abholen for(i=0; i<=20; i++) lcd_string(usartbuff[usartind]); // usartbuffer ans LCD senden ergebnis: seltsame zeichenfolgen am display: ART ART ART ART ART ART ART ART ART ART ART ART Diese Buchstabenkombi ist Teil einer Zeichenkette, die an den USART gesendet wird, der aber in einem anderen Programmteil liegt und überhaupt nicht angesprochen wird.... Merkwürdig... kannst Du mir bitte vll. helfen? Danke, RudiR
warum nicht gleich so ;-) vielleicht leigt es daran, dass Deine Lcd-Ausgabe ist nicht mit dem Empfang synchronisiert ist. Du kannst ein Flag im INT setzen, wenn der String vom Modem komplett eingelesen wurde. Ich meine mich zu erinnern, dass die Strings mit Carriage Return oder ähnlichem abgeschlossen werden.
Versuchs mal so: for(i=0; i<=79; i++) usartbuff[usartind]=0; // usartbuffer sicherheitshalber löschen usartind=0; // rs232_print("ATI"); delay(1000); // Modeminfo abholen lcd_string(usartbuff); // usartbuffer ans LCD senden
hallo folks, dank Eurer Hilfe läuft das Ding jetzt zufriedenstellen. Zusammengefassst: Meine Interruptroutine (unverändert): interrupt ISR(void) // Interruptroutine { int_save_registers // W, STATUS (und PCLATH) retten if(RCIF) { usartbuff[usartind]=RCREG; usartind++; } ... und noch einiges anderes hier } Im Hauptprogramm: for(i=0; i<=80; i++) usartbuff[usartind]=0; // buff löschen usartind=0; // alles im rs232-lesepuffer befindliche verwerfen rs232_println("ATI"); // senden befehl an modem delay(10000); // testbetrieb: 10 sec warten in schleife auf modemantwort for(i=0; i<usartind; i++) lcd_dat(usartbuff[i]); // ausgeben des lesebuffers am LCD > tadellos es war tatsächlich irgendwie die zeitliche koppelung von LCD und rs232-interrupts.. Danke nochmals, liebe Grüße Rudi
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.