Jump to content



GSM Modem με σειριακή


profitis

Recommended Posts

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

  • Replies 65
  • Created
  • Last Reply

Jaco καλησπερα και πάλι!!!

Σορρυ για τον γενικο καταιγισμό ερωτήσεων αλλά πραγματικά τα ψάχνουμε όλα όσο περισσότερο μπορούμε και πραγματικα σε ορισμένα θέματα δεν έχουμε και τόσο μεγάλη εμπειρια...

τα at+winds μας έχουν βγάλει λιγάκι τη πίστη...με το at+wind=256 κλεινουν υποτίθεται αλλα κάποια at+winds συνεχίζουν και έρχονται...Επειδή το read των responses του modem κυριολεκτικα μα ςέχει βγάλει τη πίστη, γίνεται να αφήσουμε ΜΟΝΟ το +wind:4 κα ιτα άλλα +wind να απενεργοποιηθουν;

Link to comment
Share on other sites

Τα wind έχουν binary levels και είναι ουσιαστικά 2 bytes εκφρασμένα σε integer σε δεκαδική (DEC) μορφή, δηλαδή

Byte 1

b0: SIM inserted

b1: Call indication

b2: Ready to process AT commands but still in emergency mode

b4: Ready to process AT commands, initialized

b5: new called identifier has been created

b6: release call

b7: Network service available

b8: Network lost

Byte 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

Για άλλη μία φορα 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 :D :D

Jaco ότι και να πούμε ειναι λίγο για τη βοήθεια σου :)

Link to comment
Share on other sites

Από την στιγμή που στέλνεις το ΑΤΕ0 δεν χρειάζεται μετά να στείλεις ΑΤ, για να δεις αν δουλεύει το modem, γιατί το έχεις εξακριβώσει ήδη από το ΟΚ της ΑΤΕ0...

Στο ξαναλέω ότι διαφωνώ με το while(1) μέσα στην ρουτίνα του reception, είναι λάθος... μπορεί εύκολα να μην επιστρέψεις ποτέ και να κολλήσει για πάντα εκεί μέσα ο κώδικας... χρησιμοποίησε το interrupt...

Link to comment
Share on other sites

Ξέχασα να σου πω ότι όταν λέω αδειάζεις τον buffer σου, δεν χρειάζεται να γράψεις κάποιο \0 ή κάτι τέτοιο, το σωστό είναι απλά να μηδενίζει το Index και τίποτα άλλο...

πχ ένα σενάριο είναι να τρέχεις συνέχεια στην main σου μια function που να ελέγχει αν υπάρχει κάτι στον buffer, αυτό είναι απλό και το κάνεις απλά ως εξής

if (index) {
//parse buffer
}

ή επειδή είναι AT πρωτόκολλο και πάντα υπάρχει ένα \r\n και τουλάχιστον ένα OK

if (index>3) {
//parse buffer
}

Επομένως αν το index έχει πραγματική πληροφορία τότε την διαβάζεις και όταν διαβάσεις αυτό που πραγματικά θες, κάνεις disable τα interrupts, για να μην αυξάνεται το index, και το μηδενίζεις...

Τώρα εφόσον σου δουλεύει και δεν υπάρχει χρόνος άσ' το όπως είναι, αλλά μόλις τελειώσετε ξαναγράψτε τον κώδικα για δική σας άσκηση και εμπειρία, αλλά κάντε το πιο "σωστά"... αν θες μετά το πέρας των εργασιών, το συζητάμε καλύτερα και πιο διεξοδικά...

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Δημιουργία...

Important Information

Ο ιστότοπος theLab.gr χρησιμοποιεί cookies για να διασφαλίσει την καλύτερη εμπειρία σας κατά την περιήγηση. Μπορείτε να προσαρμόσετε τις ρυθμίσεις των cookies σας , διαφορετικά θα υποθέσουμε ότι είστε εντάξει για να συνεχίσετε.