mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP 430 & Uhrzeit


Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin.

Kennt jemand von euch eine Möglichkeit dem MSP 430 die Uhrzeit
'beizubringen'? Ich möchte diese dann zB. auf einem Display ausgeben.

Autor: Läubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eventuell kannst du ja ne RTC dranbauen... die läuft sogar bis zu 5
Jahre weiter wenn du die stromversorgung entfernst.

Autor: Alexander Höller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> die läuft sogar bis zu 5 Jahre weiter wenn du die stromversorgung
entfernst.

auch auch nur wenn amn ihr ne backup batterie/goldcap/etc. gitb, oder ?

Autor: Sebastian (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
> Kennt jemand von euch eine Möglichkeit dem MSP 430 die Uhrzeit
> 'beizubringen'? Ich möchte diese dann zB. auf einem Display
> ausgeben.

Klar. Hab sowas letztens mal mit dem MSP430F140 gemacht. Ich benutze
die 50Hz des Netzes als Sekunden-Geber. Über den Tag gemittelt halten
die Energieversorger die 50Hz so präzise wie 'ne Atomuhr. :-) Ich hab
den Code mal angehangen (simple.c ist die Hauptdatei, der Rest sind
Hilfs-Libraries für den USART, I2C usw.). Das Programm liest noch zwei
I2C-Temperatursensoren aus, aber das kannst du ja auskommentieren. Du
kannst die Uhrzeit per Terminalprogramm vom PC aus einstellen, ab dann
läuft die Uhr natürlich völlig eigenständig weiter. Die Ausgabe erfolgt
auf einem Display mit KS0108-Chipsatz. Codeanpassungen für ein
HD44780-Display findest du auf meiner Homepage www.mathar.com (im
LCD-Kapitel).

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wow. Wer kommt auf so eine Idee? Nur nutze ich ein
Gleichspannungsnetzteil für meine Schaltungen.
Wäre das denn der übrigbleibende Quelltext für die Uhrzeitbestimmung:


#include <msp430x14x.h>

char uhr_str[]="00";
char hundertstelsekunden=0, sekunden=0, minuten=8, stunden=21, tage=0;


int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;  // watchdog aus
  _BIS_SR(GIE);           // allgemeiner interrupt-enable
  P1IE=0x10;              // pin 16 interrupt-faehig machen (wg.
100Hz-erkennung)
  P1IES=0x10;             // interrupt auf pin 16 ausloesen bei
high->low - uebergang



#pragma vector=PORT1_VECTOR
__interrupt void Port1_Interrupt (void)
{
  if (P1IFG&0x10)         // 0x10 ist pin 16
  {
  if (!((++hundertstelsekunden)%50))
    {                     // experimentell: uhrzeit ausgeben ...
      hundertstelsekunden = 0;
      if (!((++sekunden)%60))
      {
        sekunden = 0;
        if (!((++minuten)%60))
        {
          minuten = 0;
          if (!((++stunden)%24))
          {
            stunden = 0;
            tage++;
          }
        }
      }
    }
  }
  P1IFG&=~0x10;
}

Autor: Alexander Höller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, weil du ja keine 50Hz (oder sind's 100? hab mir die Schaltung,
Code nicht wirklich angeschaut) an den Interrupt Pin anliegen hast. Du
hast also nichts was dir eine Zeitbasis liefern würde.

Möglichkeiten:

.) du verwendest (wie oben erwähnt) einen externen RTC IC
.) du verwendest nen internen Timer, der dir die Zeitbasis liefert -
also z.B. alle 20ms (um bei den 50Hz zu bleiben) auslöst

mfG,
aleX

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du einen Uhrenquarz (32kHz) an deinem MSP hängen? Dann kannst du
ganz einfach einen 16-Bit-Timer (Timer_A) überlaufen lassen und hast so
auch einen Sekundengeber.

Autor: Läubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt RTC's mit eingebauter 'eigener' stromversorgung. das sit eine
twas größerer Klotz (etwa doppeltsohoch wie nen normaler IC).

Autor: MAX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Sebastian:

Ja, ich habe einen 32 kHz Uhrenquartz und einen 8 Mhz Quartz am MSP.
Hast du einen Tipp oder Codebeispiel wie das damit funktionieren würde?

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicht auswendig. Grab dich mal durch die Tutorials auf meiner Website.
IIRC benutze ich den Timer in dem Disco-Tutorial iVm mit einer PWM.
Dort siehst du dann den Code, den du brauchst.

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was bedeutet iVm und PWM? Ich schaue mir mal das Tutorial an.

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PWM hat sich schon geklärt....stand etwas auf der Leitung. ;-)

Autor: MAX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Echt geile Page. Das Tutorial für das Discomopped liest sich ja super,
aber mir ist im Moment schleierhaft, wie man daraus eine Uhr bauen
soll!

Autor: tenner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aclk läuft mit 32,...khz, alle 125ms wird ein interrupt ausgelöst wobei
die uhr um eben 125ms hochgezählt wird ...
wenn dir ein sekundentakt reicht, kannst du auch einfach den
timerüberlauf-interrupt nutzen und dann einfach eine sekunde hoch
zählen

stGlobalTime ist eine struktur.

void init_Timer(void)
{
  TACTL    = TASSEL_1 + TACLR + TAIE; // upcount until CC0 event (using
ACLK)
  TACCTL0  = CCIE;
  TACCR0   = 4096;                             // let count 4096
cycles: 125ms intervals

  TACTL   |= MC_2;                             // start timer
}

interrupt (TIMERA0_VECTOR) Timer_A0(void)
{
  TACCR0  += 4096;               // Add Offset to CCR0 (125ms)
  uiMsCnt += 125;
  if( uiMsCnt == 1000 ) {
    uiMsCnt = 0;
    stGlobalTime.tm_sec++;
    ulUpTime++;
    if( stGlobalTime.tm_sec >= 60 ) {
      stGlobalTime.tm_sec = 0;
      stGlobalTime.tm_min++;
      if( stGlobalTime.tm_min >= 60 ) {
        stGlobalTime.tm_min = 0;
        stGlobalTime.tm_hour++;
        if( stGlobalTime.tm_hour >= 24 ) {
          stGlobalTime.tm_hour = 0;
          stGlobalTime.tm_yday++;
          if( stGlobalTime.tm_yday >= 365 ) {
            stGlobalTime.tm_yday = 0;
            stGlobalTime.tm_year++;
          }
        }
      }
    }
  }
}

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@tenner: Vielen Dank. Ich werde das später ausprobieren!

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bitte nicht böse sein, aber ich kapiere da gar nix. Soll denn der Code
denn du,tenner, jetzte geschrieben hast, eine Uhr ergeben oder muss das
mit den Sachen von Sebastian kombiniert werden? Der nutzt ja die 50 Hz
der Wechselspannung.

Autor: tenner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
der code zeigt wie eine uhr mit hilfe des 32kHz quarz und dem timer
interrupt implementiert werden kann. hat nichts mit dem von sebastian
zu tun.
der timerA wird mit dem 32768Hz uhrenquarz getaktet. alle 4096 takte
wird ein interrupt ausgelöst, der den milisekunden-zähler um 125ms
erhöt. nach 8 interrupts, also wenn der ms-zähler auf 1000 steht, wird
der sekundenzähler um 1 erhöt. nach 60 sec der min-zähler 1+ usw.

stGlobalTime ist eine struktur die wie folgt aussieht

struct tm
{
  int tm_sec;     /* 0..59 */
  int tm_min;     /* 0..59 */
  int tm_hour;    /* 0..23 */
  int tm_mday;    /* 1..31 */
  int tm_mon;     /* 0..11 */
  int tm_year;    /* 0(:=1900).. */
  int tm_wday;    /* 0..6 */
  int tm_yday;    /* 0..365 */
  int tm_isdst;   /* 0 */
};

das anzeigen der uhrzeit mußt du schon selbst erledigen.

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Tenner,

vielen Dank für deine Programmauschnitte. Ich habe mal versucht etwas
daraus zu basteln:


#include  "msp430x14x.h"

void init_Timer(void);
void main(void);


void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;             // watchdog aus
}


struct tm
{
  int tm_sec;     /* 0..59 */
  int tm_min;     /* 0..59 */
  int tm_hour;    /* 0..23 */
  int tm_mday;    /* 1..31 */
  int tm_mon;     /* 0..11 */
  int tm_year;    /* 0(:=1900).. */
  int tm_wday;    /* 0..6 */
  int tm_yday;    /* 0..365 */
  int tm_isdst;   /* 0 */
};



void init_Timer(void)
{
  TACTL    = TASSEL_1 + TACLR + TAIE; // upcount until CC0 event
(usingACLK)
  TACCTL0  = CCIE;
  TACCR0   = 4096;                             // let count 4096
cycles: 125ms intervals
  TACTL   |= MC_2;                             // start timer
}

interrupt (TIMERA0_VECTOR) Timer_A0(void)
{
  TACCR0  += 4096;               // Add Offset to CCR0 (125ms)
  uiMsCnt += 125;
  if( uiMsCnt == 1000 ) {
    uiMsCnt = 0;
    stGlobalTime.tm_sec++;
    ulUpTime++;
    if( stGlobalTime.tm_sec >= 60 ) {
      stGlobalTime.tm_sec = 0;
      stGlobalTime.tm_min++;
      if( stGlobalTime.tm_min >= 60 ) {
        stGlobalTime.tm_min = 0;
        stGlobalTime.tm_hour++;
        if( stGlobalTime.tm_hour >= 24 ) {
          stGlobalTime.tm_hour = 0;
          stGlobalTime.tm_yday++;
          if( stGlobalTime.tm_yday >= 365 ) {
            stGlobalTime.tm_yday = 0;
            stGlobalTime.tm_year++;
          }
        }
      }
    }
  }
}


Aber so richtig will das noch nicht. Die Displayausgabe habe ich im
Moment weggelassen. Dafür bieten sich die Sachen von Sebastian ja
hervorragend an.

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was heisst "so richtig will das noch nicht"? Was will nicht? Klappt
gar nix, oder zählt er nur falsch, oder zu schnell, oder zu langsam
oder wie?

Autor: tenner (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
moin,

naja, so kanns auch nicht funktionieren. zunaächst mußt die die
variable stGlobalTime anlegen. diese muß global angelegt werden.

struct tm stGlobalTime;

die definition der struktur muß natürlich vor dem anlegen erfolgen. am
besten beides vor der main funktion.
uiMsCnt muß global angelegt und initialisiert werden

unsigned int uiMsCnt = 0;

ulUpTime kann du streichen oder sie muß global angelegt und mit 0
initialisiert werden.

du mußt die ACLK auf den externen 32768kHz quarz konfigurieren.
der timer muß initialisiert werden, aufruf der funk. init_Timer() in
der main().

ich hab mal ne datei angehängt, mit der es funktionieren sollte. kann
es aber hier selber nicht testen, da keine compiler und keine hardware
zur verfügung.

welchen compiler benutzt du?

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
[..]
        if( stGlobalTime.tm_hour >= 24 ) {    // 24hour -> 1day
          stGlobalTime.tm_hour = 0;           // reset hour counter
          stGlobalTime.tm_yday++;             // increment day
[..]

Hier fehlt noch der tm_wday:

[..]
        if( stGlobalTime.tm_hour >= 24 ) {    // 24hour -> 1day
          stGlobalTime.tm_hour = 0;           // reset hour counter
          stGlobalTime.tm_yday++;             // increment day
          stGlobalTime.tm_wday++;             // increment day of week
[..]

Autor: tenner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
moin oldbug,

die eigentliche datumsberechnung wird außerhalb der isr gemacht.

außerdem würde dann nochetwas fehlen

[..]
        if( stGlobalTime.tm_hour >= 24 ) {    // 24hour -> 1day
          stGlobalTime.tm_hour = 0;           // reset hour counter
          stGlobalTime.tm_yday++;             // increment day
          stGlobalTime.tm_wday++;             // increment day of week
          if( stGlobalTime.tm_wday >= 6 ) {    // 24hour -> 1day
            stGlobalTime.tm_wday = 0;
          }
[..]

und was ist dann stGlobalTime.tm_mday und stGlobalTime.tm_mon?
nee, nee, die isr dient nur um die fortlaufende zeit "messen"
datumsberechnungen sollten dann auf abruf geschehen.

wenn man die isr möglichst kurz halten will benutzt man eine 32bit
integer und incrementiert dies jede sekunde. so zu sagen ein
uptimecounter, dann setzt man setzt dann die Uhr und speichert den
aktuelen uptimecount. aus diesem läst sich dann jederzeit die uhrzeit
und das datum berechnen.
bsp-code?

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, stimmt schon...
Bin da auch erst durch "tm_mday" drauf gekommen.

Autor: Max (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

>welchen compiler benutzt du?

Bis gestern habe ich noch den MSPGCC benutzt. Habe mir aber vor ein
paar Tagen den ICC Compiler von Imagecraft bestellt, welcher heute
angekommen ist.
Das sind die Fehlermeldungen:


!E d:\uhr\uhr.c(42): invalid octal constant `08'
!E d:uc\uhr\uhr.c(67): type error in argument 1 to `LCDOuts'; found
`struct tm' expected `pointer to char'
!E d:\uhr\uhr.c(109): syntax error; found `12' expecting `)'
!E d:\uhr\uhr.c(109): skipping `12'
!W d:\uhr\uhr.c(109):[warning] declaring a function without prototype
may cause errors
!E d:\uhr\uhr.c(109): syntax error; found `Timer_A0' expecting `;'
!W d:\uhr\uhr.c(133):[warning] missing return value
F:\tools\icc\bin\imakew.exe: Error code 1
Done: there are error(s). Exit code: 1


Ich hänge mal das um die erweiterten Funktionen von Sebastian (Danke
dafür) c-file an.

Autor: StephanW (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nochmal zu der Netzteil-Sache:
Das man ein Gleichspannungsnetzteil benutzt ist ja wohl klar,
jedenfalls habe ich noch kein uC mit eingebauter Spannungsaufbereitung
gesehen :)

@Sebastian:
Das mit den 50Hz finde ich interessant. Im Physik-Unterricht hatten wir
mal einen Versuch, in dem die 50Hz als Referenz benutzt wurden; mein
Lehrer meinte dann auf meine Frage der Ungenauigkeit hin, das diese
50Hz absolut präzise gehalten werden...
Wie holst du dir denn die 50Hz aus dem NT? Ich stelle mir gerade so ne
Kombination aus ner Silizium- und Zenerdiode vor...

Gruß Stephan

Autor: tenner (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
auspacken,
#define __ICC430
in uhr.c am anfang hinzufügen
die ports an deine hw anpassen
mit icc430 compilieren

sollte aber auch ohne das #define mit dem gcc gehen

code anschauen und versuchen zu verstehen.

gruß tenner

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mensch tenner, du bist ja eine Wucht. Ich könnte dich knutschen. ;-)
Nee, ist nur Spaß. Vielen Dank für das Programm, es funktioniert
ausgezeichnet. Nur eine Frage: Gibt es eine Möglichkeit, die Uhrzeit zu
stellen, ohne den MSP jedes Mal neu programmieren zu müssen?

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AAARGH! Jetzt habe ich gerade eine halbe Stunde lang getippt und das
blöde Forum hat meinen Beitrag gefressen. :-( Hab keine Lust, alles
noch mal zu tippen.

@Stephan: Nulldurchgangserkennung, hab ich auf
http://mathar.com/msp_dimmer1.html erklärt. Die 50Hz sind AFAIK sehr
genau, genauer jedenfalls als jede Taiwan-Armbanduhr.

@Max: Nein, gibt es nicht. Aber dem MSP430 verbraucht ja superwenig
Strom im LPM, daher: Einfach immer anlassen. :-)

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schade. Naja, egal. Dann lasse ich den MSP 430 einfach an.

Autor: tenner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sicher gibt das ne möglichkeit die uhr zu stellen, ich zeigs euch
morgen, hab jetzt nicht die muße dazu.

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jau, mach mal. Das würde mich sehr interessieren...
_____
Fällt dir vielleicht etwas zu meinem Usart-Problem ein?!

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@tenner: Dann bin ich ja mal gespannt, wie du einem ausgeschalteten
MSP430 beibringen willst, ohne externe Bauteile (RTC o.ä.) die Uhrzeit
zu behalten. :-p

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Von behalten hat tenner hat nix geschrieben. ;-)

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja Momeeeeent. Das EINSTELLEN der Uhrzeit ist trivial. Hast du dir den
Code durchgelesen, von dem ich geredet habe? Offenbar nein. Also
guckstu http://www.mathar.com und da den Link auf der Startseite zu der
clock.zip. Da drin ist eine Routine, die die Uhr per serieller
Schnittstelle von einem PC aus einstellt. Einmal eingestellt läuft die
Uhr dann lustig vor sich hin, bis der Strom weg ist. Und wenn er weg
ist, ist es definitiv unmöglich, die aktuelle Uhrzeit weiter laufen zu
lassen.

Autor: tenner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
na kann ich mir die mühe ja sparen.

aber um die uhr weiter laufen zu lassen könnte ma zb. eine
batteriepufferung einbauen und bei stromausfall den µc in den lpm3
schicken und beim timerinterrupt aufwecken um die uhr weiter zu
stellen.

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, das wäre z.B. eine sehr elegante Lösung.

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat gut geklappt mit der Uhreinstellung durch die serielle
Schnittstelle. Danke euch Beiden nochmal.
Nur die ollen Usart-Schnitstellen bereiten mir nach wie vor
Kopfschmerzen...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.