Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général sur le langage C !

Modérateur : Jérémy

16F887 et DS3231
venom
Avatar de l’utilisateur
Confirmé
Confirmé
Messages : 953
Âge : 38
Enregistré en : avril 2016
Localisation : Klyntar
Contact :

#1 Message par venom » mar. 26 mars 2019 06:39 lien vers la Data-Sheet : Cliquez ici

Bonjour,

Je continue dans ma quête pour la création d'une horloge. Je sme suis donc acheter le module DS3231 qui permet de donner l'heure en I2c.
Je me suis donc tourner dans la partie tuto du forum fantaspic pour y trouver mon bonheur. :langue:

J'ai donc suivi ce super tuto de Jérémy 8-) et j'ai essayé de l'adapter pour un 16F887, mais sous simulation je n'ai aucun résultat. J'essaie juste d'afficher l'heure sur un LCD mais rien ne se passe. L’écran reste a 00:00:00. :cry: J'ai pourtant trouver d'autres exemples sur internet qui font le travail. Mais mon code pas moyen. :mur:

Voici le code :

Code : Tout sélectionner

#define RTC_ADDR  0xD0                     // Adresse I²C de l'esclave ( DS3231)


// LCD module connections
sbit LCD_RS at RB0_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;

sbit LCD_RS_Direction at TRISB0_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connections


unsigned char heures, minutes, secondes;
char oldstate = 0;

// Prototypes
unsigned short Bcd2Dec(unsigned short decnum);
unsigned short Dec2Bcd(unsigned short decnum);

/****************************************************************************
* Fonction: Lire les données sur le RTC
* parametre d'entrée : adresse du registre à lire
* parametre de sortie : valeur lue dans le registre
**********************************************************************************/
unsigned char RTC_Read(unsigned char addr){
  unsigned char value;                     // Déclaration variable temporaire

  I2C1_Start();                            // Début de l'I²C
  I2C1_Wr(RTC_ADDR);                       // Adresse du RTC ( 0xD0 cf datasheet)
  I2C1_Wr(addr);                           // adresse du registre à lire
  I2C1_Start();                            // On répète le signal de départ
  I2C1_Wr(RTC_ADDR);                       // Adresse du DS1307

  value = I2C1_Rd(0);                      // lecture et enregistrement de la valeur le 0=pour no ACK
  I2C1_Stop();                             // Arrêt de l'I²C

  return value;                            // On retourne la valeur lue
}

/**************************************************************************************************
* Fonction: Ecrire les données sur le DS1307
* parametre d'entrée : adresse du registre à ecrire + valeur à y mettre
**************************************************************************************************/
void RTC_Write(unsigned char addr, unsigned char value){
  I2C1_Start();                            // Début de l'I²C
  I2C1_Wr(RTC_ADDR);                       // Adresse du RTC ( 0xD0 cf datasheet)
  I2C1_Wr(addr);                           // adresse du registre à écrire
  I2C1_Wr(value);                          // On écrit la valeur dans le registre
  I2C1_Stop();                             // Arrêt de l'I²C
}

/**************************************************************************************************
* Fonction: Ecrire le Groupe Date Heure sur appui du BP
* parametre d'entrée : Les 7 valeurs du GDH à initialiser
**************************************************************************************************/
void Ecrire_GDH (unsigned char heures , unsigned char minutes, unsigned char secondes){

  I2C1_Start();                            // Début de l'I²C
  I2C1_Wr(RTC_ADDR);                       // Adresse du RTC ( 0xD0 cf datasheet)
  I2C1_Wr(0);                              // Met le pointeur à cette adresse ( N° registre)

  secondes = Dec2Bcd(secondes);            // Conversion de décimal en BCD pour le RTC
  I2C1_Wr(secondes);                       // On écrit la valeur dans le registre des secondes
  minutes = Dec2Bcd(minutes);              // Après écriture la valeur du pointeur du registre est incrémenter automatiquement
  I2C1_Wr(minutes);                        // On peut enchainer directement avec la prochaine valeur
  heures = Dec2Bcd(heures);                // etc ... toutes à la suite.
  I2C1_Wr(heures);

  I2C1_Stop();                             // Arrêt de l'I²C
}

/**************************************************************************************************
* Fonction: Lit le Groupe Date Heure sur le RTC pour mettre à jour l'affichage
**************************************************************************************************/
void Lecture_GDH(){

  I2C1_Start();                            // Début de l'I²C
  I2C1_Wr(RTC_ADDR);                       // Adresse du RTC ( 0xD0 cf datasheet)
  I2C1_Wr(0);                              // lecture à cette adresse ( N° registre)
  I2C1_Repeated_Start();                   // On répète le signal de départ
  I2C1_Wr(RTC_ADDR+1);                     // Adresse du DS1307 (1=lire / 0=ecrire)

  secondes = I2C1_Rd(1);                   // Lecture et enregistrement de la valeur
  secondes = Bcd2Dec(secondes);            // Conversion de BCD en décimal pour l'afficheur
  minutes = I2C1_Rd(1);
  minutes = Bcd2Dec(minutes);
  heures = I2C1_Rd(1);
  heures = Bcd2Dec(heures);

  I2C1_Stop();                             // Arrêt de l'I²C
}

/*##################################################################################
##########################    PROGRAMME PRINCIPAL    ###############################
##################################################################################*/
void main(){
  OSCCON = 0b01110000;                     // configuration OSCCON interne 8mhz
                                           // 0b01110000 oscillateur 8 Mhz
                                           // 0b01101000 oscillateur 4 Mhz
                                           // 0b01011000 oscillateur 2 Mhz
                                           // 0b01001000 oscillateur 1 Mhz
                                           // 0b00111000 oscillateur 500 Khz
                                           // 0b00101000 oscillateur 250 Khz
                                           // 0b00011000 oscillateur 125 Khz
                                           // 0b00001000 oscillateur 31 kHz

  while(OSCCON.HTS==0);                    // boucle en attendant de voir le flag à 1
    
    
  ANSEL  
= 0;                              // Configure AN pins as digital I/O
  ANSELH = 0;
  C1ON_bit = 0;                            // Disable comparators
  C2ON_bit = 0;

  TRISA0_bit = 1;                          // Met RA0 en entrée pour le BP.
                                           // Utilisé pour initialisé l'horloge avec une valeur enregistrée

  I2C1_Init(100000);                       // Initialise le BUS I2C
  
  Lcd_Init
();                              // Initialise le Lcd
  Lcd_Cmd(_LCD_CLEAR);                     // Efface écran
  Lcd_Cmd(_LCD_CURSOR_OFF);                // Curseur off

  Delay_ms(3000);                          // pause 3 sec

  Lcd_Cmd(_LCD_CLEAR);                     // Efface l'écran
  
  LCD_Out
(1,1,"DS3231 Clock :");           // le 20 c'est pour l'année 20xx
    
  LCD_Out
(2,1,"Heure:");                   // On écrit la matrice du texte statique
  LCD_Chr(2,11,':');
  LCD_Chr(2,14,':');


/*##################################################################################
############################    BOUCLE INFINIE    ##################################
##################################################################################*/
  while(1){
      if (Button(&PORTA, 0, 1, 0))oldstate = 1;  // Anti-rebond
      if (oldstate && Button(&PORTA, 0, 1, 1)) { // Si le BP est appuyé on envoi le GDH suivant
         Ecrire_GDH( 23,  59,  50);              //heure: min: sec
         oldstate = 0;                           // mise à 0 du flag
       }

      Lecture_GDH();                             // On va lire notre DS1307

      Lcd_Chr(2,9, (heures / 10)   + 48);        // Deuxième lignes 9iéme caractère dizaine des heures
      Lcd_Chr(2,10, (heures % 10)   + 48);       // Unité des heures
      Lcd_Chr(2,12, (minutes / 10) + 48);
      Lcd_Chr(2,13, (minutes % 10) + 48);
      Lcd_Chr(2,15, (secondes / 10) + 48);
      Lcd_Chr(2,16, (secondes % 10) + 48);

      Delay_mS(10);                              // pause de 10ms
   }


Si une ame charitable serait me dire ou j'ai fauté ? :oops:
D'avance merci. Après j'ai "bêtement" copier les routines de Jérémy c'est peut être différant sur un DS3231 qu'un DS1307 ?

Ps: J'utilise l'oscillateur interne a 8Mhz. Voici mon config Mikroc au cas ou :
Sans titre.png








@++
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Mon site web
Mon discord : venom#4888

16F887 et DS3231
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#2 Message par Jérémy » mar. 26 mars 2019 07:34 lien vers la Data-Sheet : Cliquez ici

Bonjour Venom ,

Voici une piste pour débuter car j'ai regardé vite fait avec le café ce matin !

L'adresse I2C n'est pas 0xD0 mais 0x68 . L'adresse est sur 7 bits , car le dernier bit est le R/W . 0 pour lire , 1 pour écrire !

Vérifie ton oscillateur avec un petit clignotement de led si possible.
Vérifie les routines de l'affichage de l'écran et le BP ( genre tu affiche un truc en appuyant sur le BP). histoire d'être bien sur .

J'essaie de regarder plus tard dans la journée

@+
C'est en faisant des erreurs, que l'on apprend le mieux !!!

16F887 et DS3231
Gérard
Avatar de l’utilisateur
Expert
Expert
Messages : 1640
Âge : 65
Enregistré en : septembre 2015
Localisation : Alsace - Haut-Rhin

#3 Message par Gérard » mar. 26 mars 2019 08:24 lien vers la Data-Sheet : Cliquez ici

Bonjour,

Je ne suis pas du même avis.
Pour lire $D0, pour écrire $D1.
Le 18/04/19 je suis devenu papy de jumeaux, le 01/09/23 une petite cousine des jumeaux est née.

16F887 et DS3231
Claudius
Avatar de l’utilisateur
Passioné
Passioné
Messages : 260
Âge : 69
Enregistré en : septembre 2015
Localisation : ELANCOURT (78 - YVELINES)
Contact :

#4 Message par Claudius » mar. 26 mars 2019 09:10 lien vers la Data-Sheet : Cliquez ici

Bonjour,

Sauf erreur de ma part, c'est plutôt $D0 pour écrire (R/W=0) et $D1 pour lire (R/W=1) - cf. Datasheet - DS3231 - pages 16 et 17

ScreenClip-DS3231-A.jpg

ScreenClip-DS3231-B.jpg

- The slave address byte contains the 7-bit DS3231 address, which is 1101000, followed by the direction bit (R/W), which is 0 for a write.
- The slave address byte contains the 7-bit DS3231 address, which is 1101000, followed by the direction bit (R/W), which is 1 for a read.
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.

16F887 et DS3231
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#5 Message par paulfjujo » mar. 26 mars 2019 09:13 lien vers la Data-Sheet : Cliquez ici

bonjour à tous,






:sifflotte: oui et non ...

car il faut ecrire avant de lire
on rajoute 1 à l'adresse de base , pour LIRE
donc 0xD0 pour ecrire et 0xD1 pour lire

Code : Tout sélectionner

#define DS3231_ADDR 0xD0 // RTC DS3231 + 24C32

void read_all_DS3231(void)      // I2C read subroutine
{


  I2C1_Start();
  I2C1_Wr(DS3231_ADDR);   
  I2C1_Wr
(0); // // start from word at address (REG0)
  I2C1_Repeated_Start();
  I2C1_Wr(DS3231_ADDR+1);
  second=I2C1_Rd(1);
   minute=I2C1_Rd(1);
    heure=I2C1_Rd(1);
     jS=I2C1_Rd(1);
          if (jS>6) jS=0;
      jour=I2C1_Rd(1);
       mois=I2C1_Rd(1);
        Annee=I2C1_Rd(0);
  I2C1_Stop();
 
Aide toi, le ciel ou FantasPic t'aidera

16F887 et DS3231
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#6 Message par Jérémy » mar. 26 mars 2019 09:16 lien vers la Data-Sheet : Cliquez ici

Gérard a écrit :Source du message Je ne suis pas du même avis.
Pour lire $D0, pour écrire $D1.


Oui je me suis mal exprimé ! Il faut bien envoyé 0xD0 ou 0xD1 , mais en sachant que le dernier bit est le R/W . Ce petit détail peu parfaois porté à confusion :mur:
C'est en faisant des erreurs, que l'on apprend le mieux !!!

16F887 et DS3231
venom
Avatar de l’utilisateur
Confirmé
Confirmé
Messages : 953
Âge : 38
Enregistré en : avril 2016
Localisation : Klyntar
Contact :

#7 Message par venom » mar. 26 mars 2019 12:24 lien vers la Data-Sheet : Cliquez ici

Désolé mais je dois retenir quoi de vos réponses ? :? :-D d'après Paul il faut écrire avant de lire. Donc j'écris l'heure que je souhaite voir au démarrage c'est sa ? Désolé de mon incompétence avec le ds3231 oops

@paul ta procédure c'est pour lire c'est sa ?






@++
Mon site web
Mon discord : venom#4888

16F887 et DS3231
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#8 Message par paulfjujo » mar. 26 mars 2019 12:37 lien vers la Data-Sheet : Cliquez ici

venom a écrit :..
... ta procédure c'est pour lire c'est sa ?



oui
READ ALL
lire tous les registres DS3231

l'ecriture c'est pour s'orienter sur le bon device ( equipement)
pour pouvoir apres coup lire le ou les registres
Aide toi, le ciel ou FantasPic t'aidera

16F887 et DS3231
Claudius
Avatar de l’utilisateur
Passioné
Passioné
Messages : 260
Âge : 69
Enregistré en : septembre 2015
Localisation : ELANCOURT (78 - YVELINES)
Contact :

#9 Message par Claudius » mar. 26 mars 2019 12:45 lien vers la Data-Sheet : Cliquez ici

Nous sommes tous d'accord @ notion d'adresse d'un périphérique I2C sur 8 bits voire parfois 10 bits qui, par définition inclut le bit R/W.
Le bit R/W n'étant là que pour indiquer le sens de l'échange avec un ACK présenté par le slave qui se reconnait pour continuer l'échange avec notamment la prise du bus dans le cas d'une lecture à l'initiative du maître

Cf. l'excellente présentation et synthèse : Le bus I²C

16F887 et DS3231
Gérard
Avatar de l’utilisateur
Expert
Expert
Messages : 1640
Âge : 65
Enregistré en : septembre 2015
Localisation : Alsace - Haut-Rhin

#10 Message par Gérard » mar. 26 mars 2019 13:44 lien vers la Data-Sheet : Cliquez ici

Regarde ici, au post #7, c'est écrit en Basic, ça te montrera comment faire.
Le 18/04/19 je suis devenu papy de jumeaux, le 01/09/23 une petite cousine des jumeaux est née.


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 40 invités