Table des matières:

Bus I2C pour ATtiny et ATmega : 8 étapes
Bus I2C pour ATtiny et ATmega : 8 étapes

Vidéo: Bus I2C pour ATtiny et ATmega : 8 étapes

Vidéo: Bus I2C pour ATtiny et ATmega : 8 étapes
Vidéo: AVR TWI (I2C) par interruption 2024, Juillet
Anonim
Bus I2C pour ATtiny et ATmega
Bus I2C pour ATtiny et ATmega

J'adore les microcontrôleurs Atmel AVR ! Depuis la construction du système de développement du ghetto décrit dans ce Instructable, je n'ai pas fini de m'amuser à expérimenter avec l'AVR ATtiny2313 et l'ATmega168 en particulier. Je suis même allé jusqu'à écrire un Instructable sur l'utilisation des commutateurs comme entrées et j'ai étendu le concept du système de développement du ghetto aux CPLD. Au cours d'un projet récent, j'avais besoin de plusieurs commutateurs pour définir les valeurs de contrôle. Les AVR n'avaient pas assez de broches d'E/S, j'ai donc dû penser à quelque chose. J'aurais pu essayer un système d'entrée complexe avec un clavier et un écran, mais l'ATtiny2313 aurait manqué de ressources. Heureusement, Atmel a fourni un moyen de contourner ce problème en incluant une interface qui peut se lier à des puces supplémentaires (telles que la mémoire ou les ports d'E/S) avec une simple interface à deux fils. C'est vrai, en utilisant seulement deux broches d'E/S sur un AVR, nous pouvons accéder à de nombreuses broches d'E/S supplémentaires, ainsi qu'à d'autres ressources. Cette interface à deux fils est officiellement connue sous le nom de bus de circuit inter-intégré, ou simplement de bus I2C et a été inventée par NXP alors qu'il s'agissait encore de Philips Semiconductors. Si vous lisez cet Instructable, vous avez probablement entendu parler du bus I2C et l'avez peut-être même utilisé sur un PIC ou un autre microcontrôleur. Bien que conceptuellement très simples et pris en charge par les ressources matérielles des AVR, les pilotes logiciels sont toujours nécessaires pour utiliser le bus I2C. Atmel fournit des notes d'application (voir les ressources plus loin dans ce Instructable), mais celles-ci sont incomplètes et ne montrent aucun exemple au-delà de la communication avec un autre appareil AVR. Ce n'est pas le but de ce Instructable d'enseigner à quiconque comment créer des pilotes I2C pour le AVR. Au lieu de cela, je fournirai des versions étendues des pilotes Atmel pour les périphériques ATtiny2313 et ATmega168, j'expliquerai les exigences et les restrictions qui s'appliquent lors de leur utilisation, et je vous montrerai des exemples fonctionnels de périphériques I2C. Après avoir travaillé sur ce Instructable, vous pourrez utiliser le bus I2C avec succès dans vos projets AVR. Évidemment, vous pouvez ignorer les pilotes pour tiny ou MEGA si vous n'êtes intéressé que par l'un d'entre eux. Pour ceux qui souhaitent en savoir plus sur le bus I2C, je fournirai des liens vers du matériel approprié.

Étape 1: Qu'est-ce que c'est que tout ce truc I2C de toute façon ?

Qu'est-ce que c'est que tout ce truc I2C de toute façon?
Qu'est-ce que c'est que tout ce truc I2C de toute façon?
C'est quoi tous ces trucs I2C de toute façon ?
C'est quoi tous ces trucs I2C de toute façon ?
Qu'est-ce que c'est que tout ce truc I2C de toute façon?
Qu'est-ce que c'est que tout ce truc I2C de toute façon?
C'est quoi tous ces trucs I2C de toute façon ?
C'est quoi tous ces trucs I2C de toute façon ?

Le bus I2C est une simple connexion à deux fils qui peut relier plusieurs appareils ensemble et leur permettre d'échanger des données. Dans sa forme la plus simple, il existe un appareil maître qui communique avec plusieurs appareils esclaves. Tous les appareils sont connectés en parallèle aux deux fils du bus I2C. Les deux fils sont appelés SCL et SDA. SCL est la ligne d'horloge et est contrôlé par le dispositif maître. SDA est la ligne de données bidirectionnelle. Pour transférer des données, le maître envoie une adresse d'esclave associée à un indicateur de lecture/écriture d'un bit. Si une écriture est souhaitée, le maître continuera à envoyer des données à l'esclave adressé. Si une lecture est demandée, l'esclave répondra avec des données. Pour coordonner les transactions, les lignes SCL et SDA sont manipulées par le maître et l'esclave pour signaler plusieurs conditions. Ceux-ci incluent START, STOP, ACK (accusé de réception) et NAK (aucun accusé de réception). Les détails de ces conditions sont traités par les chauffeurs. Les vrais geeks parmi vous peuvent apprendre tous les détails dans les liens fournis à la fin de ce Instructable. Les exigences électriques sont assez simples. Le maître et les esclaves doivent utiliser le même niveau pour Vcc, les masses doivent être connectées et les lignes SCL et SDA doivent être remontées à Vcc. La valeur des résistances de rappel est déterminée avec précision par un calcul basé sur la capacité totale sur le bus, mais peut pratiquement être à peu près n'importe quelle valeur entre 1,8K et 10K. Je commence avec 5.1K et utilise des valeurs inférieures jusqu'à ce que cela fonctionne. Ce n'est généralement pas un problème, sauf si vous avez beaucoup d'appareils ou de longues longueurs de fil entre les appareils. Le débit de données nominal sur le bus I2C est de 100 Kbits/seconde. Des taux de 400Kbits/seconde, 1Mbits/seconde et au-delà sont également possibles, mais ne sont pas pris en charge par les pilotes de ce Instructable. Tous les appareils I2C fonctionneront à 100 Kbits/seconde. L'ATtiny2313 et l'ATmega168 implémentent chacun le bus I2C différemment. ATtiny2313 utilise le matériel d'interface série universelle (USI) - qui peut également être utilisé pour le bus SPI. ATmega168 dispose d'un matériel dédié pour le bus I2C connu sous le nom d'interface à deux fils (TWI). Une fois les pilotes écrits, ces différences sont pour la plupart transparentes pour l'utilisateur. Une différence significative réside dans le logiciel: le pilote ATmega168 I2C est piloté par interruption alors que celui de l'ATtiny2313 ne l'est pas. Cela signifie qu'un programme ATmega168 n'a pas à attendre que les transferts de données I2C aient lieu, mais seulement à attendre avant de lancer un autre transfert, ou jusqu'à ce que les données arrivent d'une opération de lecture. Les exemples et la discussion à suivre devraient clarifier cela. Les adresses I2C ont une longueur de 7 bits, donc jusqu'à 127 périphériques peuvent être sur le bus si chacun a une adresse unique. Comme le montre la figure, cette adresse de 7 bits est décalée d'un bit vers la gauche et le bit le moins significatif est utilisé pour signaler une lecture ou une écriture de l'appareil à l'adresse. Ainsi, l'adresse complète de l'esclave est un octet de 8 bits. L'adresse réelle est partiellement déterminée en interne à l'appareil et ne peut pas être modifiée (4 bits les plus significatifs), et partiellement déterminée par les bits qui peuvent être connectés aux broches de l'appareil (3 bits les moins significatifs) qui peuvent être liés haut ou bas pour définir une adresse précise. Cela semble déroutant, mais un exemple le montrera clairement. La fiche technique du PCA8574A montre que les quatre bits les plus significatifs de l'adresse I2C seront toujours 0111. Les trois bits suivants sont déterminés par les paramètres des broches AD0, AD1 et AD2. Ces broches peuvent être reliées à la terre ou à l'alimentation en tension positive (5 volts) pour représenter respectivement 0 ou 1. La plage d'adresses possibles est donc de 38 à 3F hexadécimal, comme le montre l'autre figure de la fiche technique PCA8574. Ainsi, en modifiant les paramètres des bits d'adresse, jusqu'à 8 PCA8574A peuvent être sur le bus I2C en même temps. Chacun répondra uniquement à son adresse d'esclave spécifique. Si encore plus de ports E/S sont nécessaires, le PCA8574 peut être utilisé. La seule différence entre le PCA8574 et le PCA8574A est que la plage d'adresses esclave I2C du PCA8574 est de 20 à 27 hexadécimal. adresse. Lisez attentivement la fiche technique et gardez à l'esprit que l'adresse de l'esclave aura une longueur de 7 bits. Le bit de lecture/écriture doit être traité séparément. Encore une fois, un exemple vous aidera. La fiche technique de l'EEPROM 24C16 avec laquelle nous allons expérimenter indique que les quatre premiers bits (les plus significatifs) de l'adresse de l'esclave sont 1010. Les trois bits suivants peuvent être déterminés par A0, A1 et A2; mais notez que la fiche technique couvre également les 24C01 à 24C08, qui sont des EEPROM de plus petite taille. La figure de la fiche technique montre que les paramètres de ces bits d'adresse sont ignorés lorsque la taille augmente et sont complètement ignorés pour le 24C16. C'est-à-dire que les trois derniers bits n'ont pas d'importance et que le 24C16 utilise vraiment toutes les adresses d'esclave I2C 50 à 57 hexadécimales. La plage d'adresses d'esclaves s'adressera en fait à différentes sections du 24C16. Les 256 premiers octets sont à l'adresse 50h, les 256 suivants à 51h, et ainsi de suite jusqu'aux 256 derniers à 57h - pour un total de 2K octets. Étant donné que l'adresse de la RAM du PCF8570 que nous expérimentons également se situe dans cette plage, le 24C16 et le PCF8570 ne peuvent pas être utilisés ensemble.

Étape 2: Commandez des appareils I2C

Maintenant que vous en savez un peu plus sur le bus I2C et que vous souhaitez l'utiliser, pourquoi ne pas commander des appareils I2C à expérimenter maintenant afin qu'ils puissent être en route vers vous pendant que vous préparez le logiciel ? Les appareils appropriés incluent un I/ O Interface Expander (mon préféré), une RAM statique et une EEPROM. Il y a beaucoup plus, mais c'est un bon début. Les processeurs AVR que nous utiliserons sont l'ATtiny2313 et l'Atmega168 (utilisé dans Arduino). Si vous êtes nouveau dans ce domaine, jetez un œil à ce grand Instructable pour en savoir plus à leur sujet et construire votre système de développement de ghetto. Le schéma de l'ATmega168 dans le présent Instructable montre comment mettre en œuvre le système de développement Ghetto pour ce processeur. Le câble du port parallèle est le même que celui de l'ATtiny2313. (Je n'ai pas essayé la version USB du système de développement Ghetto, donc je ne sais pas comment le bus I2C est accessible dessus. Idem pour l'Arduino.) Voici les numéros de référence Digikey. Extenseur de port: IC I2C I/O EXPANDER 568-4236-5-NDRam:IC SRAM 256X8 W/I2C 568-1071-5-NDEEPROM:IC EEPROM SERIE 16K CAT24C16LI-G-ND

Étape 3: Pilotes I2C

Voici les descriptions des fonctions du pilote pour le bus I2C. Ceux-ci ont été développés à l'aide des notes d'applications Atmel pour les débutants. Je n'aurais pas pu faire cela sans eux comme base sur laquelle construire. Le développement a été fait à l'aide de WinAVR et du compilateur gcc C. Les restrictions de fréquence d'horloge sont décrites ci-dessous pour chaque processeur. Étant donné que je ne suis pas en mesure de tester toutes les combinaisons de saveur de processeur / fréquence d'horloge possibles, je vais simplement m'en tenir à ce que je peux réellement tester et essayer d'indiquer les restrictions et les limitations. Voici les fonctions du pilote et comment les utiliser. Veuillez regarder les exemples pour plus de détails et pour voir les fonctions utilisées dans les programmes complets. Si vous souhaitez fonctionner à d'autres vitesses, vous devrez alors ajuster les constantes dans les pilotes. Envoyez-moi un e-mail si vous avez besoin d'aide pour le faire. Vous pouvez également obtenir des conseils à partir des notes des applications Atmel dans les liens de l'étape Ressources. USI_TWI_Master_Initialise() Cette fonction initialise le matériel USI pour le fonctionnement en mode I2C. Appelez-le une fois au début de votre programme. Elle renvoie void et il n'y a pas d'arguments. USI_TWI_Get_State_Info()Cette fonction renvoie les informations d'erreur I2C et est utilisée si une erreur s'est produite lors d'une transaction I2C. Étant donné que cette fonction ne renvoie qu'un code d'erreur, j'utilise la fonction TWI_Act_On_Failure_In_Last_Transmission(TWIerrorMsg) pour faire clignoter une LED d'erreur. Les codes d'erreur sont définis dans USI_TWI_Master.h. Voici comment l'appeler:TWI_Act_On_Failure_In_Last_Transmission(USI_TWI_Get_State_Info())USI_TWI_Start_Read_Write()Cette fonction est utilisée pour lire et écrire des octets uniques sur les appareils I2C. Il est également utilisé pour écrire plusieurs octets. Il y a 6 étapes pour utiliser cette fonction.1)Déclarez un tampon de message dans votre programme pour contenir l'adresse de l'esclave et l'octet de données à envoyer ou à recevoir. unsigned char messageBuf (MESSAGEBUF_SIZE);2) Mettez l'adresse de l'esclave comme premier octet dans le tampon. Décalez-le d'un bit à gauche et OU dans le bit de lecture/écriture. Notez que le bit de lecture/écriture sera 1 pour une lecture et 0 pour une écriture. Cet exemple est pour un Read. messageBuf(0) = (TWI_targetSlaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT); 3)Lors d'une écriture, placez l'octet à écrire dans l'emplacement suivant dans le tampon.4)Appelez la fonction USI_TWI_Start_Read_Write avec le tampon de message et la taille du message comme arguments.temp = USI_TWI_Start_Read_Write(messageBuf, 2);5)Le La valeur renvoyée (temp dans ce cas) peut être testée pour voir si une erreur s'est produite. Si tel est le cas, il est traité comme indiqué ci-dessus. Voir les exemples dans les programmes.6) Si une lecture a été demandée, l'octet lu sera dans le deuxième emplacement dans le tampon. Si plusieurs octets doivent être écrits (comme sur un périphérique de mémoire), cette même routine peut être utilisée. La configuration du tampon et l'appel de la routine sont légèrement différents. Le deuxième octet du tampon sera l'adresse mémoire de départ à laquelle écrire. Les données à écrire seront dans les octets suivants. La taille du message sera la taille incluant toutes les données valides. Donc, si 6 octets doivent être écrits, alors la taille du message sera de 8 (adresse esclave + adresse mémoire + 6 octets de données). USI_TWI_Start_Random_Read() une sorte de souvenir. L'utilisation de cette routine est très similaire à la routine précédente, à deux exceptions près. Le réglage du bit de lecture/écriture n'a pas d'importance. L'appel de cette routine entraînera toujours une opération de lecture. La taille du message doit être égale à 2 plus le nombre d'octets à lire. Si aucune erreur ne s'est produite, les données seront dans la mémoire tampon en commençant au deuxième emplacement. les pilotes sont conçus pour une fréquence d'horloge de 4MHz pour ATmega168. L'exemple de code montre comment régler cette fréquence d'horloge. Si vous souhaitez fonctionner à d'autres vitesses, vous devrez alors ajuster les constantes dans les pilotes. Envoyez-moi un e-mail si vous avez besoin de le faire. TWI_Master_Initialise() Cette fonction initialise le matériel TWI pour le fonctionnement en mode I2C. Appelez-le une fois au début de votre programme. Il renvoie void et il n'y a pas d'arguments. Assurez-vous d'activer les interruptions en appelant swi() après l'initialisation. TWI_Get_State_Info()Cette fonction renvoie les informations d'erreur I2C et est utilisée si une erreur s'est produite lors d'une transaction I2C. Étant donné que cette fonction ne renvoie qu'un code d'erreur, j'utilise la fonction TWI_Act_On_Failure_In_Last_Transmission(TWIerrorMsg) pour faire clignoter une LED d'erreur. Les codes d'erreur sont définis dans TWI_Master.h, mais sont modifiés pour la signalisation sur une LED d'erreur. Voir l'exemple de code pour plus de détails. Voici comment l'appeler:TWI_Act_On_Failure_In_Last_Transmission(TWI_Get_State_Info())Notez que la vérification des erreurs est effectuée en s'assurant que la transaction I2C est terminée (fonction décrite ci-dessous) puis en testant un peu dans le mot d'état global. TWI_Start_Read_Write()TWI_Start_Random_Read()Ces deux fonctions fonctionnent de la même manière que les fonctions correspondantes décrites ci-dessus, à quelques exceptions près. Elles ne renvoient aucune valeur d'erreur. Les données lues ne sont pas transférées dans le tampon. Cela sera fait avec la fonction décrite ci-dessous. Lors de l'appel de TWI_Start_Random_Read, la taille du message doit être le nombre d'octets de données demandés plus un, pas deux. Le pilote I2C pour l'ATmega168 est piloté par interruption. C'est-à-dire que les transactions I2C sont démarrées puis exécutées indépendamment pendant que la routine principale continue de s'exécuter. Lorsque la routine principale veut des données d'une transaction I2C qu'elle a démarrée, elle doit vérifier si les données sont disponibles. La situation est la même pour la vérification des erreurs. La routine principale doit s'assurer que la transaction I2C est terminée avant de rechercher les erreurs. Les deux fonctions suivantes sont utilisées à ces fins. TWI_Transceiver_Busy()Appelez cette fonction pour voir si une transaction I2C est terminée avant de rechercher les erreurs. Les exemples de programmes montrent comment utiliser this. TWI_Read_Data_From_Buffer()Appelez cette fonction pour transférer des données du tampon de réception du pilote I2C dans le tampon de message. Cette fonction s'assurera que la transaction I2C est terminée avant de transférer les données. Bien qu'une valeur soit renvoyée par cette fonction, je trouve que la vérification directe du bit d'erreur est plus fiable. Voici comment l'appeler. La taille du message doit être supérieure d'une unité au nombre de bits de données souhaité. Les données seront dans messageBuf à partir du deuxième emplacement.temp = TWI_Read_Data_From_Buffer(messageBuf, messageSize);

Étape 4: Construisons

Construisons!
Construisons!
Construisons!
Construisons!
Construisons!
Construisons!
Construisons!
Construisons!

Commencez par télécharger le fichier I2C Schematics.zip. Vous voudrez peut-être créer un dossier I2C dans votre zone de travail pour contenir les schémas et les exemples de fichiers de programme. Décompressez les schémas dans ce répertoire. Vous trouverez un dossier appelé I2C Schematics. Ouvrez le fichier nommé minuscule I2C.pdf. Ce schéma montre le système de développement de ghetto ATtiny2313 et l'extenseur de port d'E/S PCA8574A (il est entouré d'une grande boîte en pointillés). Le circuit Port Expander est construit sur une maquette. Regardez les photos pour voir à quoi ressemblent ces circuits. Ils sont vraiment assez simples. La partie ATtiny2313 du schéma n'est que le système de développement du ghetto avec trois clignotants (LED1, 2 et 3, plus R4, 5 et 6) et un bouton-poussoir (S1) qui y est accroché, plus un détail supplémentaire. Ce détail est l'ajout de cavaliers (JP4, 5 et 6) qui peuvent être retirés pour permettre la connexion des lignes SCL et SDA du bus I2C. Les cavaliers doivent être en place pour la programmation, puis retirés pour que SCL et SDA puissent être connectés. Les photos montrent les cavaliers en place et retirés. Le placement de ces cavaliers dépend de vous, il vous suffit de les mettre sur votre Ghetto Development System si vous souhaitez utiliser le bus I2C. Le bus I2C doit être déconnecté et les cavaliers mis en place pour la programmation. Notez que vous n'avez vraiment besoin de vous préoccuper que de JP4 et JP6 pour le bus I2C. Mettez JP5 si vous pensez que vous voudrez un jour utiliser le bus SPI. L'extension de port d'E/S PCA8574A est très simple. Fournissez des connexions Vcc (+5 volts) et Gnd (masse) et connectez AD0, 1 et 2 à la masse (rend l'adresse esclave I2C 38 hexadécimale). Connectez ensuite 4 clignotants et 4 commutateurs DIP. (Si vous n'avez pas de commutateurs DIP, vous pouvez simplement utiliser des fils. Attachez à la terre ou laissez flotter pour signaler respectivement l'activation ou la désactivation.) Enfin, connectez les résistances de rappel (R11 et 12) de SDA et SCL à Vcc. Celles-ci sont affichées sous la forme 3,3K, mais toute valeur comprise entre 1,8K et 5,1K devrait fonctionner (peut-être jusqu'à 10K mais je n'ai pas essayé). Une fois que vous avez programmé l'ATtiny2313, vous pouvez retirer les cavaliers et connecter SDA et SCL pour les tests. Maintenant, pour l'ATmega168. Le seul problème ici est que vous n'avez peut-être pas construit de système de développement de ghetto pour ce processeur. Si tel est le cas, le schéma que je fournis (MEGA I2C.pdf) vous montrera comment. Ceci est juste une permutation de la version ATtiny2313. Si vous planifiez à l'avance, vous pouvez vous assurer que votre câble de programmation s'adaptera aux deux systèmes. La principale différence est l'ajout de C2 et C3. Voir les photos pour le placement de ceux-ci, ils doivent être très proches de la puce; l'un d'eux est en fait sous la puce. Ceux-ci aident à empêcher le bruit du convertisseur analogique-numérique en particulier. Vous n'avez pas besoin de mettre les cavaliers à moins que vous ne prévoyiez d'utiliser le bus SPI car ils ne sont pas nécessaires pour le bus I2C sur cette puce. Notez que la maquette PCA8754A restera inchangée. Vous n'aurez qu'à brancher SDA et SCL et c'est parti ! Facile, hein ?

Étape 5: codons et testons

Codez et testez !
Codez et testez !
Codez et testez !
Codez et testez !
Codez et testez !
Codez et testez !

Il est temps de créer les pilotes et les exemples de programmes. Nous allons commencer par l'ATtiny2313 et la maquette PCA8574A que nous venons de construire. Téléchargez le fichier I2C.zip dans votre répertoire de travail I2C et décompressez-le. Vous aurez un nouveau dossier appelé I2C. Vous y trouverez USI I2C (pour ATtiny2313) et TWI I2C (pour ATmega168). Dans USI I2C, vous trouverez le dossier I_O Port. Ce dossier contient le code de notre premier exemple de programme et les pilotes USI I2C. À l'aide de WinAVR, compilez et chargez le code dans l'ATtiny2313. Respirez profondément et mettez l'appareil sous tension. Voici à quoi s'attendre: À la mise sous tension, la LED 1 sur le port PD6 de l'ATtiny2313 clignote deux fois. Rien d'autre ne se produira jusqu'à ce que vous appuyiez sur le bouton (S1). A chaque appui sur le bouton, les interrupteurs sont lus et leur réglage s'affiche sur les LED connectées au PCA8574A. Modifiez la valeur des commutateurs, appuyez sur le bouton et les LED devraient changer. Continuez ainsi jusqu'à ce que vous ayez surmonté le plaisir de le voir fonctionner. Si (à Dieu ne plaise !) les choses ne fonctionnent pas comme prévu, vérifiez soigneusement votre câblage. Les erreurs I2C seront signalées par des clignotements sur la LED3 (PD4) et signifient probablement que vous devez vérifier que SDA et SCL sont connectés aux bonnes broches et sont correctement tirés. Si les choses ne fonctionnent toujours pas, lisez le reste de cette section pour en savoir plus sur le débogage. Maintenant, revenez en arrière et examinons le code. Ouvrez le fichier USI_I2C_Port.c. C'est le code de l'exemple de programme. (USI_TWI_Master.c et USI_TWI_Master.h contiennent les pilotes - vous pouvez les ignorer, sauf si vous êtes curieux.) Utilisez l'exemple pour guider vos propres applications I2C. La plupart du temps, le programme vous montre comment initialiser et utiliser les pilotes I2C, y compris la configuration l'adresse de l'esclave et le reste du tampon de message, et en extrayant les données. Vous verrez également comment je fais rebondir le bouton et configurer la boucle while. Quelques détails du programme méritent d'être mentionnés. Notez que les données des commutateurs sont inversées avant d'être écrites sur les voyants de l'extension de port. Notez également que les ports d'entrée sur le Port Expander doivent être écrits comme High pour qu'ils fonctionnent correctement. Ces détails sont décrits dans la fiche technique du PCA8574A. Lisez toujours attentivement les fiches techniques ! L'utilisation du débogage conditionnel est plus intéressante. Près du début du fichier programme se trouve l'instruction //#define DEBUG et des instructions #ifdef DEBUG sont parsemées dans tout le code. Tant que DEBUG n'est pas défini (les deux barres obliques font de la ligne un commentaire et l'empêchent d'être définie), le code dans les instructions #ifdef à #endif ne sera pas compilé. Mais si les choses ne fonctionnent pas comme prévu, recompilez et rechargez le code avec #define DEBUG sans commentaire. Vous obtiendrez beaucoup plus de clignotements sur les LED que vous pourrez décoder pour suivre l'exécution de votre programme et vous aider à trouver exactement où les choses ne vont pas. En fait, je vous recommande d'essayer ceci juste pour voir ce qui se passe. Ce que vous verrez, c'est que la LED 2 (sur PD5) clignotera au fur et à mesure que l'exécution progresse dans le programme. La valeur lue par les commutateurs clignotera sur la LED 1 (PD6) avant d'être affichée sur les LED de l'extension de port. Vous devriez pouvoir suivre le programme pendant son exécution en utilisant ces LED. Nous travaillerons ensuite avec l'ATmega168; sautez cette section si vous n'êtes intéressé que par l'ATtiny2313. Encore avec moi? Bon. Accédez au dossier TWI_I2C, modifiez votre répertoire de travail en IO_Port, puis compilez et chargez TWI_I2C_Port.c dans l'ATmega168. Déconnectez les lignes SDA et SCL de l'ATtiny2313 et connectez-les à l'ATmega168. Branchez l'alimentation et la terre, et mettez sous tension. L'opération devrait être la même ! Jouez jusqu'à ce que le frisson disparaisse, puis regardons le code. Ouvrez TWI_I2C_Port.c. Le code est presque identique à l'exception de la gestion des erreurs et de la prise en charge des pilotes pilotés par interruption. Voici les différences: Notez que l'horloge doit être réglée sur 4 MHz pour que le bus I2C fonctionne correctement. Le sei(); L'instruction active les interruptions après l'initialisation des pilotes I2C. Pour vérifier les erreurs, un bit d'état spécifique est testé. Lors d'une lecture, la fonction TWI_Read_Data_From_Buffer doit être appelée pour transférer les données lues dans le tampon des messages. Lors d'une écriture, while (TWI_Transceiver_Busy()) doit être utilisé pour s'assurer que le transfert est terminé avant de rechercher les erreurs. Ces deux dernières fonctions sont décrites ci-dessus dans la description des pilotes. A part ça, le code est à peu près le même que pour l'ATtiny2313. DEBUG fonctionne de la même manière si vous voulez expérimenter cela.

Étape 6: Utilisation de la mémoire I2C

Utilisation de la mémoire I2C
Utilisation de la mémoire I2C
Utilisation de la mémoire I2C
Utilisation de la mémoire I2C
Utilisation de la mémoire I2C
Utilisation de la mémoire I2C
Utilisation de la mémoire I2C
Utilisation de la mémoire I2C

Maintenant que nous avons appris à utiliser le bus I2C pour lire et écrire un extenseur de port I/O, passons à l'utilisation des mémoires I2C, à la fois RAM et EEPROM. La principale différence est que plusieurs octets peuvent être lus ou écrits à partir des mémoires avec une seule commande I2C. Pour nous préparer à ces expériences, nous devons modifier légèrement le matériel et construire quelques nouveaux circuits sur la maquette. Conservez le circuit Port Expander car nous l'utiliserons pour afficher certaines valeurs de mémoire. Retirez les commutateurs DIP du PCA8574A et mettez des clignotants sur ces broches. Si vous n'avez pas assez de clignotants, déplacez ceux de P4 à P7 vers P0 à P3. (Les valeurs à afficher sont suffisamment petites.) Maintenant, regardez le schéma I2C Ram.pdf et branchez le PCF8570 sur la maquette. Regardez aussi la photo. Assurez-vous de lier la broche 7 à Vcc. Faites passer les fils pour SDA et SCL à partir du PCA8574A. Aucune résistance de rappel supplémentaire n'est requise. Si vous êtes également intéressé par l'EEPROM, construisez ce circuit en utilisant également I2C EEPROM.pdf pour le 24C16, mais sachez que l'exemple utilise l'ATmega168. Ce circuit est vraiment simple. Comme discuté ci-dessus, les bits d'adresse doivent être ignorés. Il suffit de brancher l'alimentation et la terre. Ne connectez pas le SDA et le SCL pour l'instant car nous n'avons pas fini d'expérimenter avec le Ram. Nous commencerons nos expériences de mémoire avec l'ATtiny2313 connecté au PCA8574A Port Expander et au PCF8570 Ram. Le programme écrira quelques nombres dans la RAM, puis les relira et les affichera sur le Port Expander. Changez votre répertoire de travail en RAM sous USI I2C. Utilisez le fichier make pour compiler et télécharger USI_I2C_RAM.c. Notez que les fichiers du pilote I2C sont identiques à ceux que nous avons utilisés précédemment. Branchez l'alimentation et vous devriez voir un seul clignotement sur la LED 1 (PD6). Les données seront écrites dans les 4 premiers octets de la mémoire. Appuyez sur le bouton et deux octets seront lus et affichés. Vous devriez voir une LED s'allumer sur l'extension de port (P0), une pause de deux secondes, puis deux LED s'allumer (P0 et P1). Encore une pause de deux secondes et les LED devraient s'éteindre. Appuyez à nouveau sur le bouton pour recommencer la séquence. Le débogage est similaire à la méthode décrite ci-dessus. Regardons le code. Ouvrez USI_I2C_RAM.c. Il devrait ressembler assez au code précédent. Les principales différences sont les détails de la lecture et de l'écriture de la mémoire. Regardez la façon dont le tampon de message est chargé avant l'appel qui effectue réellement l'écriture. Le premier octet est l'adresse de l'esclave avec le bit de lecture/écriture défini de manière appropriée. Mais l'octet suivant est l'adresse mémoire à laquelle commencer à écrire des données. Viennent ensuite les octets de données réels qui seront chargés séquentiellement en mémoire à partir de l'adresse que nous avons spécifiée. Nous spécifions la taille du message comme 6. Nous commençons donc à écrire à l'adresse 00 et écrivons les valeurs 01, 03, 02 et 06 dans les emplacements de mémoire 00 à 03. Pour relire les données de la mémoire, nous devons utiliser la fonction USI_TWI_Start_Random_Read. Le tampon de messages obtient l'adresse d'esclave dans le premier octet et l'adresse de début dans le deuxième octet. Appelez ensuite la fonction avec la taille du message définie sur le nombre d'octets à lire plus 2. Notez que le bit de lecture/écriture n'a pas d'importance puisqu'une lecture sera effectuée malgré tout. Les données renvoyées commenceront au deuxième emplacement dans la mémoire tampon des messages. Une fois les données lues, elles sont inversées pour être affichées sur le Port Expander et écrites un octet à la fois avec une pause entre les valeurs. Enfin, les voyants de l'extension de port sont éteints. Les écritures sur le Port Expander sont identiques à ce qui a été fait dans les exemples précédents. Pour vous amuser, vous pouvez décommenter l'instruction #define DEBUG comme ci-dessus et voir de nombreuses LED clignotantes. Rincés d'excitation après une autre expérience réussie, passons à l'ATmega168 et à une EEPROM. Changez votre répertoire de travail en EEPROM sous TWI I2C. Utilisez le fichier make pour compiler et télécharger TWI_I2C_EEPROM.c. Notez que les fichiers du pilote I2C sont identiques à ceux que nous avons utilisés précédemment pour le PCA8574A. Pour tester le programme, déconnectez l'ATtiny2313 et connectez l'ATmega168. Laissez le bus I2C connecté au Ram et mettez-le sous tension. Les résultats sont différents puisque nous écrivons et lisons maintenant plus de données. La LED 1 sur PD7 doit clignoter à l'initialisation. Appuyez sur le bouton et les données seront lues à partir de la mémoire et affichées. Les LED du PCA8574 doivent clignoter dans la séquence suivante: P1, P0 & P2, (tous éteints), P0 & P1, P1 & P2. Enfin, les voyants du port devraient tous s'éteindre. Appuyez à nouveau sur le bouton pour répéter cela. Oh, mais attendez, dites-vous. Ce programme n'est-il pas pour l'EEPROM ? Puisque nous accédons à un périphérique de mémoire à la même adresse I2C, le même programme fonctionne à la fois pour la RAM et l'EEPROM. Mettez hors tension et déplacez SDA et SCL de la RAM vers l'EEPROM et exécutez à nouveau le programme. Cela devrait fonctionner exactement de la même manière. Notez que l'EEPROM et la Ram ne peuvent pas être connectés au bus I2C en même temps car ils partagent la même adresse. (Les plus intelligents parmi vous peuvent envisager de changer les bits d'adresses programmables sur le Ram, mais cela ne fonctionnera toujours pas. Le 24C16 utilise tout le bloc d'adresses qui peuvent être programmés pour le Ram.) OK, regardons ce dernier programme. Ouvrez TWI_I2C_EEPROM.c. La première chose à remarquer est que j'ai indiqué comment adresser l'EEPROM 24C16 complète. Il est accessible en morceaux de 256 octets à 8 adresses esclaves I2C différentes. Voyez comment MEMORY_ADDR est défini comme l'adresse de départ à 50 hexadécimales; c'est pourquoi le Ram a fonctionné. Si vous souhaitez accéder à d'autres blocs du 24C16, utilisez les autres adresses comme je l'ai indiqué. Jetez un oeil à la façon dont j'ai configuré pour écrire dans la mémoire. Tout d'abord, l'adresse de l'esclave avec le bit de lecture/écriture défini est mise dans le tampon, puis l'adresse de début 00, puis 16 octets de données. La fonction TWI_Start_Read_Write est appelée pour écrire les données (comme auparavant) avec la taille du message définie sur 18. Lorsque le bouton est enfoncé, nous utilisons TWI_Start_Random_Read et TWI_Read_Data_From_Buffer pour relire les données. Tous les trois octets sont affichés sur les voyants de l'extension de port. Enfin, les LED s'éteignent en attendant la prochaine pression sur le bouton. Vous pourriez vous demander pourquoi j'ai choisi d'écrire 16 octets. Si vous lisez attentivement la fiche technique, vous verrez que le 24C16 effectue un cycle d'écriture chaque fois qu'il reçoit 16 octets, même si davantage d'octets sont envoyés. Cela semblait donc être un bon numéro à utiliser. Si vous choisissez d'augmenter cela, vous devrez modifier la taille de MESSAGEBUF_SIZE. Vous devrez également modifier la valeur TWI_BUFFER_SIZE dans TWI_Master.h. Cela est dû au fait que le pilote copie les données de la mémoire tampon de messages pour une utilisation par la routine de service d'interruption. Toutes nos félicitations! Vous êtes maintenant prêt à utiliser le bus I2C dans vos propres projets !

Étape 7: Ressources Web

Voici les liens vers les fiches techniques des pièces utilisées pour les expériences. Vous devriez certainement les obtenir si vous n'obtenez rien d'autre. Port ExpanderRamEEPROMEn tant que créateur d'I2C, NXP (Philips) a une tonne de bonnes choses. (Ils aiment utiliser des crochets dans leurs URL, donc je ne peux pas les inclure correctement ici. Désolé.] Pour accéder à la zone I2C, sélectionnez Interface dans la liste Produits. Vous pourrez accéder à leur site I2C et accès à toutes les fiches techniques et notes d'applications qu'ils proposent. La description du bus I2C et les détails techniques en particulier sont ici. Obtenez les fiches techniques ATtiny2313 et ATmega168 (livres de données?) D'Atmel. Les notes d'application Atmel sont ici. Regardez AVR310 et AVR315. Prenez également le code. Jetez un œil ici pour beaucoup plus de choses I2C.

Étape 8: Notes pour les geeks

Pour le vrai geek qui veut connaître les détails, voici quelques points à garder à l'esprit si vous regardez les notes des applications Atmel et le code du pilote: - La méthode d'adressage et de commande d'un périphérique I2C ne fait pas partie des spécifications ! Hormis l'adresse esclave et le bit de lecture/écriture, les commandes, modes, etc. ne sont pas spécifiés et sont spécifiques à un équipement donné. Pour rendre cela très clair, notez que le schéma utilisé dans l'exemple Atmel ne s'applique qu'à cet exemple et est pratiquement non standard. - L'implémentation USI diffère de l'implémentation TWI de plusieurs manières importantes. + Avec USI, le pointage est assuré par logiciel; avec TWI, il est fourni par un générateur de débit binaire. + La méthode USI n'utilise pas d'interruptions; le TWI le fait. Cela a un certain sens puisque la famille Mega (utilisant TWI) pourrait faire beaucoup d'autres choses et ne devrait pas être accaparée par les transferts I2C. Une version pilotée par interruption pour USI est certainement possible, elle n'est tout simplement pas implémentée dans ce Instructable. + Le matériel USI n'est pas optimisé pour I2C et ne peut gérer que les transferts 8 bits. Cela signifie que deux transferts sont nécessaires pour envoyer le neuvième bit (soit NACK ou ACK). Le matériel TWI gère cela automatiquement. Cela rend l'implémentation du pilote USI un peu plus compliquée. + La détection d'erreur pour le TWI est gérée dans le matériel. L'USI nécessite une manipulation dans un logiciel qui complique quelque peu les choses. + Le matériel TWI contrôle directement la configuration du port. Le matériel USI requiert que les bits du port soient configurés avant que le port puisse être utilisé. Vous le verrez dans la routine Master_Initialize pour l'USI. - Atmel prétend qu'il est possible d'utiliser les pull-ups du port AVR pour les pull-ups du bus I2C. Je n'ai pas trouvé comment faire fonctionner cette approche. L'utilisation de deux résistances externes semble être un schéma assez simple, je n'y ai donc pas passé beaucoup de temps.

Conseillé: