- Qu'est-ce que le protocole de communication I2C?
- Comment fonctionne I2C Communication?
- Où utiliser la communication I2C?
- I2C avec PIC16F877a utilisant le compilateur XC8
- Programmation à l'aide des fichiers d'en-tête I2C:
- Simulation Proteus:
Les microcontrôleurs PIC sont une plate-forme puissante fournie par micropuce pour les projets embarqués, sa nature polyvalente lui a permis de trouver des moyens dans de nombreuses applications et la phase est toujours en cours. Si vous avez suivi nos tutoriels PIC, vous auriez remarqué que nous avons déjà couvert un large éventail de tutoriels sur le microcontrôleur PIC à partir des bases. Depuis, nous avons couvert les bases, nous pouvons entrer dans des choses plus intéressantes comme le portail de communication.
Dans le vaste système d'applications embarquées, aucun microcontrôleur ne peut effectuer toutes les activités par lui-même. À un moment donné, il doit communiquer avec d'autres appareils pour partager des informations, il existe de nombreux types de protocoles de communication pour partager ces informations, mais les plus utilisés sont USART, IIC, SPI et CAN. Chaque protocole de communication a ses propres avantages et inconvénients. Concentrons-nous sur la partie IIC pour le moment puisque c'est ce que nous allons apprendre dans ce tutoriel.
Qu'est-ce que le protocole de communication I2C?
Le terme IIC signifie « Inter Integrated Circuits ». Il est normalement désigné comme I2C ou I au carré C ou même comme protocole d'interface à 2 fils (TWI) à certains endroits, mais cela signifie tous la même chose. I2C est un protocole de communication synchrone, ce qui signifie que les deux appareils qui partagent les informations doivent partager un signal d'horloge commun. Il n'a que deux fils pour partager les informations dont l'un est utilisé pour le signal du robinet et l'autre est utilisé pour l'envoi et la réception de données.
Comment fonctionne I2C Communication?
La communication I2C a été introduite pour la première fois par Phillips. Comme dit précédemment, il a deux fils, ces deux fils seront connectés entre deux appareils. Ici, un appareil est appelé maître et l'autre appareil est appelé esclave. La communication doit et se produira toujours entre deux un maître et un esclave. L'avantage de la communication I2C est que plus d'un esclave peut être connecté à un maître.
La communication complète s'effectue via ces deux fils à savoir, Serial Clock (SCL) et Serial Data (SDA).
Serial Clock (SCL): partage le signal d'horloge généré par le maître avec l'esclave
Serial Data (SDA): envoie les données depuis et vers le maître et l'esclave.
A tout moment, seul le maître pourra initier la communication. Puisqu'il y a plus d'un esclave dans le bus, le maître doit se référer à chaque esclave en utilisant une adresse différente. Lorsqu'elle est adressée, seule la pommade avec cette adresse particulière répondra avec les informations tandis que les autres continueront de quitter. De cette façon, nous pouvons utiliser le même bus pour communiquer avec plusieurs appareils.
Où utiliser la communication I2C?
La communication I2C est utilisée uniquement pour les communications à courte distance. Il est certainement fiable dans une certaine mesure car il a une impulsion d'horloge synchronisée pour le rendre intelligent. Ce protocole est principalement utilisé pour communiquer avec des capteurs ou d'autres appareils qui doivent envoyer des informations à un maître. C'est très pratique lorsqu'un microcontrôleur doit communiquer avec de nombreux autres modules esclaves en utilisant un minimum de fils uniquement. Si vous recherchez une communication longue portée, vous devriez essayer RS232 et si vous recherchez une communication plus fiable, vous devriez essayer le protocole SPI.
I2C avec PIC16F877a utilisant le compilateur XC8
Assez de présentations, allons-y et apprenons comment nous pouvons utiliser un microcontrôleur pour effectuer une communication I2C. Avant de commencer, il est clair que ce didacticiel ne parle que d' I2C dans PIC16F877a en utilisant le compilateur XC8, le processus sera le même pour les autres microcontrôleurs mais de légères modifications peuvent être nécessaires. Rappelez-vous également que pour les microcontrôleurs avancés tels que la série PIC18F, le compilateur lui-même peut avoir une bibliothèque intégrée pour utiliser les fonctionnalités I2C, mais pour PIC16F877A, rien de tel n'existe, alors construisons-en une par nous-mêmes. La bibliothèque expliquée ici sera donnée sous forme de fichier d'en-tête à télécharger en bas qui peut être utilisé pour PIC16F877A pour communiquer avec d'autres appareils I2C.
Comme toujours, le meilleur point de départ est notre fiche technique. Recherchez des détails sur I2C dans la fiche technique et vérifiez quels registres doivent être configurés. Je ne vais pas l'expliquer en détail puisque la fiche technique l'a déjà fait pour vous. Plus loin, je vais expliquer les différentes fonctions présentes dans le fichier d'en-tête et leur responsabilité dans le programme.
void I2C_Initialize ()
La fonction d'initialisation est utilisée pour indiquer au microcontrôleur que nous allons utiliser le protocole I2C. Cela peut être fait en définissant les bits requis sur le registre SSPCON et SSPCON2. La première étape serait de déclarer les broches IIC comme broches d'entrée, ici les broches RC3 et RC4 devraient être utilisées pour la communication I2C, nous les déclarons donc comme broches d'entrée. Ensuite, nous devons définir le SSPCON et le SSPCON2 qui est un registre de contrôle MSSP. Nous utilisons le PIC en mode maître IIC avec une fréquence d'horloge de FOSC / (4 * (SSPADD + 1)). Reportez-vous aux numéros de page de la fiche technique mentionnés dans les lignes de commentaires ci-dessous pour comprendre pourquoi ce registre particulier est défini de cette façon.
Ensuite, nous devons régler la fréquence d'horloge, la fréquence d'horloge pour différentes applications peut varier, par conséquent nous obtenons le choix de l'utilisateur via la variable feq_k et l'utilisons dans nos formules pour définir le registre SSPADD.
void I2C_Initialize (const unsigned long feq_K) // Commence IIC en tant que maître { TRISC3 = 1; TRISC4 = 1; // Définit les broches SDA et SCL comme broches d'entrée SSPCON = 0b00101000; // pg84 / 234 SSPCON2 = 0b00000000; // pg85 / 234 SSPADD = (_XTAL_FREQ / (4 * feq_K * 100)) - 1; // Réglage de la vitesse d'horloge pg99 / 234 SSPSTAT = 0b00000000; // pg83 / 234 }
Void I2C_Hold ()
La fonction suivante importante est la fonction I2C_hold qui est utilisée pour suspendre l'exécution de l'appareil jusqu'à ce que l'opération I2C en cours soit terminée. Il faudrait vérifier si les opérations I2C doivent être suspendues avant de commencer toute nouvelle opération. Cela peut être fait en vérifiant les registres SSPSTAT et SSPCON2. Le SSPSTAT contient les informations sur l'état du bus I2C.
Le programme peut sembler un peu compliqué car il implique un opérateur «et» et un opérateur «ou». Quand vous le cassez comme
SSPSTAT et 0b00000100 SSPCON2 et 0b00011111
Cela signifie que nous nous assurons que le 2 ème bit sur SSPSTAT est égal à zéro et que les bits de 0 à 4 sont également à zéro sur SSPCON2. Ensuite, nous combinons tous ces éléments pour vérifier que le résultat est nul. Si le résultat est zéro, le programme procédera sinon il y tenir jusqu'à ce qu'il soit zéro car il est utilisé dans un tout boucle.
void I2C_Hold () { while ((SSPCON2 & 0b00011111) - (SSPSTAT & 0b00000100)); // vérifiez le this sur les registres pour vous assurer que l'IIC n'est pas en cours }
Void I2C_Begin () et void I2C_End ()
Chaque fois que nous écrivons ou lisons des données en utilisant le bus I2C, nous devons commencer et terminer la connexion I2C. Pour commencer une communication I2C, nous devons définir le bit SEN et pour terminer la communication, nous devons définir le bit d'état PEN. Avant de basculer l'un de ces bits, nous devons également vérifier si le bus I2C est occupé en utilisant la fonction I2C_Hold comme décrit ci-dessus.
void I2C_Begin () { I2C_Hold (); // Maintenez le programme si I2C est occupé SEN = 1; // Début IIC pg85 / 234 } void I2C_End () { I2C_Hold (); // Maintenez le programme si I2C est occupé PEN = 1; // Fin IIC pg85 / 234 }
Vide I2C_Write ()
La fonction d'écriture est utilisée pour envoyer toutes les données du module maître au module salve. Cette fonction est normalement utilisée après une fonction I2C begin et est suivie d'une fonction I2C End. Les données qui doivent être écrites sur le bus IIC passent par les données variables. Ces données sont ensuite chargées dans le registre tampon SSPBUF pour les envoyer sur le bus I2C.
Normalement, avant d'écrire une donnée, une adresse sera écrite, vous devrez donc utiliser la fonction d'écriture deux fois, une fois pour définir l'adresse et l'autre pour envoyer les données réelles.
void I2C_Write (données non signées) { I2C_Hold (); // Maintenez le programme si I2C est occupé SSPBUF = data; // pg82 / 234 }
non signé court I2C_Read ()
La dernière fonction que nous devons connaître est la fonction I2C_Read . Cette fonction permet de lire les données actuellement sur le bus I2C. Il est utilisé après avoir demandé à un esclave d'écrire une valeur sur le bus. La valeur qui est reçue sera dans le SSPBUF, nous pouvons transférer cette valeur à n'importe quelle variable pour notre opération.
Lors d'une communication I2C, l'esclave après l'envoi des données demandées par le maître enverra un autre bit qui est le bit d'acquittement, ce bit doit également être vérifié par le maître pour s'assurer que la communication a réussi. Après avoir vérifié le bit ACKDT pour l'acquittement, il doit être activé en définissant le bit ACKEN.
unsigned short I2C_Read (unsigned short ack) { unsigned short entrant; I2C_Hold (); RCEN = 1; I2C_Hold (); entrant = SSPBUF; // récupère les données enregistrées dans SSPBUF I2C_Hold (); ACKDT = (accusé de réception)? 0: 1; // vérifie si le bit d' acquittement reçu ACKEN = 1; // pg 85/234 retour entrant; }
Voilà, ces fonctions devraient être suffisantes pour mettre en place une communication I2C et écrire ou lire des données à partir d'un appareil. Notez également qu'il existe de nombreuses autres fonctionnalités que la communication I2C peut effectuer, mais par souci de simplicité, nous ne les abordons pas ici. Vous pouvez toujours vous référer à la fiche technique pour connaître le fonctionnement complet du
Le code complet avec le fichier d'en-tête pour la communication PIC16F877A I2C peut être téléchargé à partir du lien.
Programmation à l'aide des fichiers d'en-tête I2C:
Maintenant que nous avons appris comment fonctionne une communication I2C et comment nous pouvons utiliser le fichier d'en-tête créé pour cela, faisons un programme simple dans lequel nous utiliserons le fichier d'en-tête et écrirons des valeurs sur les lignes I2C. Nous simulerons ensuite ce programme et vérifierons si ces valeurs sont écrites sur le bus.
Comme toujours, le programme commence par configurer les bits de configuration et régler la fréquence d'horloge à 20 MHz comme indiqué ci-dessous
#pragma config FOSC = HS // Bits de sélection de l'oscillateur (oscillateur HS) #pragma config WDTE = OFF // Bit d'activation de la minuterie de surveillance (WDT désactivé) #pragma config PWRTE = ON // Bit d'activation de la minuterie de mise sous tension (PWRT activé) # pragma config BOREN = ON // Bit d'activation de réinitialisation de Brown-out (BOR activé) #pragma config LVP = OFF // Bit d'activation de programmation série en circuit basse tension (alimentation simple) (RB3 est E / S numérique, HV activé MCLR doit être utilisé pour la programmation) #pragma config CPD = OFF // Data EEPROM Memory Code Protection Bit (Data EEPROM code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory peut être écrit par le contrôle EECON) #pragma config CP = OFF // Bit de protection de code de mémoire de programme flash (protection de code désactivée) #define _XTAL_FREQ 20000000
La prochaine étape serait d' ajouter le fichier d'en-tête dont nous venons de parler. Le fichier d'en-tête est nommé PIC16F877a_I2C.h et peut être téléchargé à partir du lien dont nous avons discuté ci-dessus. Assurez-vous que le fichier d'en-tête est ajouté dans le fichier d'en-tête de votre liste de projets, la structure de vos fichiers de projet doit ressembler à ceci
Après vous être assuré que le fichier d'en-tête est ajouté à votre fichier de projet, incluez le fichier d'en-tête dans le fichier C principal
#comprendre
A l' intérieur du tout boucle, nous commencerons la communication I2C écrire quelques valeurs aléatoires au bus I2C, puis mettre fin à la communication I2C. Les valeurs aléatoires que j'ai choisies sont D0, 88 et FF. Vous pouvez saisir toutes les valeurs souhaitées. Mais rappelez-vous ces valeurs car nous les vérifierons dans notre simulation.
tandis que (1) { I2C_Begin (); I2C_Write (0xD0); I2C_Write (0x88); I2C_Write (0xFF); I2C_End (); __delay_ms (1000); }
Le programme complet se trouve au bas de la page, vous pouvez l'utiliser ou télécharger le fichier zip complet du programme à partir d'ici. Après avoir obtenu le programme, compilez-le et préparez-vous pour la simulation.
Simulation Proteus:
Proteus a un bel instrument appelé débogueur I2C qui peut être utilisé pour lire les données sur un bus I2C, alors construisons un circuit en l'utilisant et vérifions si les données sont écrites avec succès. Le schéma de circuit complet est illustré ci-dessous
Chargez le fichier hexadécimal généré par notre programme en double-cliquant sur le microcontrôleur. Puis simulez le programme. Vous remarquerez une fenêtre pop-up qui affichera toutes les informations sur le bus I2C. La fenêtre de notre programme est illustrée ci-dessous.
Si vous regardez de près les données en cours d'écriture, vous remarquerez qu'elles sont les mêmes que celles que nous avons écrites dans notre programme. Les valeurs sont D0, 88 et FF. Les valeurs sont écrites toutes les 1 s de sorte que l'heure est également mise à jour comme indiqué ci-dessous. La flèche bleue indique qu'il est écrit du maître à l'esclave, il pointerait dans la direction opposée sinon. Un examen plus détaillé des données envoyées est illustré ci-dessous.
Ce n'est qu'un aperçu de ce que I2C peut faire, il peut également lire et écrire des données sur plusieurs appareils. Nous aborderons plus en détail I2C dans nos prochains tutoriels en interfaçant divers modules fonctionnant avec le protocole I2C.
J'espère que vous avez compris le projet et en avez appris quelque chose d'utile. Si vous avez des doutes, postez-les dans la section des commentaires ci-dessous ou utilisez les forums pour obtenir de l'aide technique.
Le code complet a été donné ci-dessous; vous pouvez télécharger des fichiers d'en-tête avec tout le code d'ici.