Bonjour,
Je voudrais réaliser une horloge/calendrier avec un pic16F876 câblé en maître et un DS1307 esclave avec le mode I²C. Je programme en assembleur et je fais la simulation sous proteus 7. Voici le schéma de mon horloge (QUARTZ de 4MHz utilisé).
Voici mon programme :
Voilà vous l’avez sans doute deviné, mon programme ne fonctionne pas, j’ai pas d’erreur a la compilation mais j’ai l’impression que l’adresse du DS1307 n’est pas convenablement transmise par le pic16F876 et donc le DS1307 n’envoit jamais de acknowledge et donc mon programme reste bloquer a cette étape. Je ne trouve pourtant pas d’erreur dans mon programme donc je souhaiterais avoir votre aide, merci d’avance pour vos réponses.Code:;***************************************************************************** ; Réalisation d'une montre lcd contrôlée par un PIC16876 * ; * ;***************************************************************************** ; * ; NOM: montrelcd * ; Date: 06/11/2013 * ; Version: 1.0 * ; Circuit: Proteus * ; Auteur: Traoré Sékou * ; * ;***************************************************************************** ; * ; Fichier requis: P16F876.inc * ; lcd_4b.inc * ; * ; * ;***************************************************************************** ; * ; Notes: Affichage lcd 4 bits * ; * ; * ; * ; * ;***************************************************************************** LIST p=16F876 ; Définition de processeur #include <p16F876.inc> ; fichier include #include <lcd_4b.inc> ; fichier include afficheur lcd __CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _PWRTE_ON & _WDT_OFF & _HS_OSC ;_CP_OFF Pas de protection ;_DEBUG_OFF RB6 et RB7 en utilisation normale ;_WRT_ENABLE_OFF Le programme ne peut pas écrire dans la flash ;_CPD_OFF Mémoire EEprom déprotégée ;_LVP_OFF RB3 en utilisation normale ; _BODEN_ON Reset tension en service ;_PWRTE_ON Démarrage temporisé ;_WDT_OFF Watchdog hors service ;_HS_OSC Oscillateur haute vitesse (4Mhz<F<20Mhz) ;***************************************************************************** ; ASSIGNATIONS SYSTEME * ;***************************************************************************** ; REGISTRE OPTION_REG (configuration) ; ----------------------------------- OPTIONVAL EQU B'10000000' ; RBPU b7 : 1= Résistance rappel +5V hors service ; REGISTRE INTCON (contrôle interruptions standard) ; ------------------------------------------------- INTCONVAL EQU B'00000000' ; REGISTRE PIE1 (contrôle interruptions périphériques) ; ---------------------------------------------------- PIE1VAL EQU B'00000000' ; REGISTRE ADCON1 (ANALOGIQUE/DIGITAL) ; ------------------------------------ ADCON1VAL EQU B'00000110' ; PORTA en mode digital ; DIRECTION DES PORTS I/O ; ----------------------- DIRPORTA EQU B'00000000' ; Direction PORTA DIRPORTB EQU B'00000001' ; Direction PORTB DIRPORTC EQU B'11111111' ; Port RC3/SCL et RC4/SDA en entrée ;***************************************************************************** ; DEFINE * ;***************************************************************************** ; exemple ; ------- #DEFINE LCD_RS PORTB,1 ; Broche RS de l'afficheur LCD reliée a la pin RB1 #DEFINE LCD_RW PORTB,2 ; Broche RW de l'afficheur LCD reliée a la pin RB2 #DEFINE LCD_E PORTB,3 ; Broche E de l'afficheur LCD reliée a la pin RB3 #DEFINE LCD_DATA PORTB ; LCD: Port ou est branche le bus de donnee ( bits 4 à 7 ) MSB IMPERATIF #DEFINE carry STATUS,C ; define carry ;***************************************************************************** ; MACRO * ;***************************************************************************** ; Changement de banques ; ---------------------- BANK0 macro ; passer en banque0 bcf STATUS,RP0 bcf STATUS,RP1 endm BANK1 macro ; passer en banque1 bsf STATUS,RP0 bcf STATUS,RP1 endm BANK2 macro ; passer en banque2 bcf STATUS,RP0 bsf STATUS,RP1 endm BANK3 macro ; passer en banque3 bsf STATUS,RP0 bsf STATUS,RP1 endm ;***************************************************************************** ; VARIABLES ZONE COMMUNE * ;***************************************************************************** ; Zone de 16 bytes ; ---------------- CBLOCK 0x70 ; Début de la zone (0x70 à 0x7F) w_temp : 1 ; Sauvegarde registre W status_temp : 1 ; sauvegarde registre STATUS FSR_temp : 1 ; sauvegarde FSR (si indirect en interrupt) PCLATH_temp : 1 ; sauvegarde PCLATH (si prog>2K) ;variable fichier lcd_b4.asm ;--------------------------- LCD_mode_set : 1 ; LCD_disp_cont : 1 ; DATA_TMP : 1 ; J : 1 ; LCD_curs_disp_shift : 1 ; LCD_func_set : 1 ; DATA_SWAP : 1 ; PORT_SAVE : 1 ; ;variable tempo q4mhz ;-------------------- temp1 : 1; temp2 : 2; temp3 : 1; ENDC ;***************************************************************************** ; VARIABLES BANQUE 1 * ;***************************************************************************** ; Zone de 80 bytes ; ---------------- CBLOCK 0xA0 ; Début de la zone (0xA0 à 0xEF) secondes : 1 ; minutes : 1 ; heures : 1 ; jour : 1 ; mois : 1 ; annee : 1 ; cmpt1 : 1 ; variable compteur pour read endc ; Fin de la zone ;***************************************************************************** ; DEMARRAGE SUR RESET * ;***************************************************************************** org 0x000 ; Adresse de départ après reset goto init ; Initialiser ; //////////////////////////////////////////////////////////////////////////// ; P R O G R A M M E ; //////////////////////////////////////////////////////////////////////////// ;***************************************************************************** ; INITIALISATIONS * ;***************************************************************************** init ; initialisation PORTS (banque 0 et 1) ; ------------------------------------ BANK0 ; sélectionner banque0 clrf PORTA ; Sorties PORTA à 0 clrf PORTB ; sorties PORTB à 0 bsf STATUS,RP0 ; passer en banque1 movlw ADCON1VAL ; PORTA en mode digital/analogique movwf ADCON1 ; écriture dans contrôle A/D movlw DIRPORTA ; Direction PORTA movwf TRISA ; écriture dans registre direction movlw DIRPORTB ; Direction PORTB movwf TRISB ; écriture dans registre direction movlw DIRPORTC ; Direction PORTC movwf TRISC ; écriture dans registre direction ; Registre d'options (banque 1) ; ----------------------------- movlw OPTIONVAL ; charger masque movwf OPTION_REG ; initialiser registre option ; registres interruptions (banque 1) ; ---------------------------------- movlw INTCONVAL ; charger valeur registre interruption movwf INTCON ; initialiser interruptions movlw PIE1VAL ; Initialiser registre movwf PIE1 ; interruptions périphériques 1 ;-------------------------------------------------------- ; CONFIGURATION MODULE MSSP * ;-------------------------------------------------------- ; SSPSTAT ;-------- BANK1 ; passer en banque 1 movlw B'10000000' ; movwf SSPSTAT ; b7 : SMP = 1 (100 kHz) ; b6 : CKE = 0 (pour bus I²C) ; SSPADD ;------- movlw D'9' ; Quartz de 4Mhz et fréquence de 100 kHz pour le I²C maître ; SSPADD = (4 000 0000 /(4*100 000))-1 = 9 movwf SSPADD ; Le PIC va donc travailler en I²C à la frequence de 100kHz (fréquence de travail du DS1307) ; SSPCON ;------- BANKSEL SSPCON; passer en banque 0 movlw B'00101000' ; b5 : SSPEN = 1 mettre le module MSSP en service ; b3 à b0 SSMPx = 1000 mode I²C maître : fréquence déterminée par le registre SSPADD movwf SSPCON; ; autoriser interruptions (banque 0) ; ---------------------------------- goto start ; programme principal #include <lcd_4b.asm> ; Inclusion des fonctions utilisées pour l'affichage LCD #include <q4mhz.asm> ; inclusion des fonctions de temporisations LCD ;***************************************************************************** ; SOUS-ROUTINE MODULE I²C MAITRE * ;***************************************************************************** I2C_idle BANKSEL SSPSTAT ; passer en banque 1 I2C_idle2 clrwdt ; effacer watchdog btfsc SSPSTAT,R_W ; tester si émission en cours goto I2C_idle2 ; oui, attendre I2C_idle3 clrwdt ; effacer watchdog movf SSPCON2,w ; charger registre SSPCON2 andlw 0x1F ; conserver ACKEN,RCEN,PEN,RSEN,et SEN btfss STATUS,Z ; tester si tous à zero (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_start call I2C_idle ; on attend que le bus I2C soit libre BANKSEL SSPCON2 ; passage en banque 1 bsf SSPCON2,SEN ; SEN = 1 (lancement d'une opération start) bcf STATUS,RP0 ; retour en banque 0 return ; I2C_write call I2C_idle ; on attend que le bus I2C soit prêt movwf SSPBUF ; return I2C_ACK_slave_to_master call I2C_idle ; on attend que le bus I2C soit prêt BANK1 ; passage en banque 1 I2C_ACK_slave_to_master0 btfsc SSPCON2,ACKSTAT ; tester bit ACKSTAT goto I2C_ACK_slave_to_master0 ; bit ACKSTAT = 1 acknowledge pas encore reçu bcf STATUS,RP0 ; retour en banque 0 return I2C_Repeated_Start call I2C_idle ; on attend que le bus I2C soit libre BANK1 ; passer en banque 1 bsf SSPCON2,RSEN ; RSEN = 1 (lancement d'une opération Repeated Start Condition) bcf STATUS,RP0 ; return I2C_read call I2C_idle ; on attend que le bus I2C soit libre BANK1 ; bsf SSPCON2,RCEN ; on lance la réception I2C_read2 btfsc SSPCON2,RCEN ; on teste si la reception est terminer (RCEN = 0) goto I2C_read2 ; non, on attend bcf STATUS,RP0 ; réception terminée on passe en banque 0 movf SSPBUF,w ; copie de la valeur reçue dans w return I2C_ACK_master_to_slave call I2C_idle ; on attend que le bus I2C soit prêt BANK1 ; passage en banque 1 bcf SSPCON2,ACKDT ; préparation de l'envoi d'un acknowledge bsf SSPCON2,ACKEN ; ACKEN = 1 (lancement d'une opération acknowledge) bcf STATUS,RP0 ; passage en banque return ; Not Acknowledge (maître vers esclave) ;-------------------------------------- I2C_NOACK call I2C_idle ; on attend que le bus I2C soit prêt BANK1 ; passage en banque 1 bsf SSPCON2,ACKDT ; preparation de l'envoi d'un not acknowledge bsf SSPCON2,ACKEN ; lancement de l'opération not acknowledge bcf STATUS,RP0 ; retour en banque 0 return I2C_stop call I2C_idle ; on attend que le bus I2C soit prêt BANK1 ; passage en banque 1 bsf SSPCON2,PEN ; lancement d'une opération stop bcf STATUS,RP0 ; retour en banque 0 return ;***************************************************************************** ; PROGRAMME PRINCIPAL * ;***************************************************************************** start clrwdt ; effacer watch dog call I2C_start ; envoyer start condition movlw B'11010000' ; 8 bits à ecrire (7 bits d'adresse + bit 0 Write) call I2C_write ; call I2C_ACK_slave_to_master ; attendre acknowledge du DS1307 movlw B'00000000' ; envoyer l'adresse des secondes call I2C_write ; au DS1307 call I2C_ACK_slave_to_master ; attendre acknowledge DS1307 call I2C_Repeated_Start ; envoyer un repeated start condition movlw B'11010001' ; envoyer adresse DS1307 (7 bits de poids fort) + bit 0 = Read call I2C_write ; call I2C_ACK_slave_to_master ; attendre acknowledge DS1307 movlw 0xA0 ; movwf FSR ; charger première adresse variable banque 1 (secondes) dans FSR bsf STATUS,RP0 ; passer en banque 1 (sortie d'un call, donc on était en banque 0) movlw .6 ; charger 6 dans cmpt1 movwf cmpt1 ; en effet on a 6 lectures à faire (s,min,h,jour,mois,annee) lecture call I2C_ACK_master_to_slave ; lire valeur envoyée au pic call I2C_read ; et mettre le contenu dans w movwf INDF ; envoyer la valeur lue dans la variable dont l'adresse se situe dans FSR incf FSR,f ; passer à la variable suivante decfsz cmpt1,f ; decrementer compteur 1 goto lecture ; non, pas 0 donc aller à la variable suivante call I2C_NOACK ; toutes les valeurs ont été lues donc arrêter lecture call I2C_stop ; loop clrwdt ; effacer watch dog goto loop ; boucler END ; directive fin de programme
-----