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 »
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
Marsh Posté le 07-10-2009 à 17:50:53
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)
Bizarrement pour qu'il y ait communication avec le capteur, je dois lancer deux fois le bit de start.
Et celui pour l'écran
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