Go Down

Topic: [Résolu] Comment exploiter la mémoire du DS1307? (Read 762 times) previous topic - next topic

moribond

Feb 14, 2012, 10:48 pm Last Edit: Feb 15, 2012, 09:08 pm by moribond Reason: 1
Hello à tous,

J'attends mon DS1307 et j'aimerais savoir si vous connaissez une class qui permet d'exploiter la RAM disponible de ce CI.
56 octets, ce qui donne la possibilité de stocker 11 dates sauvegardées grâce à la pile bouton.

Je pensais à un champ de bits du genre:
Code: [Select]
struct {
unsigned int day : 5; // 0 -> 30
unsigned int month : 4; // 0 -> 11
unsigned int year : 6; // 0 -> 64 (2000 -> 2064)
unsigned int hour : 5; // 0 -> 23
unsigned int minute : 6; // 0 -> 59
unsigned int second : 6; // 0 -> 59
unsigned int dayofWeek : 3; // 0 -> 6
unsigned int daysinMonth : 2; // 0 -> 3 (28+0 -> 28+3)
unsigned int bisexYear : 1; }; // 0 -> 1 (false or true)


J'ai cherché mais je n'ai rien trouvé, j'essaie de faire qlqs chose mais j'ai qlqs difficultés à mettre ça en place.

Merci

Super_Cinci

#1
Feb 15, 2012, 08:05 am Last Edit: Feb 15, 2012, 08:07 am by Super_Cinci Reason: 1
Salut,

Tu ne dois pas être loin, je pense, mais ce type de déclaration [unsigned int varName : n;], je connais pas. Un unsigned int, c'est un 16 bits, j'ai bien peur que ta structure ne soit quand même compilée sur 18 octets...

dans l'idée, il faudrait une fonction qui code une structure "date" en un tableau de 5 byte, non? avec des << et des >>, ça serait très rapide

Code: [Select]

struct {
byte day; // 0 -> 30
byte month; // 0 -> 11
byte year; // 0 -> 63 (2000 -> 2063) codé sur 6 bits...
byte hour; // 0 -> 23
byte minute; // 0 -> 59
byte second; // 0 -> 59
byte dayofWeek; // 0 -> 6
byte daysinMonth; // 0 -> 3 (28+0 -> 28+3)
byte bisexYear; // 0 -> 1 (false or true)
        byte h24; // 0 -> 1 (12h or 24h)
        byte bonusBit; // 0 -> 1 (car il reste de la place...) pourquoi pas heure hiver / été?
byte memBytes[5]; // les 5 octets codés
};

void compileDate(dateStruct *dat_var){  // compile la date sur 5 octets
  with (dat_var){
    day &= 0x1F;
    month &= 0x0F;
    year &= 0x3F;
    hour &= 0x1F;
    minute &= 0x3F;
    second &= 0x3F;
    dayofWeek &= 0x07;
    daysinMonth &= 0x03;
    bisexYear &= 0x01;
    h24 &= 0x01;
    bonusBit &= 0x01;
    memBytes[0] = day + (month << 5);
    memBytes[1] = (month >>3) + (year << 1) + (hour << 7);
    memBytes[2] = (hour >> 1) + (minute << 4);
    memBytes[3] = (minute >> 4) + (second << 2);
    memBytes[4] = dayofWeek + (daysinMonth << 3) + (bisexYear << 5) + (h24 << 6) + (bonusBit << 7);
  }
}

Bon, je n'ai pas encore bien bûché les accès par pointeurs, donc ça doit pas bien compiler, mais c'est l'idée. Reste à faire la fonction inverse (qui passe de memBytes[] vers les variables heures, minutes etc etc). J'ai du coup rajouté au passage deux boolean, puis qu'il nous restait deux bits sur les 5 octets...

SesechXP

Salut,

La structure de Moribond tient sur 6 octets (3 unsigned int). Le principe même du champ de bits (ou bit field) est de n'utiliser que quelques bits d'un ou plusieurs octets pour faire tenir un champ.
Par exemple, le champ day va prendre les 5 premiers bits de l'entier non signé 16 bits, le champ month les 5 suivants et ainsi de suite...
Julien - www.idreammicro.com

osaka

#3
Feb 15, 2012, 05:09 pm Last Edit: Feb 15, 2012, 06:21 pm by osaka Reason: 1
En jouant avec les opérateur bit à bit ça devrait être assez simple .
Exemple vite fais pour enregistré une valeur à la fois, juste changer le jours par exemple, etc. (avec l'année bissextile ça fait pile 16 bit)
Code: [Select]

unsigned int date;

date &= 0xFFE0; (1111 1111 1110 0000)
date += month;

date &= 0xFE1F; (1111 1110 0001 1111)
date += (day << 5);

date &= 0x81FF; (1000 0001 1111 1111)
date += (year << 9);

date &= 0x81FF; (0111 1111 1111 1111)
date += (bisexYear << 15);
.
.
.
date &= 0x81E0; (1000 0001 1110 0000)
date += (month+(year << 9)); // juste le mois et l'année

date =  month+(day << 5)+(year << 9)+(bisexYear << 15); //tout en 1 coup


pour les deux premier octet ça sera simple, pour les 54 autres  :~.
Peut être utilisé 5 octet (2 variable int + 1byte) par structure comme le propose Super_Cinci donc 40 bit (2 de perdu ou autre chose à ajouter, retenir  ?) comme tu en as besoin de 38.

day+month+year+bisexYear : 2 octet (int dont 16bit occupé)
hour + minute + dayofWeek  : 2 octet (int dont 14 bit occupé)
second + daysinMonth : 1 octet (byte dont 8bit occupé)

second ne serait pas dans le deuxième int pour facilité le travail comme l'ensemble de l'heure fais 17bit, mais bon il serait au début du 3 ième (byte) et entier.
La structure sur laque tu travaillerais.
Code: [Select]

struct date
{
uint16_t champ1;
uint16_t champ2;
uint8_t champ3;
};

date dates[11];

moribond

#4
Feb 15, 2012, 06:20 pm Last Edit: Feb 15, 2012, 06:32 pm by moribond Reason: 1
C'est bien un problème syntaxe sur lequel je butte. Je n'ai jamais eu l'occasion de jouer avec des bits.
Finalement je pense pouvoir zapper qlqs infos et une structure sur 4 octets devrait faire l'affaire. A stocker dans 2 int donc.

5 pour le jour
5 pour l'année
6 pour les minutes

4 pour le mois
5 pour les heures
6 pour les secondes

Je vais potasser les opérations avec les bits et ce que tu as posté Super_Cinci.
Je n'ai tjrs pas mon DS donc impossible de tester pour le moment. 23 jours qu'il est commandé:(


moribond

#5
Feb 15, 2012, 08:41 pm Last Edit: Feb 15, 2012, 09:52 pm by moribond Reason: 1
Tu avais raison Osaka, plutôt simple.
J'ai stocké ça dans un long. Ce qui devrait me permettre de stocker 14 dates dans le DS.

Si ça peut servir...
Code: [Select]
struct {
byte jour;
byte mois;
byte annee;
byte heure;
byte minute;
byte seconde; };

unsigned long DT2mem(byte jour, byte mois, byte annee, byte heure, byte minute, byte seconde) {
return(((long) annee << 27) + ((long) mois << 23) + ((long) jour << 18) + ((long) heure << 13) +
((long) minute << 7) + ((long) seconde << 1)); }

void mem2DT(unsigned long v, Datime *r) {
r->annee= (byte) (v >> 27);
r->mois= (byte) ((v << 5) >> 28);
r->jour= (byte) ((v << 9) >> 27);
r->heure= (byte) ((v << 14) >> 27);
r->minute= (byte) ((v << 19) >> 26);
r->seconde= (byte) ((v << 25) >> 26); }

Go Up