Pingumaru | Bonjour,
J'ai essayé d'être le plus clair possible, je suis désolé si je m'exprime mal.
Je travaille actuellement sur un projet : à l'aide d'un capteur (Dallas 1621) je dois récuperer une température et l'afficher sur un écran 128*64 à raison d'une capture / 30 secondes.
La communication entre le pic et le capteur se fait par de l'I2C en passant par le PORT C (RC3 et 4 pour SCL et SDL).
La communication entre l'écran et le pic se fait sur les PORT B et D (Le port B contrôlant tout ce qui est "commande" et le port D les données).
J'arrive à effectuer ses deux actions séparement, malheureusement lorsque je combine l'ensemble soit : -la communication I2C marche mais l'écran n'affiche rien
-l'écran me colle une valeur fixe ne correspondant pas à la température et il n'y à aucune communication en I2C.
Mon code sur l'I2C (les fonctions proviennent du cours de Bigonoff)
Code :
- org 0x00
- goto debut
- org 0x04
- debut
- bsf STATUS,RP0 ; passer en banque 1
- bsf TRISC,3 ; SCL en entrée (mis par défaut sur un reset)
- bsf TRISC,4 ; SDA en entrée (idem)
- movlw 0x80 ; slew rate control en service, mode I²C ======================100kHZ SLEW RATE CONTROL à 1=======================
- movwf SSPSTAT ; dans SSPSTAT
- movlw 0x09 ; valeur de recharge du BRG =====================================4MHz / (100KHz * 4) - 1=============================
- movwf SSPADD ; dans registre de recharge
- bcf STATUS,RP0 ; repasser banque 0
- movlw 0x38 ; module MSSP en service en mode I²C master
- movwf SSPCON ; dans registre de contrôle
- call I2C_start1 ; Start
- call I2C_start1 ; Start
- call I2C_adress
- call I2C_check
- call I2C_send_config ; Début de config
- call I2C_check ; Réponse
- call I2C_send_conf ; Suite config
- call I2C_check ; Réponse
- call I2C_stop2
- call I2C_start1 ; Start
- call I2C_start1 ; Start
- call I2C_adress ; Appel
- call I2C_check ; Réponse
- call I2C_send_start ; Début de conversion de la température EE
- call I2C_check ; Réponse
- call I2C_stop2 ; Fin
- ici
- call I2C_start1 ; Start
- call I2C_start1 ; Start
- call I2C_adress ; Appel du capteur
- call I2C_check ; Réponse du capteur
- call I2C_send_read ; Lecture de la température
- call I2C_check ; Réponse du capteur
- call I2C_repeatstart ; ReStart
- call I2C_adress2 ; Appel
- call I2C_check ; Réponse
- call I2C_reade ; Réception des données du capteur
- movf SSPBUF, w ; Stockage des degres
- movlw buffer1
- call I2C_ACK_MASTER ; Autorise l'esclave à poursuivre
- call I2C_reade
- movf SSPBUF, w ;Stockage des demidegres
- movlw buffer2
- call I2C_NOACK ; Fin de réception
- call I2C_stop2 ; Stop
- goto ici
- I2C_idle ; Sous routine contrôlant la présence d'une action en cours
- BANKSEL SSPSTAT ; passer en banque 1
- I2C_idle2
- btfsc SSPSTAT,R_W ; tester si émission en cours
- goto I2C_idle2 ; oui, attendre
- I2C_idle3
- movf SSPCON2,w ; charger registre SSPCON2
- andlw 0x1F ; conserver ACKEN,RCEN,PEN,RSEN,et SEN
- btfss STATUS,Z ; tester si tous à 0 (aucune opération en cours)
- goto I2C_idle3 ; non, attendre
- bcf STATUS,RP0 ; repasser en banque 0
- return ; rien en cours, on peut sortir
- I2C_start1 ; Sous routine lançant le bit Start
- ;call I2C_idle ; attendre fin de l’opération précédente(voir plus haut)
- bsf STATUS,RP0 ; passer en banque 1
- bsf SSPCON2,SEN ; lancer start-condition
- bcf STATUS,RP0 ; repasser en banque 0
- return ; retour
- I2C_adress ; Mode écriture
- call I2C_idle ; attendre fin de l’opération précédente
- movlw 0x90 ; charger adresse esclave (b7 à b1) avec b0 = 0
- movwf SSPBUF ; lancer l’émission de l’adresse en mode écriture
- return ; et retour
- I2C_stop2 ; Stop
- bsf STATUS,RP0 ; passer en banque 1
- bsf SSPCON2,PEN ; lancer le stop-condition
- I2C_start2
- ;clrwdt ; effacer watchdog
- btfsc SSPCON2,PEN ; stop-condition terminé ?
- goto I2C_start2 ; non, attendre
- bcf STATUS,RP0 ; oui, repasser en banque 0
- return
- I2C_send_start ; Autoriser la conversion de température
- call I2C_idle ; attendre fin de l’opération précédente
- movlw 0xEE ; charger octet à envoyer
- movwf SSPBUF ; lancer l’écriture de l’octet
- return ; et retour
- I2C_check ; Surveillance du ACK provenant de l'esclave
- call I2C_idle ; attendre fin de l’opération précédente
- bsf STATUS,RP0 ; passer en banque 1
- btfsc SSPCON2,ACKSTAT ; tester ACK reçu
- goto errore ; pas reçu, traiter erreur
- bcf STATUS,RP0
- return
- errore
- bcf STATUS,RP0
- call I2C_stop2
- return
- I2C_send_01 ; Autoriser la conversion de température
- call I2C_idle ; attendre fin de l’opération précédente
- movlw 0x01 ; charger octet à envoyer
- movwf SSPBUF ; lancer l’écriture de l’octet
- return ; et retour
- I2C_send_config ; Lecture de la conversion
- call I2C_idle ; attendre fin de l’opération précédente
- movlw 0xAC ; charger octet à envoyer
- movwf SSPBUF ; lancer l’écriture de l’octet
- return ; et retour
- I2C_send_conf ; Lecture de la conversion
- call I2C_idle ; attendre fin de l’opération précédente
- movlw 0x00 ; charger octet à envoyer
- movwf SSPBUF ; lancer l’écriture de l’octet
- return ; et retour
- I2C_repeatstart ; Repeated Start
- call I2C_idle ; attendre fin de l’opération précédente
- bsf STATUS,RP0 ; passer en banque 1
- bsf SSPCON2,RSEN ; lancer le repeated start-condition
- bcf STATUS,RP0 ; repasser en banque 0
- return ; retour
- I2C_reade ; Reception des données par le maître
- call I2C_idle ; attendre fin de l’opération précédente
- bsf STATUS,RP0 ; passer banque 1
- bsf SSPCON2,RCEN ; lancer la réception
- bcf STATUS,RP0 ; repasser banque 0
- return ; et retour
- I2C_NOACK ; Lancer l'ack provenant du maitre cloturant une reception
- call I2C_idle ; attendre fin de l’opération précédente
- bsf STATUS,RP0 ; passer banque 1
- bsf SSPCON2,ACKDT ; le bit qui sera envoyé vaudra « 1 »
- bsf SSPCON2,ACKEN ; lancer l’acknowledge (= ACKDT = 1 = N0ACK)
- bcf STATUS,RP0 ; repasser banque 0
- return ; et retour
- I2C_ACK_MASTER ; Lancer l'ack provenant du maitre
- call I2C_idle ; attendre fin de l’opération précédente
- bsf STATUS,RP0 ; passer banque 1
- bcf SSPCON2,ACKDT ; le bit qui sera envoyé vaudra « 1 »
- bsf SSPCON2,ACKEN ; lancer l’acknowledge
- bcf STATUS,RP0 ; repasser banque 0
- return ; et retour
- I2C_send_read ; Lecture de la conversion
- call I2C_idle ; attendre fin de l’opération précédente
- movlw 0xAA ; charger octet à envoyer
- movwf SSPBUF ; lancer l’écriture de l’octet
- return ; et retour
- I2C_adress2 ; Mode lecture
- call I2C_idle ; attendre fin de l’opération précédente
- movlw 0x91 ; charger adresse esclave (b7 à b1) avec b0 = 1
- movwf SSPBUF ; lancer l’émission de l’adresse en mode lecture
- return ; et retour
-
- end
|
Bizarrement pour qu'il y ait communication avec le capteur, je dois lancer deux fois le bit de start.
Et celui pour l'écran
Code :
- #include <p16f877A.inc>
- compteur EQU 0x20 ; Variable parametrant le nombre de répétition du TIMER1 pour arriver à 30 sec
- dizaine EQU 0x21 ; Variable récuperant la valeur de la roue des dizaines
- unite EQU 0x22 ; celle de la roue des unités
- cpt EQU 0x23 ; Second compteur représentant la durée entre chaque capture
- save EQU 0x24 ; Sauvegarde la valeur du compteur
- degres EQU 0x25 ; Récupère la valeur en degrés venant du capteur
- demidegres EQU 0x26 ; Récupère la présence ou non d'un demi-degrés
- echec EQU 0x27 ; Identifie l'opération où le ACK n'a pas été reçu
- repere EQU 0x28 ; Repère se situant en haut de l'écran
- X EQU 0x29 ; plage d'adresse en hauteur (0 à 7)
- Y EQU 0x2A ; plage d'adresse en longueur (0 à 63)
- pixel EQU 0x2B ; permet l'inscription d'un pixel sur l'ecran
- CS1 EQU 0x2C ; 1 = CS1 / 0 = CS2
- efface EQU 0x2D
- org 0x00
- goto debut
- org 0x04
- bcf PIR1, TMR1IF ; Remet le flag d'overflow à 0
- decfsz compteur, f ; Décrémente le compteur
- retfie ; Retour d'interruption
- movlw 0x39 ; Nombre de passage à effectuer pour être le plus...
- movwf compteur ; ...proche de 30 secondes / On relance le timer sur 30 secondes...
- movlw 0x10
- movwf degres
- movlw 0x00
- movwf demidegres
- call ecran
- retfie
- debut
- init_lcd
- bsf STATUS, RP0 ; passer en banque 1
- clrf TRISD ; PORTD en sortie
- clrf TRISB ; PORTB en sortie
- bcf STATUS, RP0 ; passer en banque 0
- movlw 0x3F
- movwf PORTD ; ON
- movlw 0x32 ; CS2 1ère partie de l'écran
- movwf PORTB
- bcf PORTB, 4 ; Chute de l'enable, envoie des données
- call start_line_CS2 ; Position de la ligne de départ
- call blanc ;Nettoyage de l'écran
- movlw 0x3F
- movwf PORTD ; ON
- movlw 0x31 ; CS1 2nde partie de l'écran
- movwf PORTB
- bcf PORTB, 4
- movlw 0x01
- movwf CS1
- call start_line_CS1
- call blanc
- movlw 0x00
- movwf CS1
- movlw 0x0A
- movwf degres
- movlw 0x00
- movwf Y
- call setadress ; On selectionne l'adresse
- debut2
- bsf T1CON, T1CKPS1 ; Prédiviseur...
- bsf T1CON, T1CKPS0 ; ...à 8
- bcf T1CON, TMR1CS ; Position sur le timer 1
- bsf STATUS,RP0 ; passer en banque 1
- bsf PIE1,TMR1IE ; autoriser interruptions timer 1
- bcf STATUS,RP0 ; repasser banque 0
- bsf INTCON,PEIE ; interruptions périphériques en service
- bsf INTCON,GIE ; interruptions en service
- clrf TMR1L ; effacer timer 1, 8 lsb
- clrf TMR1H ; effacer timer 1, 8 msb
- movlw 0x39 ; Nombre de passage à effectuer pour être le plus
- movwf compteur ; proche de 30 secondes
- timer
- bsf T1CON,TMR1ON ; mettre timer 1 en service
- ici goto ici
- start_line_CS1
- movlw 0xC2 ; Line 0
- movwf PORTD
- movlw 0x31 ; CS1 / Write
- movwf PORTB
- bcf PORTB, 4
- return
- start_line_CS2
- movlw 0xC2 ; Line 0
- movwf PORTD
- movlw 0x32 ; CS2 / Write
- movwf PORTB
- bcf PORTB, 4
- return
- ecran
- movlw 0x3F ; On place le repère tout en haut de l'ecran (63)
- movwf repere
- movlw 0xFE ; On part du premier pixel
- movwf pixel
- movlw 0x00 ; Partie haute
- movwf X
- btfsc degres, 7 ; Est-ce que la température est négative?
- goto negatif
- movlw 0x01
- btfsc demidegres, 7 ; Est-ce qu'on à X,5°C?
- addwf degres, f ; On arrondit au degrés supérieur
- positif
- movlw 0x0A ; On décale la valeur de 10°C pour passer d'une échelle -10/50
- addwf degres, f ; à 0/60
- comparaison
- movf repere, w
- xorwf degres, w ; Si la position du repère ne correspond pas à la valeur de la case
- btfss STATUS, 2
- goto movepixel ; Alors on passe au pixel suivant
- call setpage ; On selectionne la page
- call writepixel ; Et on inscrit la température
- movlw 0x3F
- andwf Y, w
- btfsc STATUS, 2 ;Fin d'écran ? Passage sur l'autre écran
- call change
- return
- change
- call reglage_CS1
- return
- negatif
- comf degres, f
- movlw 0x01
- addwf degres, f ; Complément à deux
- btfsc demidegres, 7
- addwf degres, f ; Arrondi
- goto positif
- movepixel
- bsf STATUS, 0 ; Pas de retenue
- rlf pixel, f ; Décalage du pixel
- movlw 0xFF
- bcf STATUS, 0
- xorwf pixel, w ; Dernière case de la plage X?
- btfsc STATUS, 2 ; On vérifie si l'opération a rendu 0
- goto addX
- moins
- decf repere, f ; On descend d'une case
- goto comparaison ; et on recommence
- addX
- incf X, f ; passage à la plage suivante
- movlw 0xFE
- movwf pixel ; plaçage en haut de la plage
- goto moins
- setpage
- movlw 0xB8
- movwf PORTD
- movf X, w
- addwf PORTD, f
- btfsc CS1, 0
- movlw 0x31
- btfss CS1, 0
- movlw 0x32
- movwf PORTB
- bcf PORTB, 4
- return
- setadress
- movlw 0x40
- movwf PORTD ;0
- movf Y, w
- addwf PORTD, f
- btfsc CS1, 0
- movlw 0x31
- btfss CS1, 0
- movlw 0x32
- movwf PORTB
- bcf PORTB, 4
- return
- writepixel
- movf pixel, w
- movwf PORTD
- btfsc CS1, 0
- movlw 0x35
- btfss CS1, 0
- movlw 0x36
- movwf PORTB
- bcf PORTB, 4
- incf Y, f
- call setadress
- movlw 0x0A
- subwf degres, f
- return
- reglage_CS1
- btfsc CS1, 0
- bcf CS1, 0
- btfss CS1, 0
- bsf CS1, 0
- movlw 0x00
- movwf Y
- call setadress ; On selectionne l'adresse
- return
- blanc
- movlw 0x09
- movwf X
- boucle
- movlw 0x41
- movwf efface
- decfsz X, f
- goto suite
- return
- suite
- call setpage
- call setadress
- suite2
- decfsz efface, f
- goto write
- goto boucle
- write
- movlw 0xFF
- movwf pixel
- call writepixel
- goto suite2
- end
|
Je ne sais pas comment combiner les deux codes pour qu'ils fonctionnent.
J'ai essayé de placer la séquence de lecture I2C juste après le lancement du timer (en la conservant dans une boucle afin que la capture se fasse constamment). Dès que l'interruption se déclenche normalement mes valeurs de buffer 1 et 2 sont copiés dans degrés et demidegrés et envoyés sur l'écran mais rien n'apparait.
Dans un deuxième essai, j'ai placé la séquence de lecture I2C dans le coin des interruptions juste avant l'appel de la fonction ecran. Mais là je n'ai plus de communication avec le capteur et une valeur est inscrite sur l'écran (c'est toujours la même et elle n'est pas cohérente avec la température actuelle).
Pour moi, le timer et l'I2C ont l'air de créer un conflit mais je ne sais pas comment contourner le problème.
Si vous avez des idées, je suis preneur.
Merci de m'avoir lu Message édité par Pingumaru le 07-10-2009 à 17:52:50
|