Hi,
ich bin kürzlich in das Thema AVR Programmierung eingestiegen.
Ich verwende den ATTINY2313a und wollte zur Übung auf einem alphanum.
Display mir mittels DCF Empfänger die Uhrzeit anzeigen lassen. Ich weiß,
dass es dazu zahlreiche Foreneinträge gibt, allerdings wollte ich zum
Üben die Funktionalität selbst implementieren.
Das Display läuft soweit, allerdings schlägt die Abfrage des Busyflags
aus irgendeinem Grund fehl (wenn ich nach der Displayinitialisierung das
BF mit busycheck() aufrufe funktionierts nicht...). Das Display ist
korrekt angeschlossen und wird mit 8 Datenleitungen verwendet.
1
voidbusycheck(void)
2
{
3
PORTD|=(1<<RW);//Daten lesen
4
PORTD&=~(1<<RS);//Befehl
5
6
PORTD|=(1<<E);
7
DDRB&=~(1<<DATA7);//Datenbit7 als Eingang --> Busyflag
8
9
while(PINB&(1<<DATA7))
10
{
11
PORTD&=~(1<<E);
12
_delay_us(1);
13
PORTD|=(1<<E);
14
}
15
DDRB|=(1<<DATA7);//Datenbit 7 wieder als Ausgang definieren
16
}
Das Problem habe ich durch eine Wartezeit umgangen... über eine
Problemlösung wäre ich aber sehr dankbar :)
Das wesentlich schlimmere Problem ist die DCF Decodierung... ich weiß
echt nichtmehr weiter...
ich habe folgenden Quelltext:
1
ISR(INT0_vect)
2
{
3
staticcharsyncevent=0;
4
5
uint8_tcounter=0;
6
uint8_ti;
7
shortrawdata[59];
8
charbuffer[sizeof(uint32_t)*8+1];
9
charminbuffer[20];
10
intminute;
11
12
if(syncevent==0)
13
{
14
while((PIND&(1<<PINDCF))==0)
15
{
16
_delay_ms(10);
17
counter++;
18
if(counter>172)
19
{
20
syncevent=1;
21
PORTD|=(1<<PIND6);
22
break;
23
}
24
}
25
}
26
else
27
{
28
for(i=0;i<60;i++)
29
{
30
counter=0;
31
while((PIND&(1<<PINDCF))==0);//Warten auf High
32
33
while(PIND&(1<<PINDCF))//High Länge ermitteln
34
{
35
_delay_ms(1);
36
counter++;
37
38
}
39
if(counter>170)//Signallaenge groesser 170 ms, dann logisch 1, sonst 0
Ich kann mir die einzelnen Bits wunderbar auf dem Display anzeigen (Oszi
hängt dran die Daten passen auch :) ):
string2display(itoa(rawdata[i],buffer,2),ZEILE1+i);
Wenn ich die Problemzeile allerdings mit drin habe, funktioniert das
nichtmehr, das Minutenergebnis kommt auch nicht...(das Display bleibt
leer)
Auch wenn ich anderweitig die Variable minute verwende (z.B. if-Abfrage)
tritt der Fehler auf...
Weiß villeicht irgendwer wo es hängt?
Achja PIND6 schaltet einfach ein LED als Feedback...die geht mit der
Problemzeile auch nicht mehr...
Hi!
Also, bei einem 8-Bit Datenbus am Port schaltet man immer alle Bits auf
Eingang, wenn man etwas lesen will. Auch, wenn man hinterher nur ein Bit
davon auswertet. Andernfalls treiben im Worst-Case sieben Leitungen
gegeneinander.
Carsten
Ich bin nicht der Spezialist für die Feinheiten vopn C/C++, aber
irgendwie finde ich die Puffergröße 20 für minbuffer etwas schräg. Ich
würde den Puffer einfach mal Sicherheitshalber 33 Bytes groß machen, um
sicher zu gehen, dass es da keinen Überlauf gibt. Oder als Basis bei der
Konvertierung "10" statt "2" nehmen.
kobold254 schrieb:> short rawdata[59];> char buffer [sizeof(uint32_t)*8+1];> char minbuffer [20];> int minute;
Wie willst Du 173 Byte auf nem MC mit 128 Byte RAM unterbringen?
Und etwas Stack sollte auch noch sein.
Schonmal danke für die vielen Tips werden das ganze heute Abend mal
ausprobieren ;):)
@Carsten Wille: Ich werds versuchen aber generell sollte es doch möglich
sein jedes Bit eines Ports anders zu verwenden oder?
@Gregor Ottmann: Werde die Basis auf 10 ändern, war mein Fehler beim
Posten, habe schon so viel probiert, habe die falsche Basis drin gehabt
@Peter Dannegger: Guter Einwand :):D ich frag mich nur wieso des AVR
Studio nicht meckert?:(
Melde mich später wieder, wenn die Veränderungen eingeflossen sind ;)
kobold254 schrieb:> Schonmal danke für die vielen Tips werden das ganze heute Abend mal> ausprobieren ;):)>> @Carsten Wille: Ich werds versuchen aber generell sollte es doch möglich> sein jedes Bit eines Ports anders zu verwenden oder?
Natürlich.
Aber du bist ja mit dem µC nicht alleine.
Was macht denn das LCD, wenn du mittels RW es beauftragst, seine
Informationen rauszugeben? Es schaltet seinerseits seine 8
Datenleitungen auf Ausgang. Damit steht es
1
µC LCD
2
+--------+ +---------+
3
| DB7 | <---------< | DB7 |
4
| DB6 | >---------< | DB6 |
5
| DB5 | >---------< | DB5 |
6
| DB4 | >---------< | DB4 |
7
| DB3 | >---------< | DB3 |
8
| DB2 | >---------< | DB2 |
9
| DB1 | >---------< | DB1 |
10
| DB0 | >---------< | DB0 |
11
+--------+ +---------+
DB7 hast du korrekt am µC auf Eingang umgeschaltet. Aber was ist mit dem
Rest? Das dich die anderen Bits nicht interessieren, interessiert ja das
LCD nicht. Das schaltet seine restlichen Bit-Leitungen ebenfalls auf
Ausgang und gibt dort seine Daten drauf. Nur das eben der µC seine
restlichen Portpins ebenfalls auf Ausgang geschaltet hat. Sagen wir mal
das LCD möchte DB2 auf 1 ziehen, der µC möchte die Leitung aber auf 0
ziehen (weil da zufällig vom letzten mal nach ein 0 Bit am Portpin
liegt). Nicht gut. 2 Ausgänge lässt man nie gegeneinander arbeiten!
...ich bin kürzlich in das Thema AVR Programmierung eingestiegen.
Falsches Projekt für einen Einstieg:
- alphanum.Display mir mittels
- DCF Empfänger die
- Uhrzeit anzeigen lassen
Gleich 3 Wünsche auf einmal. Viel zu viel, ertsmal eine LED blinken
lassen.
Projekt in die 3 Teilaufgaben aufteilen und einzeln ausbauen.
Yve
Durch die Änderung am Port funktioniert der Busy-Check --> erledigt
vielen Dank :)
Habe den Code umgeschrieben und verwende nun statt des Arrays eine
uint_64 in die ich die Daten shifte... leider ohne Erfolg :(
@Yvonne J.: Blinkende LED habe ich davor gemacht ;) darüber hinaus habe
ich schon einiges auf dem RPi programmiert ;) (u.a. auch das Display,
allerdings ohne Busyflag und im 4-Bit Betrieb)
Habe den gesamten, aktuellen Quellcode mal in den Anhang ;)
BTW: die Shiftvariante braucht einiges mehr an Speicher, als die
Variante mit dem short-array
kobold254 schrieb:> Habe den Code umgeschrieben und verwende nun statt des Arrays eine> uint_64 in die ich die Daten shifte... leider ohne Erfolg :(
schau dir das mal an:
Beitrag "DCF77 Uhr in C mit ATtiny26"http://www.mikrocontroller.net/attachment/80829/dcf77.zip
kann man ne Menge von lernen
Peter Dannegger schrieb:> Wie willst Du 173 Byte auf nem MC mit 128 Byte RAM unterbringen?> Und etwas Stack sollte auch noch sein.
danke Peter, ewig nix von dir gelesen :-) wir hatten auch mal
telefoniert)
ich habe auch am PC angefangen das auszuwerten einfach das Bit in einen
Joystikport gegeben und alle 60ms per IRQ die Bits gelesen
PC Speicher satt und man kann locker reservieren und schieben, mit 60ms
Interrupt ist es zwar etwas grob geht aber
am AVR kann man zum spielen ja auch größere nehmen wo der Speiche nicht
so knapp ist.
kobold254 schrieb:> uint_64 in die ich die Daten shifte... leider ohne Erfolg :(
Was heisst 'ohne Erfolg'?
Tja.
Du gehst die Sache ein wenig naiv an, indem du annimmst du könntest das
aus dem Stegreif fehlerfrei schreiben.
Wenn du schon ein wenig auf dem Pi programmiert hast, solltest du
eigentlich wissen, dass man Programme schrittweise programmiert.
Erster Schritt: kriegst du eine Synchronisation auf die fehlende
Sekundenmarke am Anfang einer Minute? Wenn nein, warum nicht?
Das die ganze ISR genau so gemacht ist, wie man das nicht macht, brauch
ich wohl nicht extra dazu sagen. So kannst du dir den Interrupt auch
gleich sparen und alles in der Hauptschleife machen. Wäre einfacher.
Synchronisation funktioniert ja ;) und die Bedingungen werden auch
richtig aufgerufen ;) (Die LED am PIND6 zeigt mir das an, ich vergleiche
mitm Oszi)
Ich weiß, dass das nicht aus dem Stegreif zu schreiben ist, deshalb
sitze ich ja auch schon einige Zeit daran und habe hier um Hilfe gefragt
:)
Ich gebe zu die ISR ist echt nicht schön :(... aber ist ja auch erstmal
zum üben gedacht ;)
Ich werde mir mal den anderen Quelltext anschauen, über weitere Hilfe
würde ich mich dennoch sehr freuen :)
>Erster Schritt: kriegst du eine Synchronisation auf die fehlende>Sekundenmarke am Anfang einer Minute?>Synchronisation funktioniert ja ;)
Dieses nun wundert mich, denn die Tastlücke sitzt am Ende der Minute.