Forum: Mikrocontroller und Digitale Elektronik Ansteuerung einer 7-Segment-Anzeige mit ATmega8 funktioniert nicht mehr


von Nils ‫. (n-regen)


Angehängte Dateien:

Lesenswert?

Hallo!

Kann sich bitte einer von euch meinen Quelltext anschauen und mir sagen, 
was ich falsch gemacht habe?
Ursprünglich hat dieser Code mal einen ATmega8 dazu gebracht, YEAH auf 
einer 7-Segment-Anzeige auszugeben.
Dann habe ich die Anzeige in eine Unterfunktion anzeigen() ausgelagert - 
und schon leuchtet nur noch die erste Ziffer der Anzeige (Punkt und alle 
Segmente außer dem Obersten).
Die Verschaltung der Anzeige seht ihr im angehängten Schaltplan (die 
Ziffern hängen in Wirklichkeit allerdings zusammen).
1
#include <avr/io.h>
2
#ifndef F_CPU
3
#define F_CPU 1000000UL  //Taktfrequenz einstellen, damit _delay_ms() funktioniert
4
#endif
5
#include <util/delay.h>
6
#include <stdint.h>
7
8
////
9
////Beginn des neuen Teils
10
////
11
12
uint8_t bwert;  //wird in anzeigen() verwendet
13
uint8_t cwert;  //wird in anzeigen() verwendet
14
15
void anzeigen(uint8_t stelle, char zeichen)
16
{
17
  switch (stelle)  //der Stelle, die angesteuert werden soll, + geben, die anderen ausschalten
18
  {
19
    case 1: PORTD = ((PORTD && 0b11001100) || 0b00000001);
20
        break;
21
    case 2: PORTD = ((PORTD && 0b11001100) || 0b00000010);
22
        break;
23
    case 3: PORTD = ((PORTD && 0b11001100) || 0b00010000);
24
        break;
25
    case 4: PORTD = ((PORTD && 0b11001100) || 0b00100000);
26
        break;
27
  }
28
  switch (zeichen)  //den benötigten Segmentteilen - geben, die anderen ausschalten
29
  {
30
    case 'Y':  {
31
            bwert = 0b11010001;
32
            cwert = 0b11001111;
33
            break;
34
          }
35
    case 'E':  {
36
            bwert = 0b11100100;
37
            cwert = 0b11001111;
38
            break;
39
          }
40
    case 'A':  {
41
            bwert = 0b11000000;
42
            cwert = 0b11011111;
43
            break;
44
          }
45
    case 'H':  {
46
            bwert = 0b11000001;
47
            cwert = 0b11011111;
48
            break;
49
          }
50
  }
51
  PORTB = ((PORTB && 0b11000000) || bwert);
52
  PORTC = ((PORTC && 0b11001111) || cwert);
53
}
54
55
////
56
////Ende des neuen Teils
57
////
58
59
int main(void)
60
{
61
  DDRB = 0xFF;
62
  DDRC = 0xFF;
63
  DDRD = 0xFF;
64
  while (1)
65
  {
66
    /********
67
    Der alte Code zum YEAH-Erzeugen:
68
    PORTB = 0b00010001;
69
    PORTC = 0b00100000;
70
    PORTD = 0b00000001;
71
    _delay_ms(3);
72
    PORTB = 0b00100100;
73
    PORTC = 0b00100000;
74
    PORTD = 0b00000010;
75
    _delay_ms(3);
76
    PORTB = 0b00000000;
77
    PORTC = 0b00110000;
78
    PORTD = 0b00010000;
79
    _delay_ms(3);
80
    PORTB = 0b00000001;
81
    PORTC = 0b00110000;
82
    PORTD = 0b00100000;
83
    _delay_ms(3);
84
    ********/
85
86
    ////Der neue Code zum YEAH-Erzeugen
87
    anzeigen(1, 'Y');
88
    _delay_ms(3);
89
    anzeigen(2, 'E');
90
    _delay_ms(3);
91
    anzeigen(3, 'A');
92
    _delay_ms(3);
93
    anzeigen(4, 'H');
94
    _delay_ms(3);
95
    ////
96
  }
97
  return 0;
98
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Probiers mal so:
1
  PORTB = ((PORTB & 0b11000000) | bwert);
2
  PORTC = ((PORTC & 0b11001111) | cwert);
Stichworte: logische Verknüpfung und bitweise Verknüpfung.

von Ben (Gast)


Lesenswert?

zuerst hoff ich mal die anzeigen sind low-current-typen und die 
vorwiderstände hast du nur im schaltplan weggelassen?

von Nils ‫. (n-regen)


Lesenswert?

@Lothar:
Das war tatsächlich der Fehler. Ich habe die || durch | und && durch & 
ersetzt - und die Anzeige funktioniert wieder.
Vielen Dank für deine Hilfe.

@Ben:
Ich weiß nicht, ob das eine low-current-Anzeige ist, allerdings wird der 
ATmega8 kein bisschen warm (und das müsste er bei Überlastung doch 
werden, oder?).
Außerdem: Dadurch, dass ich die Anzeige multiplexe, sind die 
Zeichen-Pins (PD0,1,4,5) sowieso nur ein Viertel der Zeit belastet, also 
müsste ich ja theoretisch bis zu 80mA Last dran hängen können.
Zu den Vorwiderständen: Ich hatte gerade keine vier 150 Ohm-Widerstände 
da, also habe ich einfach je eine LED zwischen die Anode jedes Zeichens 
und den entsprechenden Pin am ATmega gehängt.

von Falk B. (falk)


Lesenswert?

@  Nils S. (n-regen)

>Ich weiß nicht, ob das eine low-current-Anzeige ist, allerdings wird der
>ATmega8 kein bisschen warm (und das müsste er bei Überlastung doch
>werden, oder?).

Ohje. Du hast mehr Glück als Verstand. Die Ausgänge vom AVR haben so um 
die 30 Ohm Ausgangswderstnd und begrenzen dadurch den Strom.

>Außerdem: Dadurch, dass ich die Anzeige multiplexe, sind die
>Zeichen-Pins (PD0,1,4,5) sowieso nur ein Viertel der Zeit belastet, also
>müsste ich ja theoretisch bis zu 80mA Last dran hängen können.

Nö.

>Zu den Vorwiderständen: Ich hatte gerade keine vier 150 Ohm-Widerstände
>da, also habe ich einfach je eine LED zwischen die Anode jedes Zeichens
>und den entsprechenden Pin am ATmega gehängt.

[ ] Du kennst den Unterschied zwischen einer Diode und einem Widerstand.

Naja

von Ben (Gast)


Lesenswert?

na klasse...

also da besteht wohl noch etwas verbesserungsbedarf. hattest du 
wenigstens einen netztrafo zur hand? oder läuft der atmega direkt an 
230V~?

schon komisch auf was für ideen manche leute kommen.

die strombegrenzung gehört übrigens nicht in die gemeinsame 
stromversorgung der segmente (in deinem fall die anode). bei dir braucht 
jede kathode ihren widerstand. da du die anzeige gemultiplext betreibst 
reichen 7 stück am "kathode-port" des atmega. wirst staunen, da 
verschwindet auch dein problem, daß die anzeigen bei verschienen zeichen 
verschieden hell leuchten.

und was die spitzenströme angeht hast du prinzipiell recht, da die 
effektive einschaltzeit nur 25% sind. 80mA find ich aber dennoch ganz 
schön viel für einen einzigen pin. beim nächsten mal einfach vier 
PNP-transistoren (mit basiswiderständen bitte!!) opfern bzw. zur hand 
haben und du kannst sicher sein, daß es dauerhaft funktioniert. mußt nur 
aufpassen, daß die PNP-transistoren das signal invertieren, sprich bei 
logisch 0 am ausgang hast du 5v auf der segmentanzeige.

von Karl H. (kbuchegg)


Lesenswert?

Ben schrieb:

> und was die spitzenströme angeht hast du prinzipiell recht, da die
> effektive einschaltzeit nur 25% sind.

Allerdings muss der Strom ja auch durch die Spannungsanschlusspins des 
µC erst mal in den µC hineinkommen. Es gibt also nicht nur die eine 
Grenze, weiviel Strom durch einen einzelnen Pin rauskommen darf, sondern 
auch noch die Grenze, dass der Gesamtstrom eine Grenze nicht 
überschreiten darf.

von Ben (Gast)


Lesenswert?

die steht im datenblatt, ich glaub 20mA pro pin, 100mA pro port und 200 
oder 300mA fürs ganze gerät.

von Nils ‫. (n-regen)


Lesenswert?

Die "Absolute Maximum Ratings" sind laut ATmega8-Datenblatt 05/09, Seite 
242 40mA pro I/O-Pin und 300mA bei den VCC- und GND-Pins.
Und dann schreiben sie, dass ein Port kurzzeitig auch mehr als 20mA 
aushält, dass aber dabei alle Ports zusammen nicht mit mehr als 300mA, 
die Pins C0-C5 nicht mit mehr als 100mA und die Ports B0-B7, C6, D0-D7 
und XTAL2 nicht mit mehr als 200mA belastet werden dürfen.

Da meine Anzeige funktioniert, werde ich die Schaltung nicht mehr 
umbauen (das würde außerdem entgültig zu Chaos auf meiner Platine 
führen), aber bei der nächsten Anzeige kann ich ja vor dem Löten mal 
etwas messen und rechnen.

von pyotr (Gast)


Lesenswert?

/Da meine Anzeige funktioniert, werde ich die Schaltung nicht mehr
umbauen.../

Naja, die Frage ist, wie lange die funktioniert...

von Vlad T. (vlad_tepesch)


Lesenswert?

Nils S. schrieb:
> Zu den Vorwiderständen: Ich hatte gerade keine vier 150 Ohm-Widerstände
> da, also habe ich einfach je eine LED zwischen die Anode jedes Zeichens
> und den entsprechenden Pin am ATmega gehängt.

rofl

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.