[GTranslate]
Le micro-contrôleur MSP430G2553 de Texas Instruments livrés avec le LaunchPad dispose de tout le nécessaire pour en faire une horloge temps-réel (RTC). Il suffit de lui connecter un quartz 32KHz et de le programmer convenablement.
TI donne les librairies en assembleur utilisable avec leur environnement de développement. Pour Energia, une nouvelle librairie était nécessaire, je me suis donc attelé à sa conception.
Rien de révolutionnaire, mais ça peut servir à d’autres. C’est sur cette librairie qu’est basée ma balise autonome WSPR que je compte proposer en semi-kit d’ici peu (certainement à mon retour de vacances début juillet). D’origine la dérive en fréquence est de l’ordre du Hertz pour 24 heures (20ppm) ce qui suffit pour une nuit de transmission WSPR, mais peut-être ajustée avec un condensateur variable pour corriger la fréquence du quartz.
Le fichier d’en-têtes (sRTCsec.h) :
/* sRTC.h - Library for adding simple RTC capabilities using MSP430 hardware By Yannick DEVOS (XV4Y) - 2012 ///////////////////////////////// How to use the lib * Create an instance of the object RealTimeClock myClock; * In order to have this RTC library working you should add this code to the end of your main program : interrupt(TIMER1_A0_VECTOR) Tic_Tac(void) { myClock.Inc_sec(); // Update secondes }; * Enjoy the clock reading the RTC_sec, RTC_min, RTC_hr variables */ // ensure this library description is only included once #ifndef RTCsec_h #define RTCsec_h // library interface description class RealTimeClockSec { // user-accessible "public" interface public: RealTimeClockSec(void); void Set_Time(char hr, char mins, char secs); char RTC_sec; // This how you read the time, by reading the vars char RTC_min; char RTC_hr; void Inc_sec(void); // This methode should be invoked by an Interrupt call (see top of the file comment) // A few private methods private: void Inc_min(void); void Inc_hr(void); }; #endif
Le code par lui-même (sRTCsec.cpp) :
/* sRTC.h - Library for adding simple RTC capabilities using MSP430 hardware By Yannick DEVOS (XV4Y) - 2012 */ // include this library's description file #include <sRTCsec.h> #include <legacymsp430.h> // Constructor ///////////////////////////////////////////////////////////////// RealTimeClockSec::RealTimeClockSec(void) { RTC_sec = 0; RTC_min = 0; RTC_hr = 0; WDTCTL = WDTPW | WDTHOLD; // Kill watch-dog BCSCTL1 = DIVA_3; // Clock = ACLK / 8 BCSCTL3 |= (LFXT1S_0 | XCAP_3); // Internal 12.5pF cap for 32KHz crystal TA1CCTL0 = CCIE; // CCR0 interupt activated TA1CCR0 = 4096-1; // 4096 ticks of 32KHz XTal = 1 second => CCR0 counts N+1 TA1CTL = TASSEL_1 | ID_3 | MC_1; // Clock for TIMER 1 = ACLK, By 8 division, up front }; // Methods ///////////////////////////////////////////////////////////////// void RealTimeClockSec::Inc_sec(void) { RTC_sec = RTC_sec + 1; // Update seconds if (RTC_sec == 60) { RTC_sec=0; Inc_min(); }; }; void RealTimeClockSec::Inc_min(void) { RTC_min = RTC_min + 1; // Update minutes if (RTC_min == 60) { RTC_min=0; Inc_hr(); }; }; void RealTimeClockSec::Inc_hr(void) { RTC_hr = RTC_hr + 1; // Update hours if (RTC_hr == 24) { RTC_hr=0; }; }; void RealTimeClockSec::Set_Time(char hrs=0, char mins=0, char secs=0) { if ((hrs>=0 && hrs <24) && (mins>=0 && mins<60) && (secs>=0 && secs<60)) { RTC_hr = hrs; // Set time to values given in parameters RTC_min = mins; RTC_sec = secs; }; };
Avec un exemple (testé sous Energia 005a) c’est plus facile à comprendre :
#include <sRTCsec.h> #include <legacymsp430.h> #include <TimerSerial.h> TimerSerial mySerial; RealTimeClockSec myRTC; int ledState = LOW; void setup() { pinMode(2, OUTPUT); // This is to close the serial output so you are able to upload a new sketch to the LaunchPad pinMode(5, INPUT_PULLUP), attachInterrupt(5,fin,LOW); mySerial.begin(); }; // The LED1 will blink each exact second and the time will be printed to the serial port void loop() { if ((myRTC.RTC_sec % 2)==0 && ledState== HIGH) { ledState = LOW; mySerial.print(myRTC.RTC_min, DEC); mySerial.print(":"); mySerial.println(myRTC.RTC_sec, DEC); digitalWrite(2, ledState); }; if ((myRTC.RTC_sec % 2)==1 && ledState== LOW) { ledState = HIGH; mySerial.print(myRTC.RTC_min, DEC); mySerial.print(":"); mySerial.println(myRTC.RTC_sec, DEC); digitalWrite(2, ledState); }; }; void fin() { mySerial.end(); }; interrupt(TIMER1_A0_VECTOR) Tic_Tac(void) { myRTC.Inc_sec(); // Update secondes };