Moin. Kennt jemand von euch eine Möglichkeit dem MSP 430 die Uhrzeit 'beizubringen'? Ich möchte diese dann zB. auf einem Display ausgeben.
Eventuell kannst du ja ne RTC dranbauen... die läuft sogar bis zu 5 Jahre weiter wenn du die stromversorgung entfernst.
> 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 ?
> 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).
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; }
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
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.
Es gibt RTC's mit eingebauter 'eigener' stromversorgung. das sit eine twas größerer Klotz (etwa doppeltsohoch wie nen normaler IC).
@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?
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.
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!
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++; } } } } } }
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.
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.
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.
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?
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?
[..] 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 [..]
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?
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.
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
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
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?
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. :-)
sicher gibt das ne möglichkeit die uhr zu stellen, ich zeigs euch morgen, hab jetzt nicht die muße dazu.
Jau, mach mal. Das würde mich sehr interessieren... _____ Fällt dir vielleicht etwas zu meinem Usart-Problem ein?!
@tenner: Dann bin ich ja mal gespannt, wie du einem ausgeschalteten MSP430 beibringen willst, ohne externe Bauteile (RTC o.ä.) die Uhrzeit zu behalten. :-p
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.
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.
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...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.