Communication I2C Entre 2 PIC
Communication I2C Entre 2 PIC
Communication I2C Entre 2 PIC
ca
Page 1/9
Avant tout pour la troisime version du robot aspirateur, ASAv3, et aussi pour mes futurs projets, j'ai besoin d'un bus pour communiquer entre plusieurs microcontrleurs. Mon choix s'est port sur le bus I2C pour sa grande flexibilit, sa relative facilit de mise en oeuvre et la possibilit de pouvoir ajouter des cartes sans influencer les autres. Je ne dtaillerai pas toutes les subtilites de la communication I2C dans cette article car d'autre l'ont dj fait. Je mets en lien quelques sites qui m'ont permis de bien comprendre, ainsi que certaines documentations de Microchip.
AN989 de Microchip
Donc, ce que vous trouverai dans cette article, c'est le code de base que j'ai cris, en me basant sur mes recherches et sur l'aide reue, en particulier celle de Thomas Cremel (T-Bot). Actuellement, le code ne sert qu' dmontrer la communication. La partie lectronique est trs simple. Pour mes tests, j'ai mont deux PIC 18F452 sur un petit breadboard. Chacun a un crystal de 10MHz avec ses condensateurs, un circuit de reset simplissime et deux leds : une rouge sur RA1 et une verte sur RA0. Les pins SDA de chaque PIC sont relies ensemble, ainsi que les SCL. Chaque ligne a une rsistance de pull-up de 4,7k (peut varier entre 1k et 100k, normalement).
Le code fonctionne tel que, cot Matre, si le module I2C reoit un ACK de l'esclave, preuve que les donnes sont rendues, la led verte est allume. En cas de Non-ACK, c'est la rouge qui s'allume. Pour l'esclave, c'est une led pour la lettre 'A' et une autre pour 'B', afin de dmontrer que le PIC ne reoit pas n'importe quoi, mais bien les caractres voulus. Avec le code ci-dessous, la led verte et la led rouge alternent. Maintenant, voici le code :
/////////////////////////////////////////////////////////////////////////////
#include <p18f452.h> //for ports declarations #include <delays.h> //for delay routines #include <i2c.h> //gestion de la communication I2C
Page 2/9
#define ledACK PORTAbits.RA0 #define TRIS_ledACK TRISAbits.TRISA0 #define ledNAK PORTAbits.RA1 #define TRIS_ledNAK TRISAbits.TRISA1
///////////////////////////////////////////////////////////////////////////// // // // Fonctions // // //
/////////////////////////////////////////////////////////////////////////////
//from T. Cremel unsigned char envoyer_i2c(unsigned char addr, unsigned char data) { IdleI2C(); StartI2C(); IdleI2C(); putcI2C(addr&0xFE); IdleI2C(); if ( SSPCON2bits.ACKSTAT ) { StopI2C(); return 0; } putcI2C(data); IdleI2C(); if ( SSPCON2bits.ACKSTAT ) { StopI2C(); return 0; } StopI2C(); return 1; } // bus device responded with NOT ACK // test received ack bit state // bus device responded with NOT ACK // test received ack bit state
/////////////////////////////////////////////////////////////////////////////
Page 3/9
ledACK = 0; ledNAK = 0;
while(1) { if(envoyer_i2c(0x40, letter1)) //Si l'esclave envoie un ack, on allume la led ACK ledACK = 1; else ledNAK = 1;
Delay10KTCYx(0); Delay10KTCYx(0);
ledACK = 0; ledNAK = 0;
if(envoyer_i2c(0x40, letter2)) //Si l'esclave envoie un ack, on allume la led ACK ledACK = 1; else ledNAK = 1;
Delay10KTCYx(0); Delay10KTCYx(0);
ledACK = 0; ledNAK = 0; } }
//config du PIC #pragma config OSC = HSPLL #pragma config PWRT = ON #pragma config WDT = OFF #pragma config BOR = ON #pragma config BORV = 42 #pragma config LVP = OFF
Page 4/9
/////////////////////////////////////////////////////////////////////////////
#include <p18f452.h> //for ports declarations #include <delays.h> //for delay routines #include <i2c.h> //gestion de la communication I2C
#define ledACK PORTAbits.RA0 #define TRIS_ledACK TRISAbits.TRISA0 #define ledNAK PORTAbits.RA1 #define TRIS_ledNAK TRISAbits.TRISA1
char x;
/////////////////////////////////////////////////////////////////////////////
ledACK = 0; ledNAK = 0;
SSPCON1bits.CKP = 1;
Page 5/9
if(DataRdyI2C()) { x = ReadI2C();
//config du PIC #pragma config OSC = HSPLL #pragma config PWRT = ON #pragma config WDT = OFF #pragma config BOR = ON #pragma config BORV = 42 #pragma config LVP = OFF
Page 6/9
///////////////////////////////////////////////////////////////////////////// ///Gestion des ordre reus par interruption plutt que par polling
#include <p18f452.h> //for ports declarations #include <delays.h> //for delay routines #include <i2c.h> //gestion de la communication I2C
#define ledACK PORTAbits.RA0 #define TRIS_ledACK TRISAbits.TRISA0 #define ledNAK PORTAbits.RA1 #define TRIS_ledNAK TRISAbits.TRISA1
volatile char x;
///////////////////////////////////////////////////////////////////////////// // // // Interruptions // // //
/////////////////////////////////////////////////////////////////////////////
void MyInterrupt(void);
#pragma code highVector=0x008 void atInterrupthigh(void) { _asm GOTO MyInterrupt _endasm } #pragma code // retour la zone de code
Page 7/9
if (PIR1bits.SSPIF) // c'est le MSSP qui a lev l'interruption { PIR1bits.SSPIF = 0; // on va rautoriser l'interruption x = ReadI2C();
/////////////////////////////////////////////////////////////////////////////
ledACK = 0; ledNAK = 0;
Page 8/9
SSPCON1bits.CKP = 1;
//config du PIC #pragma config OSC = HSPLL #pragma config PWRT = ON #pragma config WDT = OFF #pragma config BOR = ON #pragma config BORV = 42 #pragma config LVP = OFF
J'espre que ces bouts de code vous aideront dvelopper vos propres applications en I2C. Personnellement, c'est le manque de code d'example, de rfrence, qui m'a le plus manqu. Je prise qu'ils ne sont que des exemples, quoique parfaitement fonctionnels, d'une communication entre deux PIC. Maintenant que j'ai franchis ces tapes, je vais pouvoir faire voluer mon code par une gestion de plusieurs donnes envoyes, l'ajout d'autres esclave, la lecture et non seulement l'criture, la gestion par interruption plutt que par polling (ok, cod dans la v2.0), etc. Bon codage !
Maitre
Esclave
Esclave v2.0
Page 9/9