Forum: Mikrocontroller und Digitale Elektronik Atmega48 multiplexing


von Markus G. (hulk85)


Lesenswert?

Hallo Leute,
ich baue gerade eine Uhr mit 6x /-Segmentanzeige auf. Diese Anzeige soll 
über multiplexing angesteuert werden. Ich hab es auch auf einem Atmega 
16 und Beispielprogramm hinbekommen, nur brauche ich den Code jetzt für 
den Atmega48.
Was muss ich von den Timereinstellungen anpassen? Ich brauche dringend 
Hilfe weil diese Uhr ein Geschenk wird und kommenden Freitag übergeben 
werden soll. Schaltung und Gehäuse ist alles fertig. Brauche nur noch 
das Programm..

Hab nur mal die Main-Schleif und die Timer-Interrupt eingefügt. Ich 
hoffe das ist ausreichend. Ich bin blutiger Anfänger und hoffe auf 
anständige Antworten. Denn auch mit Beispielprogrammen kann man lernen.

Vielen Dank im voraus.
1
int main()
2
{
3
  DDRB = 0xFF;                    // PortB alles als Ausgang
4
  DDRC |= (1 << DDC0) | (1 << DDC1) | (1 << DDC2);  // PortC 0..2 als Ausgang
5
  PORTC |= (1 << PC0) | (1 << PC1) | (1 << PC2);    // 0..2 High = Digits aus
6
7
  OCR1A = (uint16_t)(F_CPU/1024.0*0.005);      // Vergleichwert für 0,005s laden: Takt= 8MHz/1024 = 7812,5 Zählerschritte pro s
8
  TIMSK1 |= (1<<OCIE1A);               // Interrupt wenn Timer Vergleichswert erreicht
9
  TCCR1B = _BV(CS12) | _BV(CS10) | _BV(WGM12);  // Timer mit Div 1024 starten und Clear Counter on Compare Match
10
  sei();                      // IRQ Behandlung ein
11
12
  while (1)  // Endlos
13
  {
14
    for (uint16_t i = 0; i <= 999; i++)
15
    {
16
      zahl_ausgeben (i);
17
      delay_ms (100);
18
    }
19
  }
20
  return 0;
21
}
22
23
24
ISR (TIMER1_COMPA_vect)
25
{
26
  PORTC |= (1 << PC0) | (1 << PC1) | (1 << PC2);    // 0..2 High = Digits aus
27
28
  switch (position)    // Aktuelle Stelle ausgeben
29
  {
30
    case 0 : digit (hunderter, PC0); break;
31
    case 1 : digit (zehner, PC1); break;
32
    case 2 : digit (einer, PC2); break;
33
  }
34
35
  position ++;      // beim nächsten Mal nächstes Digit
36
  if (position == 3)     // wenn alle Digits durch 
37
    position = 0;    // von vorne beginnen
38
}

: Bearbeitet durch User
von holger (Gast)


Lesenswert?

>Ich hab es auch auf einem Atmega
>16 und Beispielprogramm hinbekommen, nur brauche ich den Code jetzt für
>den Atmega48.

>und kommenden Freitag übergeben werden soll.

Dann nimm doch den ATMega16. Ausserdem wird der Compiler
schon meckern wenn das Programm für einen Atmega48 compiliert wird.
Behebe die Fehlermeldungen heisst es dann.

von Karl H. (kbuchegg)


Lesenswert?

Markus G. schrieb:
> Hallo Leute,
> ich baue gerade eine Uhr mit 6x /-Segmentanzeige auf. Diese Anzeige soll
> über multiplexing angesteuert werden. Ich hab es auch auf einem Atmega
> 16 und Beispielprogramm hinbekommen, nur brauche ich den Code jetzt für
> den Atmega48.

Das nenne ich allerdings dreist

> Was muss ich von den Timereinstellungen anpassen?

In dem Beispielcode gibt es 2 Zeilen, die sich mit der Timer 
Konfiguration beschäftigen. Beide sind sogar noch kommentiert. Was 
denkst du, wie andere das 'Problem' wohl lösen würden? Sie würden sich 
das Datenblatt zum Mega48 rausholen und nachsehen, welche Einstellungen 
für den 48 gemacht werden müssen um dasselbe zu erreichen. Sehr 
wahrscheinlich heissen die Register und die zu setzenden Bits sogar 
gleich oder zumindest ähnlich.

Und jetzt erklär mal, darum du selbst das nicht durchführen kannst. 
Zumal du die Hardware vor dir hast und das ganze dann sogar auch noch 
live und in Farbe ausprobieren kannst.

Das allerdings ...
> Ich bin blutiger Anfänger
... ist kein Argument.
> Denn auch mit Beispielprogrammen kann man lernen.
Dann wird es Zeit, dass du lernst mit dem Datenblatt zu arbeiten.

: Bearbeitet durch User
von Markus G. (hulk85)


Lesenswert?

Ich mach schon seit zwei Wochen mit dem Controller rum es klappt nicht.

Trotzdem Danke..

von Marco G. (grmg2010)


Lesenswert?

Ist dein geposteter Code der Beispiel-Code auf dem ATMEGA 16? Hast du 
schon mal versucht diesen für den ATMEGA48 zu kompilieren? Wie bereits 
erwähnt, sollten die Register im 16er und 48er sehr ähnlich heißen, oder 
sogar gleich heißen.
WEnn du kompiliert hast, welche Fehlermeldungen treten auf, die dich an 
der Fertigstellung hindern?

von R. R. (elec-lisper)


Lesenswert?

Beim geposteten Code muss ich was übersehen haben.
Wo ist denn die Definition von "digit()" und "zahl_ausgeben()"?
Die Variable "position" ist auch typlos. Das KANN nicht funktionieren,
wenn die Variable keine Deklaration mit einem Typ hat - komisch, dass
der Compiler gar nicht gemeckert hat?
Von der Benutzung her, würde ich auf "int" tippen.

von oldmax (Gast)


Lesenswert?

Hi
Du willst etwas lernen? Nun ja, mit C-Code kann ich nicht dienen, aber 
Ich denke, ich kann trotzdem helfen. Um eine Anzeige auf 7-Segment zu 
bringen, brauchst du den Segment -Code. Den erhälst du aus einer 
Tabelle. z.B.
Code_Array.
Dort schreibst du angefangen von 0 die zugehörigen Ausgänge der 
Segmentansteuerung rein. Auch wieder z.B. für 0 -> 00111111.
Wenn die Bitfolge
0=a
1=b
2=c
3=d
4=e
5=f
6=g
7=x nicht benutzt.
Angenommen, du hast eine Ziffer zwischen 0 und 9 so ist einfach die 
Startadresse des Code_Array in ein Adressregister zu laden und den Wert 
der Ziffer dazu addieren. Damit habe ich den Code, der in einen 
Ausgabepuffer geschrieben wird. Die Multiplexroutine greift nun nur noch 
auf den Ausgabepuffer zu. Auch hier ist zu beachten. Zuerst Anzeige 
komplett dunkel (alle Zifferansteuerungen aus). Nächsten Code aus 
Ausgabepuffer auf IO-Pins legen. nächste Ziffer selektiern und den 
Selectausgang aktivieren. Damit verhinderst du, das durch Nachleuchten 
die Ziffern schlecht eerkennbar sind. Den Multiplexer läßt du vom Timer 
anstoßen, so alle 2-5 ms. Deine darzustellenden Zahlen hälst du in einem 
Wertepuffer. Die Codewandlung erfolgt nur, wenn der Wertepuffer sich 
ändert.
Und nun nimm deinen Code und schau nach, welche Abschnitte wie 
abgewandelt werden müssen, um das hier beschriebene Vorgehen zu 
erreichen.
Gruß oldmax

von MWS (Gast)


Lesenswert?

Markus G. schrieb:
> Ich hab es auch auf einem Atmega
> 16 und Beispielprogramm hinbekommen, nur brauche ich den Code jetzt für
> den Atmega48.

ATM16 und 48 sind ausreichend gleich, die Vektorenbezeichnung ist's 
auch, der identische Code müsste bei richtig eingestelltem Target ohne 
Weiteres korrekt compilieren. Ist das Target dagegen falsch, geht 
aufgrund unterschiedlicher Registeradressen gar nichts.

Selbst die Fuses dürften keinen großen Einfluss haben, denn bei 
laufendem Controller und falscher CKDIV8-Fuse ist der eben nur zu 
langsam, macht aber trotzdem was. Der beliebte Anfängerfehler das 
JTAG-Interface nicht abzuschalten, fällt aufgrund nicht vorhandenem 
JTAGs beim ATM48 auch aus.

Bleibt also nur ein falsch eingestelltes Target oder ein Fehler in der 
Hardware.

von Peter D. (peda)


Lesenswert?

Markus G. schrieb:
> Was muss ich von den Timereinstellungen anpassen?

Die AVR Datenblätter sind sehr gut aufgebaut, zu jedem Abschnitt gibt es 
eine Registerbeschreibung.
Die Timerregister und Bits unterscheiden sich leicht.
Einfach nur die Register nacheinander setzen:
- Modus setzen
- Interrupts enablen
- Timer starten (Prescaler setzen).

von Axel S. (a-za-z0-9)


Lesenswert?

Markus G. schrieb:

> Ich bin blutiger Anfänger
...
> ich baue gerade eine Uhr mit 6x /-Segmentanzeige auf. Diese Anzeige soll
> über multiplexing angesteuert werden. Ich hab es auch auf einem Atmega
> 16 und Beispielprogramm hinbekommen, nur brauche ich den Code jetzt für
> den Atmega48.

Aha. Wenn du ein blutiger Anfänger bist, woher hast du dann die 
Schaltung und das Programm für den ATmega16? Wenn du das irgendwo 
abgekupfert hast (wogegen ja erstmal nichts prinzipiell einzuwenden ist) 
warum hast du es dann nicht 1:1 nachgebaut?

> Was muss ich von den Timereinstellungen anpassen? Ich brauche dringend
> Hilfe weil diese Uhr ein Geschenk wird und kommenden Freitag übergeben
> werden soll. Schaltung und Gehäuse ist alles fertig. Brauche nur noch
> das Programm..

Ja, so ähnlich scheinen die Leute bei VW auch gedacht zu haben. "Wir 
haben das Fahrwerk und den Motor schon fertig, blöderweise schafft er 
bloß noch nicht die Abgasnorm einzuhalten ..."

> Hab nur mal die Main-Schleif und die Timer-Interrupt eingefügt. Ich
> hoffe das ist ausreichend.

Nein ist es nicht.

Es ist noch nicht mal klar, wobei genau du Hilfe brauchst.

Der ATmega16 hat z.B. 40 Pins, der ATmega48 nur 28. Konntest du denn 
überhaupt die Hardware an die gleichen Ports anschließen? Und falls ja, 
dann müßtest du vermutlich nur mal das Programm mit den offensichtlichen 
Änderungen (z.B. MCU-Typ ATmega48) compilieren. Hast du dabei Fehler 
bekommen? Warum zeigst du dann nicht die Fehler und das ganze Programm?

Und nein, nimm das jetzt nicht als Zusage daß ich (oder sonst jemand 
hier) dir das fertig auf dem Silbertablett serviert, selbst wenn du 
jetzt mal in die Pötte kommst und alle Informationen lieferst.

Denn es ist ganz allein deine Schuld. Wenn du schon etwas nachbaust das 
eindeutig deinen Horizont übersteigt, dann mußt du es auch exakt 
nachbauen.

von Peter D. (peda)


Lesenswert?

Markus G. schrieb:
> Hab nur mal die Main-Schleif und die Timer-Interrupt eingefügt. Ich
> hoffe das ist ausreichend.

Ich sehe da weder eine Uhr, noch das Multiplexen von 6 Anzeigen.
Dafür ne Menge unbekannter Funktionen, die aufgerufen werden.

Du mußt schon was compilierbares zeigen (als Anhang).
Und natürlich den kompletten Schaltplan, wir können ja nicht hellsehen.

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
Noch kein Account? Hier anmelden.