Exercices I2C ************* Programme N°2b : --------------- En branchant un potentiomètre de 10K lin sur l'entrée AD1 du K8000 (voir shémas ci-dessous), écrivez un programme qui change la vitesse du chenillard en fonction de la position du potentiomètre. La postition gauche du potentiomètre fait défiler les leds vers la gauche, puis au fur et à mesure que l'on tourne le potentiomètre, la vitesse ralenti pour s'arrêter en position centrale, puis le défilement repart vers la droite en s'accélérant au fur et à mesure que le potentiomètre s'approche de la butée de droite. 5V ------------\ / \<---------AD1 / \ GND(AD1)-------/ Le K8000 est commuté en position 0 (OFF-OFF) Circuit Type Adresse du circuit ________________________________________________Fixe_A3_A2_A1_A0__Déc._ IC17 : PCF8574A n°0 IO-chip no: 0 0111 0 0 0 X = 112+X IC18 : PCF8574A n°1 IO-chip no: 1 0111 0 0 1 X = 114+X IC20 : PCF8591 ADDA chip 1001 0 0 0 X = 144+X 'En lisant l'énoncé, il semble clair que nous allons devoir définir une position 'centrale du POT (autour de la valeur 128). Ce qui l'est moins, c'est que cette 'position centrale devra avoir une certaine largeur (par exemple 16), sinon, 'l'utilisateur risque de ne jamais pouvoir la trouver. 'Fort de ces remarques, nous allons pouvoir définir trois zones pour la valeur 'de lecture du potentiomètre : ' de 0 à 119 : Défilement gauche (0 - rapide et 119 - Lent) ' de 120 à 135 : Arrêt ' de 136 à 255 : Défilement droite (255 - rapide et 136 - Lent) 'D'autre part, dans l'exercice précédent, nous avions un sens de défilement 'constant, donc, nous pouvions définir les valeurs d'allumage dans une boucle 'de type "FOR-NEXT". Ici, chaque valeur de LED devra être déduite de 'la précédente, et comme elle peut-être plus petite, egale ou plus grande, 'l'utilisation d'une boucle "FOR-NEXT" ne semble pas indiquée. 'Donc, au final, il nous faudra écrire une boucle "infinie" dans laquelle 'il nous faudra calculer la valeur du temps de pause, et le valeur de 'la "LED" suivante. 'D'autre part, l'utilisation d'une variable nibble pour la LED fera en sorte 'que les tests de butée inférieure et de butée supérieure ne seront pas utile, 'puisque en utilisant un nibble, nous avons 15+1=0 et 0-1=15. 'Après ces remarques, nous pouvons maintenant écrire la petite liste de tâches. 'Initialisation de la LED 'Début de la boucle "infinie" ' Lecture du POT ' Calcul de la tempo (3 cas) ' Calcul de la LED (3 cas) ' Allumage de la LED ' Attendre la tempo ' Eteindre la LED 'Fin de la boucle "infinie" 'Liste des routines I2C '---------------------- 'I2CSTART : Mise du bus I2C dans la condition "START" 'I2CSTOP : Mise du bus I2C dans la condition "STOP" 'I2CTX : Emission d'un octet sur le bus I2C 'I2CRX : Réception d'un octet sur le bus I2C 'ACKTX : Emission d'un "ACK" sur le bus I2C 'ACKRX : Réception d'un "ACK" sur le bus I2C 'Liste des routines utilisées dans le programme '---------------------------------------------- 'WRITEBYTE : Ecriture d'un octet sur le bus 'READBYTE : LEcture d'un octet sur le bus ******************************************************************************* Structure du programme BEGIN 'Début du programme ' Définition des variables utilisées ' ********************************** DECLARE i2cadr AS byte 'Adresse du circuit I2C DECLARE i2cio AS byte 'Valeur lue ou écrite dans le composant I2C DECLARE i2cdata AS byte 'Octet de valeur lue ou écrite sur le bus I2C DECLARE i2cack AS bit 'Bit "ACK" du bus I2C DECLARE i2csda AS nibble 'Pin du circuit qui sert de "I2C DATA" DECLARE i2cscl AS nibble 'Pin du circuit qui sert de "I2C CLOCK" DECLARE i2cad1WR AS byte 'Adresse d'écriture du premier PCF8574 DECLARE i2cad2WR AS byte 'Adresse d'écriture du deuxième PCF8574 DECLARE i2cad3RD AS byte 'Adresse de lecture du PCF8591 DECLARE Temps AS Word 'Temporisation (Vitesse de défilement) DECLARE Led AS nibble 'Valeur de la LED à allumer DECLARE Pot AS byte 'Valeur de lecture du potentiomètre DECLARE I AS Byte 'Variable de travail DECLARE J AS Byte 'Variable de travail DECLARE K AS Byte 'Variable de travail DECLARE L AS Byte 'Variable de travail ' Définition des constantes ' ************************* LET i2csda = 12 LET i2cscl = 13 LET i2cad1WR = 112 LET i2cad2WR = 114 LET i2cad3RD = 145 ' Programme Principal ' ******************* LET Led = 0 'Initialisation de la LED DO WHILE k=k 'Début de la boucle "infinie" LET i2cadr = i2cad3RD 'Adresse du circuit PCF8591 GOSUB READBYTE 'Lecture du premier convertisseur LET Pot = i2cio 'Mise en mémoire de la valeur du POT IF Pot < 120 'Test pour le défilement à "gauche" LET Led = Led - 1 'Défilement gauche LET Temps = (120 - Pot) * 16 'Temps entre 1920 ms et 100 ms ELSE IF Pot < 136 'Test pour l'arrêt LET Temps = 1000 'Pas de changement de LED et pause 1s ELSE 'Test pour défilement à "droite" LET Led = Led + 1 'Défilement droit LET Temps = (Pot - 135) * 16 'Temps entre 100 ms et 1920 ms ENDIF ENDIF IF Led < 8 'Test pour envoi vers le 1er PCF8574 LET i2cio = 2 ^ Led 'Valeur pour allumer une led LET i2cadr = i2cad1WR 'Adresse du premier PCF8574 GOSUB WRITEBYTE 'Envoi vers le bus I2C PAUSE temps 'Pause avant d'éteindre la led LET i2cio = 0 'Valeur pour éteindre la led LET i2cadr = i2cad1WR 'Adresse du premier PCF8574 GOSUB WRITEBYTE 'Envoi vers le bus I2C ELSE 'Sinon envoi vers le 2eme PCF8574 LET i2cio = 2 ^ (Led - 8) 'Valeur pour allumer une led LET i2cadr = i2cad2WR 'Adresse du deuxième PCF8574 GOSUB WRITEBYTE 'Envoi vers le bus I2C PAUSE temps 'Pause avant d'éteindre la led LET i2cio = 0 'Valeur pour éteindre la led LET i2cadr = i2cad2WR 'Adresse du deuxième PCF8574 GOSUB WRITEBYTE 'Envoi vers le bus I2C ENDIF ENDDO 'Fin ?? de la boucle "infinie" END ' Routine d'écriture de i2cio à l'adresse i2cadr sur le bus I2C SUB WRITEBYTE GOSUB i2cstart 'Mise du bus en condition "START" LET i2cdata = i2cadr 'Valeur de l'adresse à écrire GOSUB i2ctx 'Ecriture de l'adresse I2C GOSUB ackrx 'Attente de l'ACK LET i2cdata = i2cio 'valeur de la donnée à écrire GOSUB i2ctx 'Ecriture de la donnée I2C GOSUB ackrx 'Attente de l'ACK GOSUB i2cstop 'Mise du bus en condition "STOP" ENDSUB ' Routine de lecture dans i2cio à l'adresse i2cadr sur le bus I2C ' Attention, cette routine ne lit qu'un seul octet, ce qui dans ' le cas du PCF8591 ne permet de lire que la valeur du premier ' convertisseur analogique-digital. (Ce qui est demandé içi) SUB READBYTE GOSUB i2cstart 'Mise du bus en condition "START" LET i2cdata = i2cadr 'Valeur de l'adresse à écrire GOSUB i2ctx 'Ecriture de l'adresse I2C GOSUB ackrx 'Attente de l'ACK GOSUB i2crx 'Lecture de la donnée I2C GOSUB acktx 'ACK du "master" LET i2cio = i2cdata 'Mise a jour de la valeur lue GOSUB i2cstop 'Mise du bus en condition "STOP" ENDSUB 'Définitions des subroutines I2C '******************************* ' I2CSTART : Mise du bus I2C dans la condition "START" SUB I2CSTART Mise à 1 de la pin définie par i2csda 'I2C data line Mise à 1 de la pin définie par i2cscl 'I2C clock line Mise à 0 de la pin définie par i2csda 'I2C data line Mise à 0 de la pin définie par i2cscl 'I2C clock line ENDSUB ' I2CSTOP : Mise du bus I2C dans la condition "STOP" SUB I2CSTOP Mise à 0 de la pin définie par i2csda 'I2C data line Mise à 1 de la pin définie par i2cscl 'I2C clock line Mise à 1 de la pin définie par i2csda 'I2C data line ENDSUB 'Définitions des subroutines I2C (suite) '*************************************** ' I2CTX : Emission d'un octet sur le bus I2C SUB I2CTX LET i = 0 DO WHILE i < 8 LET j = (i)ème bit de i2cdata Mise à la valeur j de la pin définie par i2csda Mise à 1 de la pin définie par i2cscl PAUSE 1ms Mise à 0 de la pin définie par i2cscl Mise à 0 de la pin définie par i2csda ENDDO ENDSUB ' I2CRX : Réception d'un octet sur le bus I2C SUB I2CRX LET i = 0 DO WHILE i < 8 Mise à 1 de la pin définie par i2cscl LET j = valeur lue sur la pin définie par i2csda LET (i)ème bit de i2cdata = j PAUSE 1ms Mise à 0 de la pin définie par i2cscl ENDDO ENDSUB ' ACKTX : Emission d'un "ACK" sur le bus I2C SUB ACKTX Mise à 1 de la pin définie par i2cscl Mise "haute-impédance" de la pin définie par i2csda PAUSE 1ms Mise à 0 de la pin définie par i2csda PAUSE 1ms Mise à 0 de la pin définie par i2cscl ENDSUB ' ACKRX : Réception d'un "ACK" sur le bus I2C SUB ACKRX Mise à 1 de la pin définie par i2cscl Mise "haute-impédance" de la pin définie par i2csda PAUSE 1ms Attente d'un 0 sur la pin définie par i2csda PAUSE 1ms Mise à 0 de la pin définie par i2cscl ENDSUB '****************************************************************************** 'Programme pour le STAMP '******************************************************************* '* Exercice 5-2b : Réaliser un chenillard avec 16 voies avec K8000 * '* La vitesse du chenillard varie avec la position * '* d'un Pot branché sur l'entrée AD1 du K8000. * '* de plus, il faut ajouter une variation du sens * '* en fonction de la position du pot. * '******************************************************************* ' 'Utilisation de la carte Micro-Info et le K8000 'La ligne SDA est connectée en P12 'La ligne SCL est connectée en P13 'Notez que la carte MI est allimentée par le K8000 'Description du K8000 'Circuit Type Adresse du circuit '_________________________________________Fixe_A3_A2_A1_A0__Décimal_ 'IC17 : PCF8574A n°0 IO-chip no: 0 0111 0 0 0 X = 112+X 'IC18 : PCF8574A n°1 IO-chip no: 1 0111 0 0 1 X = 114+X 'IC20 : PCF8591 ADDA chip 1001 0 0 0 X = 144+X 'Les remarques données pour les deux PCF8574A dans l'exercice '(5-1) et pour le PCF8491 dans l'exercice (5-2a) sont identiques. 'Pour faciliter l'écriture de notre programme, nous utiliserons 'les routines "ECR17" et "ECR18", qui en fait seront la routine '"WRITEBYTE" de la structurée, mais avec les paramètres d'adresse 'respectivement de IC17 et IC18 du K8000. En plus, la routine '"READBYTE" sera ici remplacée par une routine "LEC20" qui 's'occupera d'écrire l'octet dans le PCF8591 'Liste des routines I2C '---------------------- 'I2CSTART : Mise du bus I2C dans la condition "START" 'I2CSTOP : Mise du bus I2C dans la condition "STOP" 'I2CTX : Emission d'un octet sur le bus I2C 'I2CRX : Reception d'un octet sur le bus I2C 'ACKTX : Emission d'un "ACK" sur le bus I2C 'ACKRX : Reception d'un "ACK" sur le bus I2C 'Définition des entrées-sorties OUTPUT 0 OUTPUT 1 OUTPUT 2 OUTPUT 3 OUTPUT 4 OUTPUT 5 OUTPUT 6 OUTPUT 7 OUTPUT 8 OUTPUT 9 INPUT 10 OUTPUT 11 INPUT 12 INPUT 13 INPUT 14 INPUT 15 'Initialisation du système INS = 0 OUTS = 0 'Définition des variables de travail I VAR BYTE J VAR BYTE K VAR BYTE L VAR BYTE 'Definition des variables I2C i2caddr var byte 'Mot de l'adresse du composant I2C i2cdata var byte 'Octet de valeur lue ou ecrite sur le bus I2C i2cack var bit 'Bit "ACK" du bus I2C i2csda con 12 'Pin I2C data du Stamp2 i2cscl con 13 'Pin I2C clock du Stamp2 i2cad1WR con %01110000 'Adresse d'ecriture du 1er PCF8574A i2cad2WR con %01110010 'Adresse d'ecriture du 2eme PCF8574A i2cad3RD con %10010001 'Adresse de lecture du PCF8591 i2cio var byte 'Valeur lue ou ecrite dans le composant i2c 'Definition des autres variables Temps var word 'Temps de pause pour le chenillard Pot var byte 'Valeur de lecture du potentiomètre Led var nib 'Valeur de la led à allumer 'Debut du programme principal '**************************** 'initialisation de IC17 et IC18 i2cio = 255 'Valeur pour "éteindre" les leds de IC17 et IC18 GOSUB ecr17 'Extinction des leds de IC17 GOSUB ecr18 'Extinction des leds de IC18 Led = 0 'Initialisation de la led deb: GOSUB lec20 'Lecture du Potentiomètre IF pot > 119 THEN s1 'Test pour le défilement à "gauche" led = led-1 'Défilement à gauche Temps = 240-((120-pot)*2) 'Calcul de la tempo GOTO s3 'Saut vers allumage led s1: IF pot > 135 Then s2 'Test pour l'arrêt Temps = 240 'Calcul de la tempo GOTO s3 'Saut vers allumage led s2: Led = led+1 'Défilement à droite Temps = 240-((pot-135)*2) 'Calcul ded la tempo s3: IF led>7 THEN s4 'Test inversé pour l'écriture dans IC17 i2cio=255-(1<