;**************************************************************************** ;* ;* Module Classe: PortI2C ;* ;* Description: Librairie Native permettant le contrôle du Port I2C ;* P5.0 = SCL ;* P5.1 = SDA ;* ;* Filename: PortI2C.a51 ;* ;* Fichiers Dépendant: tini.inc, ds80c390.inc, tinimacro.inc apiequ.inc ;* ;* Auteur: Régnier Bruno ;* ;* Outils: macro + a390 ;* ;* Version: 1.0 ;* ;* Créé le: 15/01/2001 ;* ;* ;**************************************************************************** ; ; $Workfile: PortI2C.a51 $ ; $Revision: 10 $ ; $Date: 15/01/01 6:31a $ ; $Author: Regnier $ ; $include(tini.inc) $include(ds80c390.inc) $include(tinimacro.inc) $include(apiequ.inc) PORT_I2C EQU 0A1H ;Déclaration de la variable du port5 I2C ;*************************************************************************** ;* ;* Description de l'utilisation des registres ;* ;* R0_B0 : Tempo ;* R1_B0 : Adresse ;* R2_B0 : Masque pour l'adresse et la donnée ;* R3_B0 : Décrémentation du tempo ;* R4_B0 : Donnée d'écriture ;* R5_B0 : Donnée de lecture ;* R6_B0 : Valeur Tampon ;* ;* Bank 1 R0 -> R3 : Longueur du tableau de byte ;* ;*************************************************************************** ;*************************************************************************** ;* ;* Nom de la fonction: init ;* ;* Description: Initialisation de la librairie ;* ;* Input(s): void ;* ;* Outputs(s): void ;* ;**************************************************************************** PortI2C_Init: clr a; ret; ;*************************************************************************** ;* ;* Nom de la fonction: readWithOutAck ;* ;* Description: Lecture de valeurs sur le bus I2C sans Ack de la part du master ;* ;* Input(s): Tempo, Adresse, Valeur[] ;* ;* Outputs(s): void ;* ;**************************************************************************** Native_readWithOutAck: mov a,#0h ;Efface l'accumulateur lcall NatLib_LoadPrimitive ;Demande du premier paramètre - tempo - byte mov R0_B0,R0 ;On place le tempo dans le registre R0 de la bank0 mov a,#1h ;Sélection du deuxième paramètre lcall NatLib_LoadPrimitive ;Demande du deuxième paramètre - adresse - byte mov R1_B0,R0 ;On place l'adresse dans le registre R1 de la bank0 lcall INIT_I2C ;Initialisation du Bus lcall START_I2C ;Lancement de la condition de Start lcall SEND_ADDRESS ;Envoie de l'adresse lcall SEND_READ ;Envoie un bit de lecture lcall LISTEN_ACK ;Ecoute du ack de retour du composant mov R0,a ;Passage de la valeur de ack mov R1,a ;Passage de la valeur de ack mov R2,a ;Passage de la valeur de ack mov R3,a ;Passage de la valeur de ack jz Read_Fin ;Je stop tout si y'a pas eu de ACK mov a,#2h ;Sélection du troisième paramètre lcall NatLib_LoadJavaByteArray ;Demande du tableau de byte jnz Read_Fin ;Le pointeur n'est pas bon, alors je quitte mov R0_B1,R0 ;Déplacement de la taille du tableau mov R1_B1,R1 ;Déplacement de la taille du tableau mov R2_B1,R2 ;Déplacement de la taille du tableau mov R3_B1,R3 ;Déplacement de la taille du tableau mov a,R0_B1 ;Vérification de la conformité de la taille du tableau orl a,R1_B1 ;Taille +8bits orl a,R2_B1 ;Taille +16bits orl a,R3_B1 ;Taille +22bits jz Read_Fin ;Si la taille est nulle alors j'écris rien, na! mov a,R3_B1 ;Passage du MSB de la taille jnz Lecture_Donnee ;Si il est pas à zéro alors je le laisse tranquille inc R3_B1 ;J'incrémente le poid fort car dans la dernière phase, il a sa place mov a,R2_B1 jnz Lecture_Donnee inc R2_B1 mov a,R1_B1 jnz Lecture_Donnee inc R1_B1 mov a,R0_B1 jnz Lecture_Donnee inc R0_B1 Lecture_Donnee: lcall READ_DATA ;Envoie de la donnée lcall SDA_1 ;Simulation du Ack après lecture mov a,R5_B0 ;Stockage de la valeur lu dans ACC movx @dptr,a ;Stockage de la valeur dans le tableau inc dptr ;Je pointe ensuite sur le suivant djnz R0_B1,Lecture_Donnee ;Les tableaux de bytes actuelles sont djnz R1_B1,Lecture_Donnee ;adressable sur 2 octets uniquement djnz R2_B1,Lecture_Donnee ;l'utilisation de R2 et R3 djnz R3_B1,Lecture_Donnee ;reste pour une utilisation future mov R0,#0Fh ;Passage de la valeur de ack mov R1,#0Fh ;Passage de la valeur de ack mov R2,#0Fh ;Passage de la valeur de ack mov R3,#0Fh ;Passage de la valeur de ack Read_Fin: lcall STOP_I2C ;Stop clr a ;Tout c'est bien passé ljmp FIN ;Le programme se termine ;*************************************************************************** ;* ;* Nom de la fonction: readWithAck ;* ;* Description: Lecture de valeurs sur le bus I2C sans Ack de la part du master ;* ;* Input(s): Tempo, Adresse, Valeur[] ;* ;* Outputs(s): void ;* ;**************************************************************************** Native_readWithAck: mov a,#0h ;Efface l'accumulateur lcall NatLib_LoadPrimitive ;Demande du premier paramètre - tempo - byte mov R0_B0,R0 ;On place le tempo dans le registre R0 de la bank0 mov a,#1h ;Sélection du deuxième paramètre lcall NatLib_LoadPrimitive ;Demande du deuxième paramètre - adresse - byte mov R1_B0,R0 ;On place l'adresse dans le registre R1 de la bank0 lcall INIT_I2C ;Initialisation du Bus lcall START_I2C ;Lancement de la condition de Start lcall SEND_ADDRESS ;Envoie de l'adresse lcall SEND_READ ;Envoie un bit de lecture lcall LISTEN_ACK ;Ecoute du ack de retour du composant mov R0,a ;Passage de la valeur de ack mov R1,a ;Passage de la valeur de ack mov R2,a ;Passage de la valeur de ack mov R3,a ;Passage de la valeur de ack jz Read_Fin_Ack ;Je stop tout si y'a pas eu de ACK mov a,#2h ;Sélection du troisième paramètre lcall NatLib_LoadJavaByteArray ;Demande du tableau de byte jnz Read_Fin_Ack ;Le pointeur n'est pas bon, alors je quitte mov R0_B1,R0 ;Déplacement de la taille du tableau mov R1_B1,R1 ;Déplacement de la taille du tableau mov R2_B1,R2 ;Déplacement de la taille du tableau mov R3_B1,R3 ;Déplacement de la taille du tableau mov a,R0_B1 ;Vérification de la conformité de la taille du tableau orl a,R1_B1 ;Taille +8bits orl a,R2_B1 ;Taille +16bits orl a,R3_B1 ;Taille +22bits jz Read_Fin_Ack ;Si la taille est nulle alors j'écris rien, na! mov a,R3_B1 ;Passage du MSB de la taille jnz Lecture_Donnee_Ack ;Si il est pas à zéro alors je le laisse tranquille inc R3_B1 ;J'incrémente le poid fort car dans la dernière phase, il a sa place mov a,R2_B1 jnz Lecture_Donnee_Ack inc R2_B1 mov a,R1_B1 jnz Lecture_Donnee_Ack inc R1_B1 mov a,R0_B1 jnz Lecture_Donnee_Ack inc R0_B1 Lecture_Donnee_Ack: lcall READ_DATA ;Envoie de la donnée mov a,R5_B0 ;Stockage de la valeur lu dans ACC movx @dptr,a ;Stockage de la valeur dans le tableau inc dptr ;Je pointe ensuite sur le suivant lcall SDA_0 ;Effectue le Ack par le master djnz R0_B1,Lecture_Donnee_Ack ;Les tableaux de bytes actuelles sont djnz R1_B1,Lecture_Donnee_Ack ;adressable sur 2 octets uniquement djnz R2_B1,Lecture_Donnee_Ack ;l'utilisation de R2 et R3 djnz R3_B1,Lecture_Donnee_Ack ;reste pour une utilisation future mov R0,#0Fh ;Passage de la valeur de ack mov R1,#0Fh ;Passage de la valeur de ack mov R2,#0Fh ;Passage de la valeur de ack mov R3,#0Fh ;Passage de la valeur de ack Read_Fin_Ack: lcall STOP_I2C ;Stop clr a ;Tout c'est bien passé ljmp FIN ;Le programme se termine ;*************************************************************************** ;* ;* Nom de la fonction: write ;* ;* Description: Ecriture de valeurs sur le bus I2C ;* ;* Input(s): Tempo, Adresse, Valeur[] ;* ;* Outputs(s): void ;* ;**************************************************************************** Native_write: mov a,#0h ;Efface l'accumulateur lcall NatLib_LoadPrimitive ;Demande du premier paramètre - tempo - byte mov R0_B0,R0 ;On place le tempo dans le registre R0 de la bank0 mov a,#1h ;Sélection du deuxième paramètre lcall NatLib_LoadPrimitive ;Demande du deuxième paramètre - adresse - byte mov R1_B0,R0 ;On place l'adresse dans le registre R1 de la bank0 lcall INIT_I2C ;Initialisation du Bus lcall START_I2C ;Lancement de la condition de Start lcall SEND_ADDRESS ;Envoie de l'adresse lcall SEND_WRITE ;Envoie un bit de lecture lcall LISTEN_ACK ;Ecoute du ack de retour du composant mov R0,a ;Passage de la valeur de ack mov R1,a ;Passage de la valeur de ack mov R2,a ;Passage de la valeur de ack mov R3,a ;Passage de la valeur de ack jz Write_Fin ;Je stop tout si y'a pas eu de ACK mov a,#2h ;Sélection du troisième paramètre lcall NatLib_LoadJavaByteArray ;Demande du tableau de byte jnz Write_Fin ;Le pointeur n'est pas bon, alors je quitte mov R0_B1,R0 ;Déplacement de la taille du tableau mov R1_B1,R1 ;Déplacement de la taille du tableau mov R2_B1,R2 ;Déplacement de la taille du tableau mov R3_B1,R3 ;Déplacement de la taille du tableau mov a,R0_B1 ;Vérification de la conformité de la taille du tableau orl a,R1_B1 ;Taille +8bits orl a,R2_B1 ;Taille +16bits orl a,R3_B1 ;Taille +22bits jz Write_Fin ;Si la taille est nulle alors j'écris rien, na! mov a,R3_B1 ;Passage du MSB de la taille jnz Envoie_Donnee ;Si il est pas à zéro alors je le laisse tranquille inc R3_B1 ;J'incrémente le poid fort car dans la dernière phase, il a sa place mov a,R2_B1 jnz Envoie_Donnee inc R2_B1 mov a,R1_B1 jnz Envoie_Donnee inc R1_B1 mov a,R0_B1 jnz Envoie_Donnee inc R0_B1 Envoie_Donnee: movx a,@dptr ;Je met dans le registre a un élément du tableau mov R4_B0,a ;Stockage de la valeur inc dptr ;Je pointe ensuite sur le suivant lcall SEND_DATA ;Envoie de la donnée lcall LISTEN_ACK ;Ecoute du ack de retour du composant mov R0,a ;Passage de la valeur de ack mov R1,a ;Passage de la valeur de ack mov R2,a ;Passage de la valeur de ack mov R3,a ;Passage de la valeur de ack jz Write_Fin ;Pas de Ack reçu djnz R0_B1,Envoie_Donnee ;Les tableaux de bytes actuelles sont djnz R1_B1,Envoie_Donnee ;adressable sur 2 octets uniquement djnz R2_B1,Envoie_Donnee ;l'utilisation de R2 et R3 djnz R3_B1,Envoie_Donnee ;reste pour une utilisation future Write_Fin: lcall STOP_I2C ;Stop clr a ;Tout c'est bien passé ljmp FIN ;Le programme se termine ;*************************************************************************** ;* ;* Nom de la fonction: isExist ;* ;* Description: Test d'un composant sur le bus I2C ;* ;* Input(s): Tempo, Adresse ;* ;* Outputs(s): boolean ;* ;**************************************************************************** Native_isExist: mov a,#0h ;Efface l'accumulateur lcall NatLib_LoadPrimitive ;Demande du premier paramètre - tempo - byte mov R0_B0,R0 ;On place le tempo dans le registre R0 de la bank0 mov a,#1h ;Sélection du deuxième paramètre lcall NatLib_LoadPrimitive ;Demande du deuxième paramètre - adresse - byte mov R1_B0,R0 ;On place l'adresse dans le registre R1 de la bank0 lcall INIT_I2C ;Initialisation du Bus lcall START_I2C ;Lancement de la condition de Start lcall SEND_ADDRESS ;Envoie de l'adresse lcall SEND_WRITE ;Envoie un bit de lecture lcall LISTEN_ACK ;Ecoute du ack de retour du composant mov R0,a ;Passage de la valeur de ack mov R1,a ;Passage de la valeur de ack mov R2,a ;Passage de la valeur de ack mov R3,a ;Passage de la valeur de ack lcall STOP_I2C ;Stop clr a ;Fin correcte ljmp FIN ;Le programme se termine ;*************************************************************************** ;* ;* Nom de la fonction: INIT_I2C ;* ;* Description: Méthode interne pour l'initialisation du Bus : SDA=1, SCL=1 ;* ;*************************************************************************** INIT_I2C: mov a,PORT_I2C ;On regarde l'état du port pour ne changer que les bits nécessaires orl a,#00000011b ;Filtre sur la valeur du port pour mettre à 1 les deux derniers bits mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite ret; ;*************************************************************************** ;* ;* Nom de la fonction: START_I2C ;* ;* Description: Méthode interne pour donner la condition de start ;* SDA passe à 0 alors que SCL reste à 1 ;* ;*************************************************************************** START_I2C: mov a,PORT_I2C ;On regarde l'état du port pour ne changer que les bits nécessaires anl a,#11111101b ;SDA=0 SCL=1 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite anl a,#11111100b ;SDA=0 SCL=0 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite ret; ;*************************************************************************** ;* ;* Nom de la fonction: SEND_ADDRESS ;* ;* Description: Méthode interne permettant l'envoie de l'adresse ;* ;*************************************************************************** SEND_ADDRESS: mov R2_B0,#7h ;Adresse sur 7 bits mov b,#01000000b ;Masque permettant le traitement de l'adresse Boucle_Envoie: mov a,R1_B0 ;Travail avec l'adresse anl a,b ;réponse jz mise_SDA_0 ;Le bit est un 0 lcall SDA_1 ;Le bit est un 1 ljmp suite ;saute la mise à 0 de SDA mise_SDA_0: lcall SDA_0 ;Le bit est un 0 suite: mov a,b ;C'est bête rr a ;Mais c'est mov b,a ;Comme çà ! A oui, en fait c'est le décalage du masque djnz R2_B0,Boucle_Envoie ;Boucle tand que j'ai pas envoyer totalement l'adresse ret; ;*************************************************************************** ;* ;* Nom de la fonction: SEND_DATA ;* ;* Description: Méthode interne permettant l'envoie d'une donnée ;* ;*************************************************************************** SEND_DATA: mov R2_B0,#8h ;Donnee sur 8 bits mov b,#10000000b ;Masque permettant le traitement de l'adresse Boucle_Envoie_Donnee: mov a,R4_B0 ;Travail avec la donnée anl a,b ;réponse jz mise_SDA_0_Donnee ;Le bit est un 0 lcall SDA_1 ;Le bit est un 1 ljmp suite_Donnee ;saute la mise à 0 de SDA mise_SDA_0_Donnee: lcall SDA_0 ;Le bit est un 0 suite_Donnee: mov a,b ;C'est bête rr a ;Mais c'est comme çà ! mov b,a ;A oui, en fait c'est le décalage du masque djnz R2_B0,Boucle_Envoie_Donnee ;Boucle tand que j'ai pas envoyer totalement l'adresse ret; ;*************************************************************************** ;* ;* Nom de la fonction: READ_DATA ;* ;* Description: Méthode interne permettant la lecture d'une donnée ;* ;*************************************************************************** READ_DATA: mov R5_B0,#0h ;Mise à zéro de la donnée de lecture mov R2_B0,#8h ;Donnee sur 8 bits mov b,#10000000b ;Masque permettant le traitement de l'adresse Boucle_Lecture_Donnee: mov a,PORT_I2C ;On regarde l'état du port pour ne changer que les bits nécessaires anl a,#11111100b ;SDA=0 SCL=0 orl a,#00000010b ;SDA=1 SCL=0 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite mov a,PORT_I2C ;On regarde l'état du port pour ne changer que les bits nécessaires anl a,#11111100b ;SDA=0 SCL=0 orl a,#00000011b ;SDA=1 SCL=1 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite mov a,PORT_I2C ;Ecoute du bit de la lecture anl a,#00000010b ;Regarde le résultat si a=0 alors SDA=0 jz Bit_0 mov a,R5_B0 orl a,b ;Marquage du bit de lecture mov R5_B0,a Bit_0: mov a,b ;C'est bête rr a ;Mais c'est comme çà ! mov b,a ;A oui, en fait c'est le décalage du masque mov a,PORT_I2C ;On regarde l'état du port pour ne changer que les bits nécessaires anl a,#11111100b ;SDA=0 SCL=0 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite djnz R2_B0,Boucle_Lecture_Donnee ;Boucle tand que j'ai pas envoyer totalement l'adresse ret; ;*************************************************************************** ;* ;* Nom de la fonction: LISTEN_ACK ;* ;* Description: Méthode interne pour écouter la reception d'un ACK ;* ;*************************************************************************** LISTEN_ACK: mov a,PORT_I2C ;On regarde l'état du port pour ne changer que les bits nécessaires anl a,#11111110b ;SDA=1 SCL=0 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite orl a,#00000011b ;SDA=1 SCL=1 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite mov a,PORT_I2C ;Ecoute du Ack mov b,a ;Sauvegarde de la valeur du port anl a,#00000010b ;Regarde le résultat si a=0 c'est bon, sinon pas bon jz Ack_Bon ;True = a<>0 clr a ;False = 0 ljmp Ack_Retour ;J'me casse Ack_Bon: mov a,#11111111b ;True<>0 Ack_Retour: anl b,#11111110b ;SDA=1/0 SCL=0 mov PORT_I2C,b ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite ret; ;*************************************************************************** ;* ;* Nom de la fonction: SEND_WRITE ;* ;* Description: Méthode interne envoyant un bit d'ecriture ;* ;*************************************************************************** SEND_WRITE: lcall SDA_0; ret; ;*************************************************************************** ;* ;* Nom de la fonction: SEND_READ ;* ;* Description: Méthode interne envoyant un bit de lecture ;* ;*************************************************************************** SEND_READ: lcall SDA_1; ret; ;*************************************************************************** ;* ;* Nom de la fonction: SDA_0 ;* ;* Description: Méthode interne permettant de mettre à 0 SDA ;* ;*************************************************************************** SDA_0: mov a,PORT_I2C ;On regarde l'état du port pour ne changer que les bits nécessaires anl a,#11111100b ;SDA=0 SCL=0 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite orl a,#00000001b ;SDA=0 SCL=1 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite anl a,#11111100b ;SDA=0 SCL=0 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite ret ; ;*************************************************************************** ;* ;* Nom de la fonction: SDA_1 ;* ;* Description: Méthode de interne permettant de mettre à 1 SDA ;* ;*************************************************************************** SDA_1: mov a,PORT_I2C ;On regarde l'état du port pour ne changer que les bits nécessaires anl a,#11111100b ;SDA=0 SCL=0 orl a,#00000010b ;SDA=1 SCL=0 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite orl a,#00000011b ;SDA=1 SCL=1 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite anl a,#11111110b ;SDA=1 SCL=0 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite ret ; ;*************************************************************************** ;* ;* Nom de la fonction: STOP_I2C ;* ;* Description: Méthode interne pour donner la condition de stop ;* SDA passe à 1 alors que SCL reste à 1 ;* ;*************************************************************************** STOP_I2C: mov a,PORT_I2C ;On regarde l'état du port pour ne changer que les bits nécessaires anl a,#11111100b ;SDA=0 SCL=0 / Non Validé anl a,#00000001b ;SDA=0 SCL=1 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite orl a,#00000011b ;SDA=1 SCL=1 mov PORT_I2C,a ;transfert de la donnée vers le port lcall WAIT ;Attente avant la suite ret; ;*************************************************************************** ;* ;* Nom de la fonction: WAIT ;* ;* Description: Méthode interne pour perdre du temp ;* ;*************************************************************************** WAIT: mov R3_B0,R0_B0 ;Mise en place de la minuterie Attente: nop ;Je fais rien mais je le fait bien djnz R3_B0,Attente ;On décrémente et on jump tand que c'est pas égale à 0 ret; ;*************************************************************************** ;* ;* Nom de la fonction: FIN ;* ;* Description: Méthode permettant de quitter le programme ;* ;*************************************************************************** FIN: ret; END