To πρωτόκολλο επικοινωνίας I2C

To IIC (Inter – Integrated Circuit) είναι ένας δίαυλος επικοινωνίας ο οποίος είναι ενσωματωμένος σε πολλές συσκευές, όπως σε διάφορους αισθητήρες, RTC (real time clock) και EEPROM. Το IIC αναφέρεται και ως I2C (I2C) σε πολλά τεχνικά κείμενα. Σ’ αυτό το άρθρο θα περιγράψουμε τους ακροδέκτες και τη δομή του Ι2C πρωτοκόλλου.

Το Ι2C πρωτόκολλο αναπτύχθηκε αρχικά από την εταιρεία Philips, αλλά όμως στις μέρες μας έχει γίνει ένα πλατιά διαδεδομένο πρωτόκολλο, υιοθετημένο από πολλές εταιρείες κατασκευής ολοκληρωμένων κυκλωμάτων. Το πρωτόκολλο Ι2C είναι ιδανικό για τη σύζευξη χαμηλής ταχύτητας περιφερειακών με την μητρική πλακέτα ή οπουδήποτε αλλού που χρειάζεται μία αξιόπιστη επικοινωνία μεταξύ συσκευών σε μικρές  αποστάσεις. Όπως θα δούμε σ’ αυτό το άρθρο το πρωτόκολλο Ι2C παρέχει κατευθυνόμενη επικοινωνία με επαλήθευση (acknowledge). Οι Ι2C συσκευές χρησιμοποιούν μόνο δύο ακροδέκτες για τη μεταφορά δεδομένων αντί για οκτώ ή περισσότερους όπως στον παλιό παραδοσιακό δίαυλο. Αυτές οι γραμμές ονομάζονται SCL (Serial Clock) που συγχρονίζει τη μεταφορά δεδομένων μεταξύ δύο τσιπς και SDA (Serial Data) για μεταφορά δεδομένων. Αυτός ο μειωμένος αριθμός γραμμών επικοινωνίας έχει σαν αποτέλεσμα το μικρότερο μέγεθος των τσιπς και στη μειωμένη κατανάλωση ρεύματος, κάνοντας το ιδανικό σε συσκευές με απαιτήσεις μικρότερης επιφάνειας. Αυτές οι δύο γραμμές SDA και SCL κάνουν το πρωτόκολλο Ι2C σαν ένα 2-wire interface. Σε κάποια τεχνικά κείμενα το πρωτόκολλο Ι2C αναφέρεται και σαν Two-wire Serial Interface (TWI).

Ηλεκτρικά χαρακτηριστικά των γραμμών του πρωτοκόλλου Ι2C

Οι Ι2C συσκευές χρησιμοποιούν μόνο 2 αμφίδρομους ανοικτού – απαγωγού ακροδέκτες για τη μεταφορά δεδομένων. Για την υλοποίηση του Ι2C μόνο μια pull – up αντίσταση 4,7ΚΩ χρειάζεται για κάθε γραμμή του διαύλου Ι2C. Αυτό υλοποιεί wired –AND το οποίο χρειάζεται για την υλοποίηση του Ι2C πρωτοκόλλου. Αυτό σημαίνει ότι αν μία ή περισσότερες συσκευές τραβούν την γραμμή σε επίπεδο low, η κατάσταση της γραμμής είναι το λογικό 0 ενώ η κατάσταση της γραμμής είναι το λογικό 1 αν καμία από τις συσκευές δεν τραβά τη γραμμή σε επίπεδο low.

Ι2C κόμβοι

Για τον μικροελεγκτή τύπου AVR, μέχρι 120 διαφορετικές συσκευές μπορούν να συνδεθούν στον δίαυλο Ι2C. Κάθε μια από αυτές τις συσκευές λέγεται κόμβος. Στην Ι2C ορολογία κάθε κόμβος μπορεί να λειτουργήσει είτε σαν αφέντης είτε σαν σκλάβος. Αφέντης είναι η συσκευή που παράγει τους παλμούς του ρολογιού για το σύστημα καθώς επίσης αρχικοποιεί και τερματίζει την επικοινωνία. Σκλάβος είναι ο κόμβος που λαμβάνει τους παλμούς του ρολογιού και επιλέγεται από τον αφέντη.

Στο πρωτόκολλο Ι2C και οι δύο αφέντης και σκλάβος μπορούν να λαμβάνουν και να στέλνουν δεδομένα. Έτσι υπάρχουν τέσσερις καταστάσεις επικοινωνίας. Αυτές είναι αφέντης εκπομπός, αφέντης λήπτης, σκλάβος εκπομπός, και σκλάβος λήπτης. Σημείωση: κάθε κόμβος μπορεί να έχει περισσότερες από μία καταστάσεις λειτουργίας σε διαφορετικές χρονικές στιγμές, αλλά έχει μία συγκεκριμένη κατάσταση λειτουργίας σε μία χρονική στιγμή.

Παράδειγμα
Δώσε ένα παράδειγμα για να δείξεις πως μια μια συσκευή (node) μπορεί να έχει περισσότερες από μία καταστάσεις λειτουργίας

Λύση
Εάν συνδέσεις ένα μικροελεγκτή AVR  με μία μνήμη ΕΕPROM διαμέσου του πρωτοκόλλου Ι2C ο AVR είναι σε κατάσταση αφέντη σε λειτουργία εκπομπού όταν γράφει δεδομένα στην ΕΕPROM. Ο AVR μπαίνει σε κατάσταση αφέντη σε λειτουργία λήπτη καθώς διαβάζει από την ΕΕPROM.

&

Μορφολογία Bit

To πρωτόκολλο Ι2C είναι ένα σύγχρονο σειριακό πρωτόκολλο που κάθε bit δεδομένων μεταφέρεται με τη γραμμή SDA και συγχρονίζεται με τη μετάβαση high – to – low του παλμού ρολογιού στη γραμμή SCL. Σύμφωνα με το Ι2C πρωτόκολλο τα δεδομένα στη γραμμή SDA δεν πρέπει να αλλάζουν καθώς η γραμμή ρολογιού είναι σε κατάσταση high και μπορούν να αλλάζουν όταν η γραμμή ρολογιού SCL είναι σε κατάσταση low. Οι συνθήκες STOP και START είναι οι μόνες εξαιρέσεις αυτού του κανόνα.

START και STOP συνθήκες

Όπως αναφέρθηκε προηγουμένως το Ι2C είναι ένα κατευθυνόμενο πρωτόκολλο επικοινωνίας. Αυτό σημαίνει ότι κάθε μετάδοση αρχίζει με τη συνθήκη START και τερματίζει με τη συνθήκη STOP.

Οι συνθήκες STOP και START πρέπει να διαχωρίζονται από τα bits διευθύνσεων ή δεδομένων. Γι΄ αυτό το λόγο δεν υπακούουν στον κανόνα που αναφέραμε πριν.

Οι συνθήκες START και STOP παράγονται κρατώντας το επίπεδο της γραμμής ρολογιού SCL σε κατάσταση high  και μετά γίνεται η αλλαγή στο επίπεδο της γραμμής δεδομένων SDA. H συνθήκη START παράγεται από τη μετάβαση high – to – low της γραμμής δεδομένων SDA όταν η γραμμή ρολογιού SCL είναι high. Η συνθήκη STOP παράγεται με τη μετάβαση low – to –high της γραμμής δεδομένων SDA καθώς η γραμμή ρολογιού SCL είναι high.

Ο δίαυλος θεωρείται απασχολημένος μεταξύ των ζευγαριών συνθηκών START και STOP και κανένας άλλος αφέντης δεν μπορεί να πάρει τον έλεγχο του διαύλου. Εάν ο αφέντης ο οποίος έχει τον έλεγχο του διαύλου θέλει να αρχίζει νέα μετάδοση και δεν θέλει να απελευθερώσει το δίαυλο πριν αρχίσει τη νέα μετάδοση δεδομένων, μπορεί να δημιουργήσει μια νέα συνθήκη START μεταξύ του ζευγαριού συνθηκών START και STOP. Αυτή η συνθήκη ονομάζεται REPEATED START.

Διαμόρφωση πακέτων στο Ι2C

Στο πρωτόκολλο Ι2C κάθε διεύθυνση ή δεδομένα πρέπει να σχηματίζουν πακέτα. Κάθε πακέτο έχει μέγεθος 9 bits. Tα πρώτα 8 bits τοποθετούνται στη γραμμή SDA από τον εκπομπό (αφέντη ή σκλάβο) και το ένατο bit είναι το bit επιβεβαίωσης ACK (aknowledge) από τον δέκτη (σκλάβο ή αφέντη) ή μπορεί να είναι NACK (not acknowledge). Oι παλμοί του ρολογιού παράγονται από τον αφέντη ανεξάρτητα αν είναι εκπομπός ή λήπτης. Για να πάρουμε το bit επιβεβαίωσης, ο εκπομπός απελευθερώνει τη γραμμή δεδομένων SDA κατά τη διάρκεια του ένατου παλμού ρολογιού έτσι ώστε ο λήπτης να μπορεί να τραβήξει τη γραμμή SDA σε κατάσταση low για την παραγωγή του bit επιβεβαίωσης ACK. Εάν ο λήπτης δεν τραβήξει τη γραμμή SDA σε κατάσταση low τότε θεωρείται NACK.

Στο πρωτόκολλο Ι2C κάθε πακέτο μπορεί να περιέχει είτε διεύθυνση είτε δεδομένα. Ας σημειώσουμε ότι START συνθήκη + πακέτο διεύθυνσης + ένα ή περισσότερα πακέτα δεδομένων + STOP συνθήκη αποτελούν μαζί μια πλήρη μετάδοση δεδομένων. Στη συνέχεια θα δούμε τη διαμόρφωση πακέτων διεύθυνσης και δεδομένων και πως συνδυάζονται μαζί για μια πλήρη επικοινωνία.

Διαμόρφωση πακέτων διευθύνσεων

Όπως όλα τα άλλα πακέτα, όλα τα πακέτα διευθύνσεων που μεταδίδονται στο δίαυλο Ι2C έχουν μέγεθος  εννέα bits. Ένα πακέτο διεύθυνσης αποτελείται από επτά bits της διεύθυνσης της Ι2C συσκευής που θέλουμε να επικοινωνήσουμε, ένα bit ελέγχου READ /WRITE και ένα Bit επαλήθευσης (acknowledge).

Τα bit διεύθυνσης χρησιμοποιούνται για να ενεργοποιήσουμε μια συγκεκριμένη συσκευή σκλάβου πάνω στο δίαυλο. Τα 7 bit της διεύθυνσης επιτρέπουν στον αφέντη να ενεργοποιήσει ένα μέγιστο αριθμό 128 σκλάβων συσκευών που μπορούν να συνδεθούν στον δίαυλο. Η διεύθυνση 0000 000 είναι δεσμευμένη για τη γενική ενεργοποίηση όλων των σκλάβων συσκευών καθώς επίσης όλες οι διευθύνσεις 1111xxx είναι δεσμευμένες. Αυτό σημαίνει ότι 119 (128-1-8) συσκευές μπορούν να συνδεθούν στο Ι2C δίαυλο. Στο πρωτόκολλο Ι2C το MSB της διεύθυνσης μεταδίδεται πρώτο.

Το όγδοο bit του πακέτου είναι το bit ελέγχου READ /WRITE. Εάν αυτό το bit είναι το λογικό 1 ο αφέντης θα διαβάσει το επόμενο πλαίσιο δεδομένων από τον σκλάβο, αλλιώς ο αφέντης θα γράψει το επόμενο πλαίσιο δεδομένων στον σκλάβο. Εάν ένας σκλάβος ανιχνεύσει την διεύθυνση του πάνω στο δίαυλο γνωρίζει ότι αυτός ενεργοποιείται και θα πρέπει  να επαληθεύσει με τον ένατο παλμό ρολογιού SCL (ACK) τραβώντας τη γραμμή SDA σε κατάσταση low. Εάν ο σκλάβος που επιλέγεται δεν είναι έτοιμος ή για οποιοδήποτε λόγο δεν θέλει να ανταποκριθεί στον αφέντη, θα πρέπει να αφήσει τη γραμμή SDA σε κατάσταση high στον ένατο παλμό ρολογιού. Αυτό ορίζεται να λέγεται NACK. Στην περίπτωση NACK ο αφέντης μεταδίδει την STOP συνθήκη για να τερματίσει τη μετάδοση ή μια REPEATED START  συνθήκη για να αρχίσει μια καινούργια μετάδοση.

Παράδειγμα
Δείξτε πως ο αφέντης λέει πως θέλει να γράψει στον σκλάβο με διεύθυνση 1001 101

Λύση
Οι επόμενες ενέργειες εκτελούνται από τον αφέντη

Α] ο αφέντης δημιουργεί ένα high – to – low  παλμό στη γραμμή δεδομένων SDA ενώ η γραμμή ρολογιού SCL είναι σε κατάσταση high για να δημιουργήσει μια start συνθήκη και να αρχίσει την επικοινωνία.
Β] ο αφέντης μεταδίδει 10011010 στο δίαυλο. Τα πρώτα επτά bits (1001101) ορίζουν την διεύθυνση του σκλάβου, ενώ το όγδοο bit (0) ορίζει μια Write λειτουργία και λέει ότι ο master θα γράψει το επόμενο byte δεδομένων στον σκλάβο.

&

Ένα πακέτο διεύθυνσης αποτελείται από τη διεύθυνση του σκλάβου και μια λειτουργία READ ονομάζεται SLA + R  ενώ ένα πακέτο διεύθυνσης που αποτελείται από μια διεύθυνση σκλάβου και μια λειτουργία WRITE ονομάζεται SLA + W.

Όπως αναφέραμε προηγουμένως μια διεύθυνση 0000 000 είναι δεσμευμένη και χρησιμοποιείται για γενική ενεργοποίηση των σκλάβων συσκευών. Αυτό σημαίνει όταν ο αφέντης μεταδώσει τη διεύθυνση 0000 000 όλοι οι σκλάβοι ανταποκρίνονται τραβώντας τη γραμμή SDA  στο μηδέν και περιμένουν να λάβουν το byte δεδομένων. Αυτό είναι χρήσιμο όταν ο αφέντης θέλει να μεταδώσει τα ίδια δεδομένα προς όλους τους σκλάβους του συστήματος. Ας σημειώσουμε ότι η γενική ενεργοποίηση των σκλάβων δεν μπορεί να χρησιμοποιηθεί για λειτουργία READ από τους σκλάβους διότι περισσότεροι του ενός σκλάβοι δεν μπορούν να γράψουν ταυτόχρονα στο δίαυλο.

Διαμόρφωση πακέτων δεδομένων

Όπως και τα άλλα πακέτα, τα πακέτα δεδομένων έχουν μέγεθος 9 bits. Τα πρώτα 8 bits είναι ένα byte δεδομένων που πρόκειται να μεταδοθούν και το ένατο bit είναι το ΑCK. Εάν ο λήπτης έχει λάβει και το τελευταίο byte δεδομένων και δεν υπάρχουν άλλα δεδομένα ή ο λήπτης δεν μπορεί να λάβει ή επεξεργαστεί περισσότερα δεδομένα ορίζει το σήμα NACK αφήνοντας τη γραμμή SDA σε κατάσταση high. Όπως στα πακέτα διευθύνσεων, στα πακέτα δεδομένων το MSB μεταδίδεται πρώτο.

Συνδυάζοντας πακέτα διευθύνσεων και δεδομένων σε μία μετάδοση.

Στο πρωτόκολλο Ι2C μία μετάδοση αρχίζει με την START  συνθήκη ακολουθούμενη από το πακέτο διεύθυνσης (SLA + R/W), ένα ή περισσότερα πακέτα δεδομένων και τερματίζεται από μία STOP συνθήκη. H ακόλουθη εικόνα δείχνει μία τυπική μετάδοση δεδομένων.

Παράδειγμα
Δείξε πως ο αφέντης γράφει την τιμή 11110000 στον σκλάβο με διεύθυνση 1001101

Λύση
Ο αφέντης εκτελεί τις ακόλουθες λειτουργίες:

1] Ο αφέντης ορίζει τον παλμό high – to – low στη γραμμή δεδομένων SDA ενώ η γραμμή ρολογιού SCL είναι σε κατάσταση high για να δημιουργήσει τη START συνθήκη και να αρχίσει την επικοινωνία
2] Ο αφέντης μεταδίδει 10011010 στο δίαυλο. Τα πρώτα επτά bits (1001101) ορίζουν την διεύθυνση του σκλάβου και το όγδοο bit (0) ορίζει λειτουργία εγγραφής από τον αφέντη για να στείλει το επόμενο byte στον σκλάβο για εγγραφή.
3] Ο σκλάβος τραβά τη γραμμή SDA σε κατάσταση low για να δημιουργήσει ACK για να δείξει ότι είναι έτοιμος να λάβει το byte δεδομένων
4] Μετά που ο αφέντης λάβει το ACK θα μεταδώσει το byte δεδομένων 1111000 πάνω στη γραμμή SDA (Το MSB πρώτο)
5] Όταν ο σκλάβος λάβει τα δεδομένα απελευθερώνει τη γραμμή SDA σε κατάσταση high για να μεταδώσει NACK. Αυτό πληροφορεί τον αφέντη ότι ο σκλάβος έλαβε το τελευταίο byte δεδομένων και δεν θα λάβει άλλα δεδομένα.
6] Μετά που ο αφέντης λάβει NACK γνωρίζει ότι δεν θα μεταδώσει άλλα δεδομένα. Ο αφέντης αλλάζει την γραμμή SDA από low –to – high όταν η γραμμή SCL είναι σε κατάσταση high για να μεταδώσει μία συνθήκη  STOP και μετά απελευθερώνει το δίαυλο.

&

Τέντωμα ρολογιού

Μία δυνατότητα του πρωτοκόλλου Ι2C είναι το τέντωμα (stretching) του ρολογιού. Είναι ένα είδος ελέγχου ροής δεδομένων. Εάν ένας επιλεγμένος σκλάβος δεν είναι έτοιμος να επεξεργαστεί περισσότερα δεδομένα μπορεί να τεντώσει το ρολόι τραβώντας τη γραμμή ρολογιού SCL σε κατάσταση low μετά που λάβει (ή στείλει) ένα bit δεδομένων. Επομένως ο αφέντης δεν είναι ικανός να υψώσει σε κατάσταση high τη γραμμή ρολογιού SCL (διότι η σύνδεση  των συσκευών είναι (wire – AND)) και θα περιμένει μέχρι ο σκλάβος απελευθερώσει τη γραμμή ρολογιού SCL για να δείξει ότι είναι έτοιμος για τη μεταφορά του επόμενου bit.