Pic16f877A : Incompatibilité I2C / Timer / Ecran

Pic16f877A : Incompatibilité I2C / Timer / Ecran - ASM - Programmation

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)
 

Code :
  1. org 0x00
  2. goto debut
  3. org 0x04
  4. debut
  5. bsf STATUS,RP0    ; passer en banque 1
  6. bsf TRISC,3    ; SCL en entrée (mis par défaut sur un reset)
  7. bsf TRISC,4    ; SDA en entrée (idem)
  8. movlw 0x80     ; slew rate control en service, mode I²C  ======================100kHZ SLEW RATE CONTROL à 1=======================
  9. movwf SSPSTAT    ; dans SSPSTAT
  10. movlw 0x09     ; valeur de recharge du BRG =====================================4MHz / (100KHz * 4) - 1=============================
  11. movwf SSPADD    ; dans registre de recharge
  12. bcf STATUS,RP0    ; repasser banque 0
  13. movlw 0x38     ; module MSSP en service en mode I²C master
  14. movwf SSPCON    ; dans registre de contrôle
  15. call I2C_start1   ; Start
  16. call I2C_start1   ; Start
  17. call I2C_adress
  18. call I2C_check
  19. call I2C_send_config ; Début de config
  20. call I2C_check   ; Réponse
  21. call I2C_send_conf  ; Suite config
  22. call I2C_check   ; Réponse
  23. call I2C_stop2
  24. call I2C_start1   ; Start
  25. call I2C_start1   ; Start
  26. call I2C_adress   ; Appel
  27. call I2C_check   ; Réponse
  28. call I2C_send_start  ; Début de conversion de la température EE
  29. call I2C_check   ; Réponse
  30. call I2C_stop2   ; Fin
  31. ici
  32. call I2C_start1   ; Start
  33. call I2C_start1   ; Start
  34. call I2C_adress   ; Appel du capteur
  35. call I2C_check   ; Réponse du capteur
  36. call I2C_send_read  ; Lecture de la température
  37. call I2C_check   ; Réponse du capteur
  38. call I2C_repeatstart  ; ReStart
  39. call I2C_adress2  ; Appel
  40. call I2C_check   ; Réponse
  41. call I2C_reade   ; Réception des données du capteur
  42. movf SSPBUF, w   ; Stockage des degres
  43. movlw buffer1
  44. call I2C_ACK_MASTER               ; Autorise l'esclave à poursuivre
  45. call I2C_reade
  46. movf SSPBUF, w                             ;Stockage des demidegres
  47. movlw buffer2
  48. call I2C_NOACK   ; Fin de réception
  49. call I2C_stop2   ; Stop
  50. goto ici
  51. I2C_idle      ; Sous routine contrôlant la présence d'une action en cours
  52. BANKSEL SSPSTAT   ; passer en banque 1
  53. I2C_idle2
  54. btfsc SSPSTAT,R_W   ; tester si émission en cours
  55. goto I2C_idle2    ; oui, attendre
  56. I2C_idle3
  57. movf SSPCON2,w    ; charger registre SSPCON2
  58. andlw 0x1F     ; conserver ACKEN,RCEN,PEN,RSEN,et SEN
  59. btfss STATUS,Z    ; tester si tous à 0 (aucune opération en cours)
  60. goto I2C_idle3    ; non, attendre
  61. bcf STATUS,RP0    ; repasser en banque 0
  62. return      ; rien en cours, on peut sortir
  63. I2C_start1     ; Sous routine lançant le bit Start
  64. ;call I2C_idle    ; attendre fin de l’opération précédente(voir plus haut)
  65. bsf STATUS,RP0    ; passer en banque 1
  66. bsf SSPCON2,SEN   ; lancer start-condition
  67. bcf STATUS,RP0    ; repasser en banque 0
  68. return      ; retour
  69. I2C_adress     ; Mode écriture
  70. call I2C_idle    ; attendre fin de l’opération précédente
  71. movlw 0x90     ; charger adresse esclave (b7 à b1) avec b0 = 0
  72. movwf SSPBUF    ; lancer l’émission de l’adresse en mode écriture
  73. return      ; et retour
  74. I2C_stop2     ; Stop
  75. bsf STATUS,RP0    ; passer en banque 1
  76. bsf SSPCON2,PEN   ; lancer le stop-condition
  77. I2C_start2
  78. ;clrwdt      ; effacer watchdog
  79. btfsc SSPCON2,PEN   ; stop-condition terminé ?
  80. goto I2C_start2   ; non, attendre
  81. bcf STATUS,RP0    ; oui, repasser en banque 0
  82. return
  83. I2C_send_start     ; Autoriser la conversion de température
  84. call I2C_idle    ; attendre fin de l’opération précédente
  85. movlw 0xEE     ; charger octet à envoyer
  86. movwf SSPBUF    ; lancer l’écriture de l’octet
  87. return      ; et retour
  88. I2C_check     ; Surveillance du ACK provenant de l'esclave
  89. call I2C_idle    ; attendre fin de l’opération précédente
  90. bsf STATUS,RP0    ; passer en banque 1
  91. btfsc SSPCON2,ACKSTAT  ; tester ACK reçu
  92. goto errore    ; pas reçu, traiter erreur
  93. bcf STATUS,RP0
  94. return
  95. errore
  96. bcf STATUS,RP0
  97. call I2C_stop2
  98. return
  99. I2C_send_01     ; Autoriser la conversion de température
  100. call I2C_idle    ; attendre fin de l’opération précédente
  101. movlw 0x01    ; charger octet à envoyer
  102. movwf SSPBUF    ; lancer l’écriture de l’octet
  103. return      ; et retour
  104. I2C_send_config    ; Lecture de la conversion
  105. call I2C_idle    ; attendre fin de l’opération précédente
  106. movlw 0xAC     ; charger octet à envoyer
  107. movwf SSPBUF    ; lancer l’écriture de l’octet
  108. return      ; et retour
  109. I2C_send_conf    ; Lecture de la conversion
  110. call I2C_idle    ; attendre fin de l’opération précédente
  111. movlw 0x00    ; charger octet à envoyer
  112. movwf SSPBUF    ; lancer l’écriture de l’octet
  113. return      ; et retour
  114. I2C_repeatstart    ; Repeated Start
  115. call I2C_idle    ; attendre fin de l’opération précédente
  116. bsf STATUS,RP0    ; passer en banque 1
  117. bsf SSPCON2,RSEN   ; lancer le repeated start-condition
  118. bcf STATUS,RP0    ; repasser en banque 0
  119. return      ; retour
  120. I2C_reade     ; Reception des données par le maître
  121. call I2C_idle    ; attendre fin de l’opération précédente
  122. bsf STATUS,RP0    ; passer banque 1
  123. bsf SSPCON2,RCEN  ; lancer la réception
  124. bcf STATUS,RP0    ; repasser banque 0
  125. return      ; et retour
  126. I2C_NOACK      ; Lancer l'ack provenant du maitre cloturant une reception
  127. call I2C_idle    ; attendre fin de l’opération précédente
  128. bsf STATUS,RP0    ; passer banque 1
  129. bsf SSPCON2,ACKDT   ; le bit qui sera envoyé vaudra « 1 »
  130. bsf SSPCON2,ACKEN   ; lancer l’acknowledge (= ACKDT = 1 = N0ACK)
  131. bcf STATUS,RP0    ; repasser banque 0
  132. return      ; et retour
  133. I2C_ACK_MASTER    ; Lancer l'ack provenant du maitre
  134. call I2C_idle    ; attendre fin de l’opération précédente
  135. bsf STATUS,RP0    ; passer banque 1
  136. bcf SSPCON2,ACKDT   ; le bit qui sera envoyé vaudra « 1 »
  137. bsf SSPCON2,ACKEN   ; lancer l’acknowledge
  138. bcf STATUS,RP0    ; repasser banque 0
  139. return      ; et retour
  140. I2C_send_read    ; Lecture de la conversion
  141. call I2C_idle    ; attendre fin de l’opération précédente
  142. movlw 0xAA     ; charger octet à envoyer
  143. movwf SSPBUF    ; lancer l’écriture de l’octet
  144. return      ; et retour
  145. I2C_adress2     ; Mode lecture
  146. call I2C_idle    ; attendre fin de l’opération précédente
  147. movlw 0x91     ; charger adresse esclave (b7 à b1) avec b0 = 1
  148. movwf SSPBUF    ; lancer l’émission de l’adresse en mode lecture
  149. return      ; et retour
  150.          
  151.             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 :
  1. #include <p16f877A.inc>
  2. compteur  EQU 0x20  ; Variable parametrant le nombre de répétition du TIMER1 pour arriver à 30 sec
  3. dizaine  EQU 0x21  ; Variable récuperant la valeur de la roue des dizaines
  4. unite   EQU 0x22  ; celle de la roue des unités
  5. cpt   EQU 0x23  ; Second compteur représentant la durée entre chaque capture
  6. save   EQU 0x24  ; Sauvegarde la valeur du compteur
  7. degres   EQU 0x25  ; Récupère la valeur en degrés venant du capteur
  8. demidegres  EQU 0x26  ; Récupère la présence ou non d'un demi-degrés
  9. echec   EQU 0x27  ; Identifie l'opération où le ACK n'a pas été reçu
  10. repere   EQU 0x28  ; Repère se situant en haut de l'écran
  11. X    EQU 0x29  ; plage d'adresse en hauteur (0 à 7)
  12. Y    EQU 0x2A  ; plage d'adresse en longueur (0 à 63)
  13. pixel   EQU 0x2B  ; permet l'inscription d'un pixel sur l'ecran
  14. CS1   EQU 0x2C  ; 1 = CS1 / 0 = CS2
  15. efface  EQU 0x2D
  16.              org 0x00
  17. goto debut
  18. org 0x04
  19. bcf PIR1, TMR1IF   ; Remet le flag d'overflow à 0
  20. decfsz compteur, f   ; Décrémente le compteur
  21. retfie     ; Retour d'interruption
  22. movlw 0x39    ; Nombre de passage à effectuer pour être le plus...
  23. movwf compteur    ; ...proche de 30 secondes / On relance le timer sur 30 secondes...
  24.              movlw 0x10
  25.              movwf degres
  26.              movlw 0x00
  27.              movwf demidegres
  28.              call ecran
  29. retfie
  30. debut
  31. init_lcd
  32. bsf STATUS, RP0   ; passer en banque 1
  33. clrf TRISD    ; PORTD en sortie
  34. clrf TRISB    ; PORTB en sortie
  35. bcf STATUS, RP0   ; passer en banque 0
  36. movlw 0x3F
  37. movwf PORTD    ; ON
  38. movlw 0x32    ; CS2  1ère partie de l'écran
  39. movwf PORTB
  40. bcf PORTB, 4                                  ; Chute de l'enable, envoie des données
  41. call start_line_CS2                           ; Position de la ligne de départ
  42. call blanc                                       ;Nettoyage de l'écran
  43. movlw 0x3F
  44. movwf PORTD    ; ON
  45. movlw 0x31    ; CS1 2nde partie de l'écran
  46. movwf PORTB
  47. bcf PORTB, 4
  48. movlw 0x01
  49. movwf CS1
  50. call start_line_CS1
  51. call blanc
  52. movlw 0x00
  53. movwf CS1
  54. movlw 0x0A
  55. movwf degres
  56. movlw 0x00
  57. movwf Y
  58. call setadress   ; On selectionne l'adresse
  59. debut2
  60. bsf T1CON, T1CKPS1  ; Prédiviseur...
  61. bsf T1CON, T1CKPS0  ; ...à 8
  62. bcf T1CON, TMR1CS  ; Position sur le timer 1
  63. bsf STATUS,RP0    ; passer en banque 1
  64. bsf PIE1,TMR1IE   ; autoriser interruptions timer 1
  65. bcf STATUS,RP0    ; repasser banque 0
  66. bsf INTCON,PEIE   ; interruptions périphériques en service
  67. bsf INTCON,GIE    ; interruptions en service
  68. clrf TMR1L     ; effacer timer 1, 8 lsb
  69. clrf TMR1H     ; effacer timer 1, 8 msb
  70. movlw 0x39    ; Nombre de passage à effectuer pour être le plus
  71. movwf compteur    ; proche de 30 secondes
  72. timer
  73. bsf T1CON,TMR1ON   ; mettre timer 1 en service
  74. ici goto ici
  75. start_line_CS1
  76. movlw 0xC2    ; Line 0
  77. movwf PORTD
  78. movlw 0x31    ; CS1 / Write
  79. movwf PORTB
  80. bcf PORTB, 4
  81. return
  82. start_line_CS2
  83. movlw 0xC2    ; Line 0
  84. movwf PORTD
  85. movlw 0x32    ; CS2 / Write
  86. movwf PORTB
  87. bcf PORTB, 4
  88. return
  89. ecran
  90. movlw 0x3F    ; On place le repère tout en haut de l'ecran (63)
  91. movwf repere
  92. movlw 0xFE   ; On part du premier pixel
  93. movwf pixel
  94. movlw 0x00    ; Partie haute
  95. movwf X
  96. btfsc degres, 7   ; Est-ce que la température est négative?
  97. goto negatif
  98. movlw 0x01
  99. btfsc demidegres, 7  ; Est-ce qu'on à X,5°C?
  100. addwf degres, f   ; On arrondit au degrés supérieur
  101. positif
  102. movlw 0x0A    ; On décale la valeur de 10°C pour passer d'une échelle -10/50
  103. addwf degres, f   ; à 0/60
  104. comparaison
  105. movf repere, w
  106. xorwf degres, w   ; Si la position du repère ne correspond pas à la valeur de la case
  107. btfss STATUS, 2
  108. goto movepixel   ; Alors on passe au pixel suivant
  109. call setpage   ; On selectionne la page
  110. call writepixel   ; Et on inscrit la température
  111. movlw 0x3F
  112. andwf Y, w
  113. btfsc STATUS, 2                             ;Fin d'écran ? Passage sur l'autre écran
  114. call change
  115. return
  116. change
  117. call reglage_CS1
  118. return
  119. negatif
  120. comf degres, f
  121. movlw 0x01
  122. addwf degres, f   ; Complément à deux
  123. btfsc demidegres, 7
  124. addwf degres, f   ; Arrondi
  125. goto positif
  126. movepixel
  127. bsf STATUS, 0   ; Pas de retenue
  128. rlf pixel, f   ; Décalage du pixel
  129. movlw 0xFF
  130. bcf STATUS, 0
  131. xorwf pixel, w   ; Dernière case de la plage X?
  132. btfsc STATUS, 2   ; On vérifie si l'opération a rendu 0
  133. goto addX
  134. moins
  135. decf repere, f    ; On descend d'une case
  136. goto comparaison  ; et on recommence
  137. addX
  138. incf X, f    ; passage à la plage suivante
  139. movlw 0xFE
  140. movwf pixel    ; plaçage en haut de la plage
  141. goto moins
  142. setpage
  143. movlw 0xB8
  144. movwf PORTD
  145. movf X, w
  146. addwf PORTD, f
  147. btfsc CS1, 0
  148. movlw 0x31
  149. btfss CS1, 0
  150. movlw 0x32
  151. movwf PORTB
  152. bcf PORTB, 4
  153. return
  154. setadress
  155. movlw 0x40
  156. movwf PORTD    ;0
  157. movf Y, w
  158. addwf PORTD, f
  159. btfsc CS1, 0
  160. movlw 0x31
  161. btfss CS1, 0
  162. movlw 0x32
  163. movwf PORTB
  164. bcf PORTB, 4
  165. return
  166. writepixel
  167. movf pixel, w
  168. movwf PORTD
  169. btfsc CS1, 0
  170. movlw 0x35
  171. btfss CS1, 0
  172. movlw 0x36
  173. movwf PORTB
  174. bcf PORTB, 4
  175. incf Y, f
  176. call setadress
  177. movlw 0x0A
  178. subwf degres, f
  179. return
  180. reglage_CS1
  181. btfsc CS1, 0
  182. bcf CS1, 0
  183. btfss CS1, 0
  184. bsf CS1, 0
  185. movlw 0x00
  186. movwf Y
  187. call setadress   ; On selectionne l'adresse
  188. return
  189. blanc
  190. movlw 0x09
  191. movwf X
  192. boucle
  193. movlw 0x41
  194. movwf efface
  195. decfsz X, f
  196. goto suite
  197. return
  198. suite
  199. call setpage
  200. call setadress
  201. suite2
  202. decfsz efface, f
  203. goto write
  204. goto boucle
  205. write
  206. movlw 0xFF
  207. movwf pixel
  208. call writepixel
  209. goto suite2
  210. 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  :jap:


Message édité par Pingumaru le 07-10-2009 à 17:52:50
Reply

Marsh Posté le 07-10-2009 à 17:50:53   

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed