Jaco Ιανουάριος 16, 2011 #61 Κοινοποίηση Ιανουάριος 16, 2011 To while(RI!=1) είναι blocking και σε ένα interrupt driven κώδικα μπορεί (ίσως) να είναι και επικίνδυνο να σου κολλήσει τον κώδικα... ο λόγος είναι ότι από την στιγμή που το rx σου έχει κάποιο σήμα, τότε αυτόματα θα καλεστεί η interrupt routine που έχεις δηλώσει, οπότε αυτό σημαίνει ότι σίγουρα το RI θα είναι 1, οπότε χρειάζεσαι το εξ'ηςvoid ISR_Rx() interrupt 4 using 1{ if(RI) { cBuffer[++index] = SBUF; //γεμίζεις τον buffer σου, αυξάνεις και το index RI = 0; //κάνεις reset το interrupt } }Υπόψη αυτό είναι ένα απλό παράδειγμα, δεν είναι κώδικας που είναι χρησιμοποιήσιμος, γιατί δεν γίνεται καθόλου έλεγχος για το index, ώστε να μην κάνει overflowμε αυτό, δεν μπλοκάρεις και τρως πολύ λίγο χρόνο μέσα στο interrupt... Πιο σωστό, θα ήταν εδώ να χρησιμοποιήσεις κάποιο κυκλικό buffer, όπως στο link που σου έδωσα πριν... αυτό το αφήνω σε σένα...Τον χειρισμό των δεδομένων σου τον κάνεις από έναν handler μέσα στην main σου...Με παρόμοιο τρόπο στέλνεις και τα δεδομένα σου...Ιδεατά δεν πρέπει να υπάρχει καμία printf ή scanf ή οτιδήποτε παρόμοιο μέσα στον κώδικά σου...Γενικά στους μC πρέπει να γράφεις, όπως θα έγραφες ένα λειτουργικό από το μηδέν, δηλαδή τα πάντα είναι interrupts, handlers, timers και flagged events... μόνο με αυτόν τον τρόπο μπορείς να έχεις full error recovery από οποιαδήποτε στραβή συνθήκη που μπορεί να συμβεί... μετά το πιο δύσκολο ίσως είναι αφού ανιχνεύσεις το σφάλμα και δεν έχεις κολλήσει σε αυτό, πως μπορείς να κάνεις recover... στην περίπτωση του gsm απλά κάνεις ένα ati να δεις ότι ζωντανό και μετά ξανα-κάνεις το initialization του modem, ανεξάρτητα από την κατάσταση που βρίσκεται... επίσης το πιο quick-n-dirty είναι να κάνεις "AT+CFUN=1" και να περιμένεις πάλι το +WIND: 4, οπότε να ξεκινήσεις πάλι από την αρχή το state σου... αυτό δεν είναι το καλύτερο και πιο σωστό, αλλά δεν είναι και λάθος και ίσως σε γλιτώσει από πολλά προβλήματα... Link to comment Share on other sites More sharing options...
profitis Ιανουάριος 19, 2011 Author #62 Κοινοποίηση Ιανουάριος 19, 2011 Jaco καλησπερα και πάλι!!!Σορρυ για τον γενικο καταιγισμό ερωτήσεων αλλά πραγματικά τα ψάχνουμε όλα όσο περισσότερο μπορούμε και πραγματικα σε ορισμένα θέματα δεν έχουμε και τόσο μεγάλη εμπειρια...τα at+winds μας έχουν βγάλει λιγάκι τη πίστη...με το at+wind=256 κλεινουν υποτίθεται αλλα κάποια at+winds συνεχίζουν και έρχονται...Επειδή το read των responses του modem κυριολεκτικα μα ςέχει βγάλει τη πίστη, γίνεται να αφήσουμε ΜΟΝΟ το +wind:4 κα ιτα άλλα +wind να απενεργοποιηθουν; Link to comment Share on other sites More sharing options...
Jaco Ιανουάριος 19, 2011 #63 Κοινοποίηση Ιανουάριος 19, 2011 Τα wind έχουν binary levels και είναι ουσιαστικά 2 bytes εκφρασμένα σε integer σε δεκαδική (DEC) μορφή, δηλαδήByte 1b0: SIM insertedb1: Call indicationb2: Ready to process AT commands but still in emergency modeb4: Ready to process AT commands, initializedb5: new called identifier has been createdb6: release callb7: Network service availableb8: Network lostByte 2, άσ' το δεν σου χρειάζεταιΤο byte 1 είναι ουσιαστικά αυτό [b7 b6 b5 b4 | b3 b2 b1 b0]με | χωρίζεται το MS nibble (Most significant) και το LS nibble (Less Significant)...Τώρα ανάλογα με τα indications που θες να επιτρέψεις κάνεις 1 το αντίστοιχο bit, οπότε το 255 = 1111 1111, οπότε τα αφήνεις όλα...Επομένως αν θες να παίρνεις μόνο indications για το +WIND: 4, τότε θα πρέπει b4=1, άρα 0000 1000 = 8, οπότε ΑΤ+WIND=8Όμως, αυτό δεν είναι σωστή πρακτική...!!! Έτσι χάνεις πολύ σημαντικά indications, όπως πχ το network loss, που σημαίνει ότι αν για κάποιο λόγο χάσεις το δίκτυο, τότε δεν θα το μάθεις ποτέ και θα νομίζει η συσκευή ότι έχει δίκτυο και θα σου επιστρέφει συνέχεια errors... Επίσης αν δεν έχει κουμπώσει καλά η sim ή κάποιος την αφαιρέσει, τότε δεν θα το μάθεις...Τέλος πάντως αποφασίστε εσείς τι θέλετε, αλλά το ελάχιστο δυνατό πρέπει να είναι το 1000 1000 = 210, η ακόμα καλύτερα 1100 1000 = 200... Link to comment Share on other sites More sharing options...
profitis Ιανουάριος 19, 2011 Author #64 Κοινοποίηση Ιανουάριος 19, 2011 Για άλλη μία φορα respect... Επειδή το θέμα του receive απο το modem το παλευουμε ποσες μερες και απλά δεν θέλει να παίξει (ή πιο σωστα δεν μπορουμε να βρουμε το λάθος που κάνουμε) Λοιπον, η υλοποίηση που προσπαθούμε ειναι σχετικά απλή, βασισμένη σ' όλα αυτά που έχεις γράψει παραπάνω. Ο interrupt handler απλά γεμίζει έναν buffer και αν έχουμε overflow . void ISR_Serial(void) interrupt 4 using 1{ char temp; if(RI0){ //receive mode RI0=0; temp=SBUF0; if(bufferIndex<READ_BUFFER_LENGTH_GSM_Modem) modemReceiveBuffer[bufferIndex++]=temp; else overflowFlag=1; }} το πρώτο πράγμα που κάνουμε όταν ξεκινάει το πρόγραμμα είναι να κάνουμε το initialize του gsm. Ψιλοκαταχρηστικά θεωρούμε ότι τα πρώτα +wind που θα πετάξει θα πάνε κυριολεκτικα στον αερά αφού το πρόγραμμα του mcu ξεκινάει και περιμένει πρώτα 10 sec. μετά κάνο Στην gsm_modem_init() ξεκινάμε την ακολουθία των βημάτων μας:ATE0 ώστε να μην έρχονται πίσω αυτά που δίνουμε εμείς, ΑΤ για ενα check του modem, σβήνουμε τα error codes για να απλοποιήσουμε τη ζωή μας και επίσης ενεργοποιούμε at+winds (αν και αυτό μας προκαλει τελικα περισσότερα προβλήματα γενικά). Η γενική δομή αυτου που κάνουμε: -αποστολή της εντολής στο modem -rxhandler() που περιμένει να δει στον incoming buffer μία απάντηση. Επειδή αρχικά είναι ενεργοποιημένο το echo back περιμένουμε να διαβάσουμε π.χ. το "ΑΤΕ0\n\r\nOK\r\n" που επιστρέφεται πίσω. Μολις το διαβάσουμε αυτο κάνουμε return τον κωδικο της απάντησης. Αν και μπακάλικο αυτη η υλοποίηση παίζει αλλα μεμονωμένα -αφού διαβάσαμε αυτο που περιμέναμε να διαβάσουμε ξανακάνουμε clearBuffer() -επόμενη εντολη Γενικά δεν προσφέρει κανα τρελο error recovery, όμως τουλαχιστον θεωρητικα θα ελέγχαμε πως ολα ειναι οπως τα θέλουμε int rxHandler(char* waitingAnswer){ while(1)//wait until answer comes from serial port { if(overflowFlag==1)//overflow case { clearBuffer(); overflowFlag=0; LED2=1; return 0;//answer code for overflow==0 } if((strcmp(waitingAnswer,modemReceiveBuffer)==0)) { clearBuffer(); return 1;//rx mode ends, everything ok,return with answerCode==1 } //if(bufferIndex>2){return 2;} }} το ΓΕΝΙΚΟ πρόβλημα μας είναι ότι ο buffer ΔΕΝ ΚΑΘΑΡΙΖΕΤΑΙ. με ότι και αν έχουμε δοκιμάσει. με ότι Έχουμε δηλώση των πίνακα char modemBufferReceive[READ_BUFFER_LENGTH_GSM_Modem] αλλα όπως και αν έχουμε προσπαθήσει να τον καθαρισουμε δεν καθαριζει. μένουν συνέχεια πίσω σκουπιδια. ειτε βαζουμε bit by bit '/0' είτε σε όλα κενό ειτε οτιδηποτε άλλο μένουν σκουπίδια μέσα στον buffer. Προφανώς ίσως η λύση με τον κυλικο buffer οπως μας ειχες πει ειναι η καλυτερη, ελα ομως που δεν υπηρχε ο χρονος... Προγραμματιστικά γιατί δεν καθαρίζεται ο buffer; τα κενά ή το \0 δεν θα επρεπε να καθαρίζει...; ΕDITED: solved προς το παρον!!!!!! :D Jaco ότι και να πούμε ειναι λίγο για τη βοήθεια σου Link to comment Share on other sites More sharing options...
Jaco Ιανουάριος 19, 2011 #65 Κοινοποίηση Ιανουάριος 19, 2011 Από την στιγμή που στέλνεις το ΑΤΕ0 δεν χρειάζεται μετά να στείλεις ΑΤ, για να δεις αν δουλεύει το modem, γιατί το έχεις εξακριβώσει ήδη από το ΟΚ της ΑΤΕ0...Στο ξαναλέω ότι διαφωνώ με το while(1) μέσα στην ρουτίνα του reception, είναι λάθος... μπορεί εύκολα να μην επιστρέψεις ποτέ και να κολλήσει για πάντα εκεί μέσα ο κώδικας... χρησιμοποίησε το interrupt... Link to comment Share on other sites More sharing options...
Jaco Ιανουάριος 20, 2011 #66 Κοινοποίηση Ιανουάριος 20, 2011 Ξέχασα να σου πω ότι όταν λέω αδειάζεις τον buffer σου, δεν χρειάζεται να γράψεις κάποιο \0 ή κάτι τέτοιο, το σωστό είναι απλά να μηδενίζει το Index και τίποτα άλλο...πχ ένα σενάριο είναι να τρέχεις συνέχεια στην main σου μια function που να ελέγχει αν υπάρχει κάτι στον buffer, αυτό είναι απλό και το κάνεις απλά ως εξήςif (index) { //parse buffer}ή επειδή είναι AT πρωτόκολλο και πάντα υπάρχει ένα \r\n και τουλάχιστον ένα OKif (index>3) { //parse buffer}Επομένως αν το index έχει πραγματική πληροφορία τότε την διαβάζεις και όταν διαβάσεις αυτό που πραγματικά θες, κάνεις disable τα interrupts, για να μην αυξάνεται το index, και το μηδενίζεις...Τώρα εφόσον σου δουλεύει και δεν υπάρχει χρόνος άσ' το όπως είναι, αλλά μόλις τελειώσετε ξαναγράψτε τον κώδικα για δική σας άσκηση και εμπειρία, αλλά κάντε το πιο "σωστά"... αν θες μετά το πέρας των εργασιών, το συζητάμε καλύτερα και πιο διεξοδικά... Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.