-
OK.
Wenn man das Dateblatt komplett liest findet man die Info, dass das DS1307 nur mit 100kHz arbeitet.
in der i2cmaster.S bin ich dann auf folgenden Code gestoßen
Code:
;*************************************************************************
; delay half period
; For I2C in normal mode (100kHz), use T/2 > 5us
; For I2C in fast mode (400kHz), use T/2 > 1.3us
;*************************************************************************
.stabs "",100,0,0,i2c_delay_T2
.stabs "i2cmaster.S",100,0,0,i2c_delay_T2
.func i2c_delay_T2 ; delay 5.0 microsec with 4 Mhz crystal
i2c_delay_T2: ; 4 cycles
rjmp 1f ; 2 "
1: rjmp 2f ; 2 "
2: rjmp 3f ; 2 "
3: rjmp 4f ; 2 "
4: rjmp 5f ; 2 "
5: rjmp 6f ; 2 "
6: nop ; 1 "
ret ; 3 "
.endfunc ; total 20 cyles = 5.0 microsec with 4 Mhz crystal
Da mein Assembler noch dürftiger ist als mein C komm ich mit dem Code überhaupt nicht zurecht. Kann mir jemand den Code abändern, damit das RTC bei 8MHz-takt meines Atmega8 mit 100kHz arbeitet?
-
](*,) ](*,) ](*,)
Ich bin mit SDA und SCL um jeweils einen Pin am Atmega8 verrutscht.
Und ja ich weiß, dass die beiden Pins 23 und 24 sind und somit ein Eck-Pin und der da drunter sind
](*,) ](*,) ](*,)
Auf jeden Fall funktioniert es jetzt. Ich hoffe euer Schweigen kommt daher, dass ihr den nicht vorhandenen Fehler gesucht aber nicht gefunden habt.
Jetzt mache ich mich dran die Zeiten auszulesen und erstmal via LCD auszugeben. Aber eine Frage habe ich schon einmal für die anstehende Matrixansteuerung:
Wie löse ich das am geschicktesten?
Ich habe schon mal angefangen die Uhrzeiten über Case-Anweisungen auszuwerten und dadurch die entsprechenden Bits zu setzen bzw. zu löschen. Das ganze habe ich versucht zu verschachteln, um Zeilen zu speichern. Also nicht einfach 60 Case-Abfragen für die Minuten und 12 für die Stunden. Aber ich habe das Gefühl, das geht auch stilvoller. Vor allem wenn ich mir den Code der Wordclock ansehe.
Dazu muss ich aber sagen, dass ich deren Code nur überflogen habe und mich nicht genau damit beschäftigt habe wie aus dem Funkmodul die Daten für die Uhrzeit kommen.
Habt ihr einen Vorschlag wie ich die Zeit am besten auf meine Matrix übertrage?
-
Na, 60 Abfragen für die Minuten werden es schon nicht werden. Ist die Wordclock-Sprache nicht im 5-Minuten-Raster? Dann prüfst du einfach nacheinander auf zwölf Grenzen, z.B. > 5, >10 , >15 ... Minuten und überschreibst die Matrixcodierung der vorherigen Grenze einfach mit der gerade positiv geprüften nächst größeren. Wenn ein NEIN kommt, springst du ohne Aktion aus der Kette raus ans Ende der Minuten-Transcodierung. Die Stunden werden in gleicher Weise transcodiert. Einen geschlossenen Algorithmus sehe ich hier nicht, an den Abfragen kommst Du m.E. nicht vorbei.
Jeder endgültig codierte Minuten-Sprachausdruck, z.B. "viertel nach" wird als min_viertel = TRUE und min_nach = TRUE zwischengespeichert. Das sind die zu aktivierenden realsprachlichen Wörter. Die werden in einem zweiten Schritt zu Bitmustern der jeweiligen Matrixzeile umcodiert und per ODER-Verknüpfung in die Matrix implantiert.
Hoffentlich war das jetzt verständlich! Die Bits tanzen schon vor meinem inneren Auge, aber das verständlich niederzuschreiben .... 8-(
-
Die Wörter sind zwar in 5-Minuten-Schritten aber zusätzlich gibt es in den Ecken ja noch die Punkte für die Minuten 1,2,3 und 4 (bzw. 6,7,8 und 9)
Die einfachste Version wäre jetzt ein 60-stufiges Switch-Konstrukt (nicht Case-Anweisung ^^ ) für die Minuten, bzw. 12-stufig für die Stunden.
Bei den Minuten kann man mit ein paar Überlegungen und Verschachtelungen bestimmt ein paar Stufen einsparen.
Den Rest kann ich nachvollziehen da meine Überlegungen in die gleiche Richtung gehen. Ich wollte mir nur den Zwischenschritt über über =TRUE sparen und gleich die Bitmuster beeinflussen.
Zwischenstand zur Anzeige der Uhrzeit:
Das bcd2dec-Wandeln und umgekehrt funktioniert bei mir noch nicht wirklich. Ich bekomme immer nur eine 255 auf dem LCD angezeigt. Muss mich da nochmal mit den Datentypen und Codierungen auseinandersetzten. Aber nicht mehr heute. Mein Bett ruft.
-
Die Minuten-Punkte kann man mit MODULO 5 abhandeln.
Bei den 5-ern kommt Integer-DIVision zum Zuge, die Bitmuster könnten im Flash/EEPROM hinterlegt sein. Allerdings wird es vorkommen, daß man in mehrere Displayzeilen eingreifen muß, was ein zweidimensionales Array erforderlich macht.
Die Stunde kann ebenfalls ein Array indizieren, ggf. mit Korrektur "Viertel vor [Stunde+1]".
Damit kann man hoffentlich den Verzweigungs-Mammutbaum umgehen.
-
Und wenn ich davon nur die Hälfte auf Anhieb verstanden hätte würde ich dir wahrscheinlich zustimmen. :D
Aber dafür arbeite ich ja an solchen Projekten: Um neues zu lernen!
-
Oje, mittlerer Realitätsverlust zu nächtlicher Stunde. Mein vorheriges Posting war das Ergebnis wilden Umschreibens des ersten -gänzlich anderen- Lösungsansatzes und schlussendlich war IN MIR DRIN doch alles glasklar gewesen :)
MODULO ist der Rest einer Integerdivision. Der Ergebnisbereich einer MODULO 5-Funktion sind die ganzen Zahlen 0, 1, 2, 3 und 4.
Daraus machst du die Schaltbefehle für 0-4 Minutendötzchen.
Diese ziemlich elementare (das geht nicht an deine Adresse, gell) Funktion sollte idealerweise in jeder Hochsprache verfügbar sein. Pascal kennt MOD und DIV; wie das bei C ist, weiß ich nicht.
DIV entspricht der der Zuweisung eines Integer-Divisionsergebnisses auf eine Integervariable. Keine Rundung, der Divisionsrest wird verworfen.
MOD läßt sich (im hiesigen Kontext) durch [minuten - (minuten DIV 5) * 5] umschreiben.
Das (ganzzahlige) Divisionsergebnis von minuten / 5 ergibt die Anzahl abgelaufener 5-Minuten-Zeiteinheiten. Diese Zahl kann man als Index für ein Array verwenden, in dem die passenden Bitmuster für die Minuten-Texte stehen.
Da sich die Minuten-Texte auf mehrere Displayzeilen verteilen können, wird man je 5-Minuten-Text mehrere Bitmuster-Datensätze anlegen, müssen. Ein Datensatz könnte dann etwa so aussehen:
zzzz bbbb bbbb bbbb , wobei die b's das Bitmuster beschreiben und die z's die Zeilennummer enthalten. Das sind 16 Bit, die dir aber nicht reichen werden. Dann eben 32 Bit. Im Programmspeicher sollte das eigentlich Platz finden.
-
So.
Mein LCD gibt jetzt endlich eine brauchbare Zeit aus. Allerdings hatte ich wieder Probleme mit der i2c_start_wait();-Funktion. Das hat sich aber wie von allein auf einmal gegeben. Keine Ahnung woran das lag muss aber beobachtet werden.
Hier erstmal der Code der jetzt läuft:
Code:
#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include "i2cmaster/i2cmaster.h"
#include "lcdlibrary/lcd.h"
#define DS1307 0xD0
unsigned char time_s; // Sekundenvariable
unsigned char time_m; // Sekundenvariable
unsigned char time_h; // Sekundenvariable
unsigned char buffer[10];
unsigned char set_clock(unsigned char reg, unsigned char val)
{
if (i2c_start(DS1307+I2C_WRITE) != 0) return 1;
i2c_write(reg);
i2c_write(val);
i2c_stop();
return 0;
}
unsigned char get_time_s()
{
i2c_start_wait(DS1307+I2C_WRITE);
i2c_write(0x00);
i2c_stop();
i2c_start(DS1307+I2C_READ);
time_s = i2c_readNak();
i2c_stop();
return time_s;
}
unsigned char get_time_m()
{
i2c_start_wait(DS1307+I2C_WRITE);
i2c_write(0x01);
i2c_stop();
i2c_start(DS1307+I2C_READ);
time_m = i2c_readNak();
i2c_stop();
return time_m;
}
unsigned char get_time_h()
{
i2c_start_wait(DS1307+I2C_WRITE);
i2c_write(0x02);
i2c_stop();
i2c_start(DS1307+I2C_READ);
time_h = i2c_readNak();
i2c_stop();
return time_h;
}
int main (void)
{
DDRB = (1<<PB0); // PB0 als Ausgang
DDRC = ~(1<<PC3); // PC3 als Eingang
lcd_init(LCD_DISP_ON);
lcd_clrscr();
i2c_init();
lcd_puts("Bereit");
_delay_ms(1000);
lcd_clrscr();
// set_clock(0x02, 0x09);
// set_clock(0x01, 0x12);
// set_clock(0x00, 0x58);
while (1)
{
get_time_s();
get_time_m();
get_time_h();
sprintf(buffer, "Zeit: %02x:%02x:%02x", time_h, time_m, time_s);
lcd_puts(buffer);
lcd_gotoxy(0,0);
_delay_ms(100);
}
return 0;
}
Einzig die Spalte
Code:
sprintf(buffer, "Zeit: %02x:%02x:%02x", time_h, time_m, time_s);
habe ich mir aus dem Netz geklaut und noch nicht verstanden. Zusammen mit dieser zeile treten beim kompilieren auch zwei Warnungen auf:
Code:
../exp_RTC.c: In function 'main':
../exp_RTC.c:86: warning: pointer targets in passing argument 1 of 'sprintf' differ in signedness
../exp_RTC.c:87: warning: pointer targets in passing argument 1 of 'lcd_puts' differ in signedness
Kann mir bei diesen beiden Punkten grad mal jemand vom Schlauch helfen?
-
*push*
Ich brauch noch immer Hilfe bei der Codezeile und den daraus resultierenden Warnungen.
Zudem hab ich festgestellt, dass dieser BCD-Code doof ist :D
-
Hi,
die Warnung ist recht einfach erklärt: In den Header-Files sind die Funktionen lcd_puts und sprintf so definiert, dass sie ein "char" erwarten. Du übergibst aber ein "unsigned char".
Es funktioniert natürlich trotzdem, da du deinen Variablen maximalst eine 60 zuweist. Würdest du einen Wert größer 127 zuweisen würde für die Funktion die du aufrufst eine negative Zahl herauskommen, da dein Wert anders interpretiert wird. Daher die Warnungen.