Bonjour à tous,
Aujourd'hui nous allons parlé du module RTC2_click de Mikroelekronika .
Ce module est un calendrier qui permet de connaitre la date et l'heure en temps réel.
Il utilise le driver DS1307 très répandu.
Nous allons voir comment communiquer avec ce driver et dégrossir ses fonctions principales. ( Data-sheet du DS1307 )
Pour faire ce Tuto je me suis inspiré de l'exemple de MikroE, que vous pouvez retrouver ici
Exemple d'utilisation du moduleRTC2_click
Schéma de connexion du module
Configuration :
- PIC18F45K22
- IDE : MikroC Pro for PIC Version 6.6.2
- Compilateur : Mikro prog suite fo PIC V 2.32
- Plaque Easy PIC V7
- RTC2_click en mode I²C
- LCD 16x2 en mode 4bits
1/ Préliminaire
Le module RTC permet d'avoir l'heure et la date n'importe où sur vos projets ! .
Associer à une pile lithium, il sauvegarde la date et l'heure durant plusieurs mois/année même en cas de coupure de courant. Il est cadencé par un quartz externe calé sur une certaine fréquence(32.768KHz).
Durant ce tutoriel nous allons voir comment écrire et lire sur ce module. Nous allons ainsi pouvoir régler le Groupe-Date-Heure (GDH) en écrivant dans les registres du module, et bien évidemment récupérer le GDH fournit par le RTC pour se servir des informations ( afficher l'heure par exemple).
Le DS1307 offre également une sortie qui peut-être configurée en sortie logique ou en sortie de générateur de signal carré(Square-Wave). Cette sortie est relativement peu utilisée. Nous ne verrons pas cette fonction pour le moment.
2/ Initialisation de l'heure
Sans pile de sauvegarde , les registres sont tous à 0 au démarrage . Il conviendra donc de les initialiser.
Cela se fera par l'appui sur un BP (branché sur RA0).
Cette initialisation va simplement injectée dans les registres les valeurs que nous aurons préalablement configurées.
Une fois initialisé et le fonctionnement autorisé, le DS1307 incrémentera les valeurs automatiquement. elle est pas belle la vie ! :D
3/Récupération des infos
Le DS1307 une fois initialisé va nous fournir la date et l'heure ( l'unité la plus petite est la seconde). Il va donc nous falloir lire ses registres où sont stockés les valeurs du GDH , les enregistrées et enfin les affichées ou faire des calculs de durée par exemple.
Dans notre exemple nous afficherons la date et l'heure sur un écran LCD .
Attention!! La seule petite difficulté que j'ai rencontré c'est sur le fait que le module communique avec des valeurs en hexa ( BCD). Il va donc falloir convertir les données de décimal à hexa dans un sens , et de hexa à décimal dans l'autre .
pour ce faire nous utiliserons la bibliothèque conversions et les fonctions qui vont bien :
Bcd2Dec() et Dec2Bcd()
Donc avant chaque écriture et lecture nous devrons convertir les données.
Comme d'habitude , si vous avez des questions, remarques, propositions etc ..... n’hésitez pas à poster a la suite de ce sujet !
Voici le programme commenté ligne par ligne :
Code : Tout sélectionner
/*----------------------------------------------------------------------------------
- Tutoriel Module RTC 2 click sur plaque easyPic 7
- fait par Jérémy le 01/11/2015 sur www.FantasPic.fr
- Pic 18F45K22 avec MikroC 6.6.2
- Fosc : 8Mhz
----------------------------------------------------------------------------------*/
#define RTC_ADDR 0xD0 // Adresse I²C de l'esclave ( DS1307)
// Lcd module connections
sbit LCD_RS at LATB4_bit;
sbit LCD_EN at LATB5_bit;
sbit LCD_D4 at LATB0_bit;
sbit LCD_D5 at LATB1_bit;
sbit LCD_D6 at LATB2_bit;
sbit LCD_D7 at LATB3_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// Constantes
unsigned char txt1[]=" RTC2 click sur ";
unsigned char txt2[]="www.FantasPic.fr";
// Variables
unsigned char heures, minutes, secondes, jour, n_jour, mois, annee, D_secondes, U_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 ,
unsigned char jour,unsigned char n_jour, unsigned char mois,unsigned char annee){
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);
jour = Dec2Bcd(jour);
I2C1_Wr(jour);
n_jour = Dec2Bcd(n_jour);
I2C1_Wr(n_jour);
mois = Dec2Bcd(mois);
I2C1_Wr(mois);
annee = Dec2Bcd(annee);
I2C1_Wr(annee);
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);
jour = I2C1_Rd(1);
jour = Bcd2Dec(jour);
n_jour = I2C1_Rd(1);
n_jour = Bcd2Dec(n_jour);
mois = I2C1_Rd(1);
mois = Bcd2Dec(mois);
annee = I2C1_Rd(0);
annee = Bcd2Dec(annee);
I2C1_Stop(); // Arrêt de l'I²C
}
/*##################################################################################
########################## PROGRAMME PRINCIPAL ###############################
##################################################################################*/
void main(){
ANSELA = 0; // Configure le PORTA en digital
ANSELB = 0; // Configure le PORTB en digital
ANSELC = 0; // Configure le PORTC en digital
SLRCON = 0; // ?? Configure all PORTS at the standard Slew
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
Lcd_Out(1,1,txt1); // Écrit le texte de présentation 1er ligne
Lcd_Out(2,1,txt2); // Écrit le texte de présentation 2iéme ligne
Delay_ms(3000); // pause 3 sec
Lcd_Cmd(_LCD_CLEAR); // Efface l'écran
LCD_Chr(1,9,'.'); // On écrit la matrice du texte statique
LCD_Chr(1,12,'.');
LCD_Out(2,1,"Heure:");
LCD_Chr(2,11,':');
LCD_Chr(2,14,':');
LCD_Out(1,13,"20"); // le 20 c'est pour l'année 20xx
/*##################################################################################
############################ 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, 4, 31, 12, 15); //heure: min: sec: N°jour: jour: mois: année
oldstate = 0; // mise à 0 du flag
}
Lecture_GDH(); // On va lire notre DS1307
switch(jour) // On sélectionne le jour suivant la valeur retournée
{
case 1: LCD_Out(1,1, "Lundi"); break; // Affichage du jour en fonction de la valeur
case 2: LCD_Out(1,1, "Mardi"); break;
case 3: LCD_Out(1,1, "Mer. "); break;
case 4: LCD_Out(1,1, "Jeudi"); break;
case 5: LCD_Out(1,1, "Ven. "); break;
case 6: LCD_Out(1,1, "Sam. "); break;
case 7: LCD_Out(1,1, "Dim. "); break;
}
Lcd_Chr(1,7, (n_jour / 10) + 48); // Le numéro du jour dizaine
Lcd_Chr(1,8, (n_jour % 10) + 48); // Le numéro du jour unité
Lcd_Chr(1,10, (mois / 10) + 48);
Lcd_Chr(1,11, (mois % 10) + 48);
Lcd_Chr(1,15, (annee / 10) + 48);
Lcd_Chr(1,16, (annee % 10) + 48);
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
}
}
Sur la vidéo, n'ayant pas de pile, on voit les registres à 0 à l'allumage, puis en appuyant sur le BP en injecte les données . Dans notre exemple nous sommes le Jeudi 31 décembre 2015 et il est 23h59 .
http://www.dailymotion.com/video/x3bxeqz