MPLABX dispose de 2 variables __DATA__ et __TIME__ liées au compilateur XC8 2.36 C90
permettant de signaler par exemple, la date fraicheur du programme :
Compile le Oct 15 2023 a 14:29:37 UTC
avec version XC8 : 2360
L'idée est d'exploiter ces 2 infos pour initialiser une RTC DS3231 via I2C1
nota: j'ai supposé que MLPAB delivre dans _DATA__ le nom du mois avec seulement les 3 premiers caracteres
et que le format ( longueur de texte est constant)
ATTENTION aux notions aux valeurs pouvant représenter de l'ascii, du binaire, ou du BCD ...
La RTC nécessite du BCD !
Dommage, Le numéro du jour dans la semaine n'est pas transmis par MLPAB
et on en a besoin pour cette appli "chaudiere".
Recherche de ce jour via le calcul du Jour Julien fonction ( an,mois,jour)
pour déterminer jS : jour de semaine (jS évolue de 0=Lundi à Dimanche=6)
qui sera assigné au parametre #04 de la RTC
(malgré quand même un peu de code supplementaire ! ... (mais c'est un 18F27K42 avec 128ko)
ça marche ! MAIS ....
(variable !) estimée ici à 1mn 20" à la premiere compilation
et 49 sec ... aux suivantes ( avec 12go de RAM sur le PC WIN10, et plusieurs minutes avec seulement 4Go de RAM)
ce n'est donc pas le Perrou !
... mais on peut toujours rectifier ce retard au temps
sachant que le terminal YAT , permet de mesurer exactement cette différence de temps ... option ...view...show time Stamp
à la seconde compilation, sans modif de code source...
(14:59:25.467) Datas PC System
(14:59:25.467) Oct 15 2023
(14:59:25.519) 14:58:37
...etc ....
(14:59:38.327) 00000
(14:59:39.341) BAV=2
(14:59:40.691) Recu :BAV=2
(14:59:40.703) 00001 Dimanche 15/10/23 14H58M52S
(14:59:43.102) 00002 Dimanche 15/10/23 14H58M54S
ecart= 59:43 - 58:54 = 0mn 49sec
L'autre probleme est le flag automatique ETE / HIVER qui dépend du moment de compilation
car sauvé en EEPROM et relu ensuite ..
cela implique de garder
- une possibilite MANUELLE de rectifier le contenu RTC ( dialogue operateur via BP et LCD) (déja prevu et ok)
- ou via la liaison UART (dialogue Operateur) en envoyant la sequence d'init sous la forme :
U;15;10;23;14;20;06;# pour 15 octobre 2023 , 14H20, Dimanche \r\n") (deja prevu et ok)
Conclusion : fausse bonne idée ... mais intéressera peut être quelqu'un. ?mais ça m'a permis de dépoussiérer un vieux programme écris en Turbo C 2.00, il y a quelques décennies (CALANDAR.C)
Transposable facilement en XC8
(14:59:25.467) Datas PC System
(14:59:25.467) Oct 15 2023
(14:59:25.519) 14:58:37
(14:59:25.519)
(14:59:25.519) recup datas (en BCD !!) pour init RTC
(14:59:25.519) Mois = Oct..mois trouve =10
(14:59:25.519) , jour = 15, Annee = 23
(14:59:25.519) JMA= 15/10/23 , time 14:58:37
(14:59:25.519)
(14:59:25.519) Test jour Julien
(14:59:25.519) date 29/08/1996 -> jour julien # 2450325 Jeudi jour # 3
(14:59:25.519) date aujourd'hui 15/10/2023 -> jour julien # 2460233 Dimanche jour # 6
(14:59:25.519)
(14:59:25.519) MAJ RTC !
(14:59:25.519) ATTENTION : Possibilité de forçage init RTC , inhibée pendant les tests
(14:59:25.519) Re-Lecture et affichage des 8 registres RTC DS3231
(14:59:25.622) Temperature DS3231 => 24.75°C
(14:59:25.668) Horaire d' ETE
(14:59:25.854) adresse LCD= 32 soit 0X20
(14:59:25.854)
(14:59:25.854) Sequence d'Init LCD 4x20 via I2C1 PCF8574
(14:59:25.854) .123456789A
(14:59:26.003) version Carte PCB chaudiere : LCD Blanc à l'adresse 0x20 !
(14:59:26.231) Chargement caracteres Speciaux en CGRAM
(14:59:26.415) ECO....
(14:59:26.469) BARRE_G
(14:59:26.475) BARRE_D
(14:59:26.505) BARREGD
(14:59:26.535) FLECH H
(14:59:26.565) FLECH_B
(14:59:26.594) 1/2Heur
(14:59:26.634) DEGREC
(14:59:27.653)
(14:59:27.653) Config et Init One Wire
(14:59:27.715)
(14:59:27.715) Rechargement corrections capteurs DS18B20 depuis Eeprom
(14:59:27.715) T1Cor= -0.021
(14:59:27.715) T2Cor= -0.021
(14:59:27.715) T3Cor= 0.042
(14:59:27.715)
(14:59:27.850) Mesures 3 temperatures Corrigees :
(14:59:28.430) INT_mes= 23.667°C
(14:59:28.486) EXT_mes= 23.729°C
(14:59:28.555) EAU_mes = 23.854°C
(14:59:30.603)
(14:59:30.603) Init Compteur 24 bits SMT1, avec choix clock 4=> 500KHz tick=2uS
(14:59:30.713) Test SMT1 avec delay 100mS , Nb Tics 49997 L2=99994 uS
(14:59:30.743)
(14:59:30.743)
(14:59:30.743)
(14:59:30.743) Lecture table programmes horaire en eeprom
(14:59:37.913)
(14:59:38.275) Duree Affichage LCD , Nb Tics 178186 L2=356372 uS
(14:59:38.327) Init Timer1 100mS et SMT1 compteur 24bits
(14:59:38.327) Reaffectation RC5 (SW6 inout) en Sortie pour Alarme L5
(14:59:38.327) 00000
(14:59:39.341) BAV=2
(14:59:40.691) Recu :BAV=2
(14:59:40.703) 00001 Dimanche 15/10/23 14H58M52S
(14:59:43.102) 00002 Dimanche 15/10/23 14H58M54S
la partie code associée à ce test
Code : Tout sélectionner
const char Prefixe_Mois[12][4]={ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
// ----date et RTC -----
long Jour_Julien;
const char All_Jour_Semaine[]="LuMaMeJeVeSaDiEr";
const char Jour0[]="Lundi ";
const char Jour1[]="Mardi ";
const char Jour2[]="Mercredi ";
const char Jour3[]="Jeudi ";
const char Jour4[]="Vendredi ";
const char Jour5[]="Samedi ";
const char Jour6[]="Dimanche ";
const char Jour7[]="Error ";
const char * JourSemaine[]={Jour0,Jour1,Jour2,Jour3,Jour4,Jour5,Jour6,Jour7};
char time[]="00H00M00S";
char date[]="00/00/00";
long jour2jul(char jour , char mois , int annee);
char *j_txt(long n , char *num);
long jour2jul(char jour , char mois , int annee)
{
long jule, gregorien, a , j , m;
/* Attention, cette routine ne doit etre appellee que si on est sur
que le jour fourni en param?tre existe !!!!!! */
a = (long)annee;
m = (long)mois;
j = (long)jour;
// On commence par faire un ajustement pour les annnees negatives
if (annee < 0) a++;
jule = ((489L *m - 481 ) >>4) + j + 1721423L - (((a&3)+7)>>2)*((m+13)>>4) + ((1461L*(a-1))>>2);
/* Avant le 04/10/1582 on est en calendrier julien, et en calendrier gregorien apres le 15/10/1582 */
if (jule <= 2299160L)
return jule;
/* En calendrier gregorien les ajustements ? faire sont :
- les annees divisibles par 100 ne sont pas bissextiles
- les annees divisibles par 400 sont bissextiles.
*/
gregorien = jule - (a/100L - a/400L - 2L);
if ( ( (a%100) == 0 ) && (m < 3) && ( (a%400) != 0)) gregorien++;
return gregorien;
}
char *j_txt(long n , char *num)
{
char c;
if (n < 0L)
c = 6 - (char)((-n-1)%7);
else
c = (char)(n%7);
*num = c;
return (char *)JourSemaine[c];
}
// ------------ dans le main.c ---------------------------
sprintf(txt," Compile le %s a %s UTC\r\n avec version XC8 : %d \r\n", __DATE__, __TIME__,__XC8_VERSION);
Print(txt);
CRLF1();
__delay_xSec(2);
CPrint(" Init_I2C() à 100Khz;\r\n");
Init_I2C(); //SCLK= 500Khz / 5 = 100Khz
CPrint(" Test presence devices sur Bus I2C1\r\n");
Test_Presence_I2C_devices();
CRLF1();
CPrint(" #1 Active sortie RTC SQW=1Hz: \r\n");
CPrint(" GO\r\n");
// set SQW output Start oscillateur
tmp[0]=0x40; // data
I2C1_Write1ByteRegister(DS3231_ADDR,0x0E, tmp[0]);
CPrint(" ok\r\n");
__delay_ms(100);
CPrint("\r\n Datas PC System \r\n");
sprintf(txt,"%s", __DATE__); // Oct 14 2023 11 cars
Print(txt);CRLF1();
sprintf(CRam1,"%s", __TIME__);
Print(CRam1);CRLF1(); //15:02:12 8 cars
CRLF1();
CPrint(" recup datas (en BCD !!) pour init RTC \r\n");
// decodage pour le Numero du mois
*(txt+3)=0; CPrint("Mois = ");Print(txt);
i=0;
do
{
if (strcmp( &Prefixe_Mois[i],txt) ==0 )
{
sprintf(Tampon,"..mois trouve =%d ",i+1);
Print(Tampon);
CRLF1();
mois=Dec2Bcd(i+1);
break;
}
i++;
}
while (i<12);
*(txt+6)=0; CPrint(", jour = ");Print(txt+4);
jour=(*(txt+4)-48)*16 + *(txt+5)-48; // jour=atoi(txt+4);
*(txt+11)=0;
CPrint(", Annee = ");Print(txt+9);
Annee=(*(txt+9)-48) *16 + *(txt+10)-48; //Annee=atoi(txt+9);
CRLF1();
* (CRam1+2)=0;* (CRam1+5)=0;* (CRam1+8)=0;
heure= (*(CRam1)-48 ) *16 + *(CRam1+1)-48; // en BCD !!
minute=(*(CRam1+3)-48) *16 + *(CRam1+4)-48;
second=(*(CRam1+6)-48) *16 + *(CRam1+7)-48;
sprintf(txt,"JMA= %02x/%02x/%02x , time %02x:%02x:%02x\r\n",jour,mois,Annee,heure,minute,second);
Print(txt);
CRLF1();
CPrint(" Test jour Julien\r\n");
Jour_Julien=jour2jul(29,8,1996);
sprintf(txt," date 29/08/1996 -> jour julien # %ld",Jour_Julien);
Print(txt);PrintChar(TAB);
// jour de la semaine
Print(j_txt(Jour_Julien , &cx));
CPrint(" jour # ");PrintChar(cx);
PrintChar(cx+48);
CRLF1();
i=Bcd2Dec(jour);
j=Bcd2Dec(mois);
k=Bcd2Dec(Annee);
Jour_Julien=jour2jul(i,j,k+2000);
sprintf(txt," date aujourd'hui 15/10/2023 -> jour julien # %ld",Jour_Julien);
Print(txt);PrintChar(TAB);
// jour de la semaine
Print(j_txt(Jour_Julien , &jS));
CPrint(" jour # ");
PrintChar(jS+48); CRLF1();
CRLF1();
CPrint(" MAJ RTC !\r\n");
// avec datas en BCD !
tmp[0]=0x00; //stop Oscillateur
tmp[1]=second; ;
tmp[2]= minute;
tmp[3]= heure;
tmp[4]=jS; //write day of week
tmp[5]=jour;
tmp[6]=mois;
tmp[7]=Annee;
tmp[8]=0;
p1=&tmp[0];
I2C1_WriteNBytes(DS3231_ADDR,p1,9);
oui, je sais ... il y aurait sans doute d'autres possibilités ( Via ESP8266 ou autre GPS ..etc ...)

