Club robotique de Sophia-Antipolis

Accueil > POBOTpedia > Communications > Communications filaires > Tutoriel complet sur I2C

Tutoriel complet sur I2C

dimanche 12 août 2012, par Julien H.

Nous utilisons le protocole de communication par bus série I2C depuis longtemps : beaucoup de micro-contrôleurs et même de microprocesseurs utilisent cette technologie.

Il était temps de faire un article complet, en se concentrant sur la détection du périphérique, la lecture et l’écriture par la liaison I2C plutôt que sur le composant en lui-même. Consultez les mots-clés en colonne de droite pour avoir accès à une liste d’articles traitant du sujet.

Pour qu’il soit complet, nous allons utiliser un maximum de contrôleurs et de langages différents :
- PIC
- AVR
- Arduino
- mBed
- Raspberry Pi
- un PC Linux

Il y a même une astuce pour utiliser le port écran (VGA, ...) comme adaptateur I2C.

 Le matériel

- une carte avec un contrôleur programmable (l’un de ceux cités dessus)
- les câbles et extensions pour les programmer
- un composant I2C
- les câbles pour relier la carte au composant

Plus précisément, nous allons d’abord utiliser un extenseur de port PCF8575 sur une carte de support simple "breakout" de Sparkfun. On utilisera également une mémoire EEPROM 24LC16B qui passait par là.

 Code Arduino

On branche SCL sur ANALOG 5 et SDA sur ANALOG 4.
Puis le Vcc sur 5 ou 3.3 volts et Gnd sur... Gnd.

Pour commencer, on va "scanner" le bus I2C avec un petit programme pour Arduino. Téléchargez l’archive ci-dessous

Zip - 799 octets
Sketch Arduino "scan I2C"

Envoyer le programme dans votre carte Arduino et ouvrez la console série. Le message suivant apparait :

Scanning...
I2C device found at address 0x20 !
done

Attention à l’adresse qui est en hexadécimal. Il faudra soit conserver l’écriture 0x dans votre code, soit faire la conversion en décimal. Ainsi 0x20 devient 32.

On peut maintenant écrire un code pour lire le composant I2C :


#include

<Wire.h>

// Test de l’I2C expander PCF8575 sur breakout Sparkfun

void setup()

Wire.begin() ;
Serial.begin(9600) ;

void loop()

Wire.requestFrom(32, 2) ;
while(Wire.available())

char c = Wire.read() ;
Serial.print(c & 0xFF, BIN) ; // astuce pour n’afficher que le premier octet, et en binaire pour voir quelle patte est activée ou pas
Serial.print(", ") ;

Serial.println() ;
delay(200) ;

Et voici ce qu’on obtient en touchant les 16 pattes de l’I2C extender :

11111111, 11111101,
11111111, 11111101,
11111111, 11111011,
11111111, 11111011,
11111111, 11110111,
11111111, 11110111,
11111111, 11111111,
11111111, 11111111,
11111111, 11111111,
11111111, 11111111,
1111111, 11111111,
10111111, 11111111,
11011111, 11111111,
11110111, 11111111,
11111101, 11111111,
11111111, 11111111,

 Commandes Linux / Raspberry Pi

Nous utilisons ici la distribution Occidentalis avec le support d’I2C.

Le montage est réalisé sur une plaque d’essai (breadboard) avec une mémoire EEPROM I2C de référence 24LC16B comportant 8 blocs de 2 ko. On conserve également l’extenseur de port. La Raspberry Pi est dans son boîtier PVC et on utilise notre connecteur rapide pour GPIO pour relier le bus I2C à la plaque Labdec.

JPEG - 306.9 ko

Il y a plusieurs bus I2C sur la RPi. Il faut utiliser le 0 pour accéder à celui qui est sur le connecteur GPIO, donc celui qui est accessible via des picots au pas standard de 2,54 mm. Note : il y a des Raspberry Pi (testée en décembre 2012) qui ont l’I2C du port GPIO sur le numéro 1.

pi@raspberrypi ~ $ sudo i2cdetect 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
I will probe address range 0x03-0x77.
Continue? [Y/n] Y
    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 51 52 53 54 55 56 57 -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --                        
pi@raspberrypi ~ $ sudo i2cget 0 0x20
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will read from device file /dev/i2c-0, chip address 0x20, current data
address, using read byte.
Continue? [Y/n] y
0xef

Notez la syntaxe : d’abord le numéro du bus (0) puis l’adresse en hexadécimal avec 0x devant.

Le retour 0xef indique qu’il y a une patte de l’extenseur à 0.

L’écriture est aussi simple. N’hésitez pas à nous contacter par mail pour obtenir plus d’explications et pour que l’on mette en ligne d’autres tests.

 Astuce pour PC Linux

La gestion de l’I2C sous Linux a déjà été en partie abordée avec la section précédente sur Raspberry Pi.

Comme les distributions standard pour PC ne sont pas dédiées à l’électronique, il faut installer les programmes de gestion de l’I2C :

atelier@ubuntu:~$ sudo apt-get install i2c-tools
atelier@ubuntu:~$ i2c<TAB>
i2cdetect  i2cdump    i2cget     i2cset  
atelier@ubuntu:~$ i2cdetect -l
atelier@ubuntu:~$

Rien n’est détecté ! Il faut insérer le module

atelier@ubuntu:~$ sudo modprobe i2c-dev
atelier@ubuntu:~$ lsmod
...
atelier@ubuntu:~$ i2cdetect -l
i2c-0        unknown           SMBus nForce2 adapter at 3040           N/A
i2c-1        unknown           SMBus nForce2 adapter at 3000           N/A
i2c-2        unknown           NVIDIA i2c adapter 0 at 2:00.0          N/A
i2c-3        unknown           NVIDIA i2c adapter 2 at 2:00.0          N/A
i2c-4        unknown           NVIDIA i2c adapter 3 at 2:00.0          N/A
atelier@ubuntu:~$

Oh oh, 5 bus I2C sur le portable de l’association. Pour le "SMBus", pas de surprise, il s’agit du bus de gestion des informations entre périphériques (system management). Mais pour les trois suivants, c’est intéressant.

Voyons ce qui est connecté :

atelier@ubuntu:~$ sudo i2cdetect -y 1
    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- 08 -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: 30 31 -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 51 -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- 61 -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: 70 -- -- -- -- -- -- --                        
atelier@ubuntu:~$

Pas mal, il faudra trouver ce que ça peut être. Pour lire tout le contenu d’un device, plutôt que de faire un i2cget à chacun des registres, on peut utiliser i2cdump. Remarquez le paramètre -y pour éviter de devoir confirmer qu’on veut faire une lecture

atelier@ubuntu:~$ sudo i2cdump -y 1 0x50
00: 80 08 08 0e 0a 61 40 00 05 30 45 00 82 08 00 00    ?????a@.?0E.??..
10: 0c 08 38 01 04 00 07 3d 50 50 60 3c 1e 3c 2d 01    ??8??.?=PP`<?<-?
20: 20 27 10 17 3c 1e 1e 00 06 3c 7f 80 18 22 00 00     '??<??.?<???"..
30: 00 03 00 00 00 00 00 00 00 00 00 00 00 00 12 1c    .?............??
40: ce 00 00 00 00 00 00 00 02 4d 34 20 37 30 54 35    ?.......?M4 70T5
50: 36 36 33 52 5a 33 2d 43 45 36 20 33 52 08 36 82    663RZ3-CE6 3R?6?
60: 76 24 ff 00 53 57 4c 31 33 30 33 00 00 00 00 00    v$..SWL1303.....
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
80: 00 62 43 33 73 20 35 55 fe e0 58 50 00 19 11 00    .bC3s 5U??XP.??.
90: 00 62 43 33 73 20 35 55 e0 20 00 00 01 40 06 00    .bC3s 5U? ..?@?.
a0: 00 62 43 65 36 00 35 55 fe e0 58 50 00 19 11 00    .bCe6.5U??XP.??.
b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
e0: 45 44 4d ff ff ff ff ff ff ff ff ff ff ff ff ff    EDM.............
f0: 01 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff    ?...............

Testons un autre bus :

atelier@ubuntu:~$ sudo i2cdump -y 3 0x50
No size specified (using byte-data access)
    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 ff ff ff ff ff ff 00 30 e4 c2 01 00 00 00 00    ........0???....
10: 00 12 01 03 80 22 13 78 0a e8 95 9b 56 48 96 26    .????"?x????VH?&
20: 1a 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01    ?PT...??????????
30: 01 01 01 01 01 01 3e 1c 56 a0 50 00 16 30 30 20    ??????>?V?P.?00
40: 35 00 58 c2 10 00 00 19 00 00 00 00 00 00 00 00    5.X??..?........
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 fe 00 4c    .............?.L
60: 47 20 44 69 73 70 6c 61 79 0a 20 20 00 00 00 fc    G Display?  ...?
70: 00 4c 50 31 35 36 57 48 31 2d 54 4c 41 33 00 de    .LP156WH1-TLA3.?
80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................

Oh oh... "LG display", "LP156WH1-TLA3" : ce sont des indications sur l’écran du portable.

La recherche des bus i2c 1 et 3 et surtout de l’adresse 0x50 (ou 80 en numérique) n’est pas anodine. Elle nous a été soufflée par Keuronde, notre ami de l’équipe Poivron qui rédige des articles très intéressants.

Mais si l’I2C permet de détecter un écran , est-il vrai que la sortie VGA du portable peut servir d’adaptateur I2C à peu de frais ? C’était un challenge, et nous sommes fiers de l’avoir démontré.

PNG - 497.4 ko

En regardant la prise femelle côté PC, les numéros se lisent de droite à gauche, de haut en bas. La patte 1 est donc en haut à droite et la patte 15 en bas à gauche.

Les signaux I2C sont sur la patte 12 (SDA) et la patte 15 (SCL).
La masse est sur la patte 5 et la tension d’alimentation 5 volts est sur la patte 9.

PNG - 10.3 ko

Et ça marche : voici la détection avant connection :

atelier@ubuntu:~$ sudo i2cdetect -y 2
    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --                        

Et une fois le composant I2C branché par 4 simples fils dans la prise bleu VGA :

atelier@ubuntu:~$ sudo i2cdetect -y 2
    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --                        

Allez, une lecture de l’I2C expander PCF8575 à la santé de Samuel :

atelier@ubuntu:~$ sudo i2cget -y 2 0x20 2
0xfe

Envoyez-nous les résultats de vos tests. Le portable est un Compaq avec une carte nVidia. Nous compléterons la liste des cartes graphiques qui ne marchent pas si vous nous prévenez..

Portfolio

Vos commentaires

  • Le 25 novembre 2013 à 10:23, par Tipouic En réponse à : Tutoriel complet sur I2C

    Bonjours,
    Je tiens à vous informer qu’on trouve aussi des ports I2C dans le HDMI et le DVI.
    Pour contre, il faut faire très attention car l’intensité délivré est très petite (100 ou 55ma).

    Sinon bon site bien détaillés. Bon courage pour la suite.
    A+

    PNG - 32 ko

    Répondre à ce message

Un message, un commentaire ?

modération a priori

Attention, votre message n’apparaîtra qu’après avoir été relu et approuvé.

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici
  • Ce formulaire accepte les raccourcis SPIP [->url] {{gras}} {italique} <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document