Uhr bauen - Fragen zum Anschluss und Code

Servus,
ich hab mal mim Simulator (AVR Studio 4) für den ATMega16 eine Uhr geschrieben (Code am Ende).

Jetzt sind mir ein paar Fragen zum Anschluss gekommen. Wenn ich z.B. PB0 auf 1 setze (sprich PORTB = 0x01:wink: wird dann der Pin 1 mit GND oder VCC verbunden (habe noch keine Platform wo ich das testen kann…)?
Ich werd aus dem Datasheet in dem Punkt nicht schlau.

Benötige ich Widerstände zwischen den Pins und den Trasistoren für die 7-Segment-Anzeige? Ich komm irgendwie nicht drauf, welcher Strom zwischen Basis und PinX herrscht…

Was den Code Betrifft:
Standardmäßige Bezeichnung der Segmente a-h (inklusive Punkt) ist PortB, PINA zwei Taster und Multiplexing für die vier anzeigen.

#include
#include
#include

//Variablen für die Zeit
volatile unsigned int millisekunden;
volatile unsigned int sekunde;
volatile unsigned int minute;
volatile unsigned int stunde;
volatile unsigned int minute_dekade;
volatile unsigned int stunde_dekade;
volatile unsigned char cache_a=0;
unsigned int lastpress_hou = 0;
unsigned int lastpress_min = 0;
int main(void)
{
// Timer 0 konfigurieren
TCCR0 = 9;
OCR0 = 200-1;
TIMSK |= (12500?toSegment(stunde)+128:toSegment(stunde));
cache_a=2;
break;
case 2:
cache_b=toSegment(minute_dekade);
cache_a=4;
break;
case 3:
cache_b=toSegment(minute);
cache_a=8;
panel=-1;
break;
}
PORTB=cache_b;
PORTA=cache_a;
panel++;
}
}

int toSegment(unsigned int nr){
unsigned int rtn=0;
switch(nr){
case 0:rtn=63;break;
case 1:rtn=6;break;
case 2:rtn=91;break;
case 3:rtn=79;break;
case 4:rtn=102;break;
case 5:rtn=109;break;
case 6:rtn=124;break;
case 7:rtn=7;break;
case 8:rtn=127;break;
case 9:rtn=103;break;
}
return rtn;
}

//
ISR (TIMER0_COMP_vect)
{
millisekunden++;
switch(PINA-cache_a){
case 16:
if((millisekunden5000){
lastpress_hou=millisekunden;
stunde++;
if(stunde == 10){
stunde_dekade++;
stunde=0;
}
if(stunde==4&&stunde_dekade==2){
stunde_dekade=0;
stunde=0;
}
}
break;
case 32:
if((millisekunden5000){
lastpress_min=millisekunden;
minute++;
if(minute == 10){
minute = 0;
minute_dekade++;
if(minute_dekade==6){
minute_dekade=0;
}
}
}
break;
}
if(millisekunden == 5000)
{
sekunde++;
millisekunden = 0;
if(sekunde == 60){
minute++;
sekunde = 0;
}
if(minute == 10){
minute = 0;
minute_dekade++;
if(minute_dekade==6){
stunde++;
minute_dekade=0;
}

}
if(stunde == 10){
stunde_dekade++;
stunde=0;
}
if(stunde==4&&stunde_dekade==2){
stunde_dekade=0;
stunde=0;
}
}
}

Sorry, ich vergesse immer das „“ nicht wie für mich gewollt, funktioniert.

#include
#include
#include

//Variablen für die Zeit
volatile unsigned int millisekunden;
volatile unsigned int sekunde;
volatile unsigned int minute;
volatile unsigned int stunde;
volatile unsigned int minute_dekade;
volatile unsigned int stunde_dekade;
volatile unsigned char cache_a=0;
unsigned int lastpress_hou = 0;
unsigned int lastpress_min = 0;
int main(void)
{
// Timer 0 konfigurieren
TCCR0 = 9;
OCR0 = 200-1;
TIMSK |= (12500?toSegment(stunde)+128:toSegment(stunde));
cache_a=2;
break;
case 2:
cache_b=toSegment(minute_dekade);
cache_a=4;
break;
case 3:
cache_b=toSegment(minute);
cache_a=8;
panel=-1;
break;
}
PORTB=cache_b;
PORTA=cache_a;
panel++;
}
}

int toSegment(unsigned int nr){
unsigned int rtn=0;
switch(nr){
case 0:rtn=63;break;
case 1:rtn=6;break;
case 2:rtn=91;break;
case 3:rtn=79;break;
case 4:rtn=102;break;
case 5:rtn=109;break;
case 6:rtn=124;break;
case 7:rtn=7;break;
case 8:rtn=127;break;
case 9:rtn=103;break;
}
return rtn;
}

//
ISR (TIMER0_COMP_vect)
{
millisekunden++;
switch(PINA-cache_a){
case 16:
if((millisekunden5000){
lastpress_hou=millisekunden;
stunde++;
if(stunde == 10){
stunde_dekade++;
stunde=0;
}
if(stunde==4&&stunde_dekade==2){
stunde_dekade=0;
stunde=0;
}
}
break;
case 32:
if((millisekunden5000){
lastpress_min=millisekunden;
minute++;
if(minute == 10){
minute = 0;
minute_dekade++;
if(minute_dekade==6){
minute_dekade=0;
}
}
}
break;
}
if(millisekunden == 5000)
{
sekunde++;
millisekunden = 0;
if(sekunde == 60){
minute++;
sekunde = 0;
}
if(minute == 10){
minute = 0;
minute_dekade++;
if(minute_dekade==6){
stunde++;
minute_dekade=0;
}

}
if(stunde == 10){
stunde_dekade++;
stunde=0;
}
if(stunde==4&&stunde_dekade==2){
stunde_dekade=0;
stunde=0;
}
}
}

grtz
michi

Hallo,
kommt auf den Ausgangstyp des jeweiligen Pins an, in der Regel sind es Gegentaktausgänge, dann liefert Portbit = 0 am Ausgang 0V, Portbit = 1 entsprechend VCC (bin mir grad nicht sicher, ob der erwähnte Typ überhaupt andere Ausgangsarten hat, arbeite meistens mit Microchip)

Bei der Berechnung der Basisvorwiderstände für die Schalttransistoren kann man also von VCC als Steuerspannung ausgehen. Damit kann man dann schön brav nach Transistorkennlinie rechnen (oder man weiß aus Erfahrung, dass da für einen Kleinsignaltransistor und VCC = 5V als Steuerspannung eh so um die 15kOhm Basisvorwiderstand rauskommt)

Zum Code kann ich leider nix sagen, programmier nur in Assembler.

Gruß

Passenger1966

Hallo,

Wenn ich z.B. PB0 auf 1 setze (sprich PORTB = 0x01:wink: wird dann der
Pin 1 mit GND oder VCC verbunden

Dann wird Pin 0 von Port B mit VCC verbunden. PB 0 bezeichnet Pin 0 , nicht 1.

Ich werd aus dem Datasheet in dem Punkt nicht schlau.

Darin ist zu lesen (Kapitel „I/O ports“, ziemlich am Anfang):

If PORTxn is written logic one when the pin is configured as an output pin, the port pin is driven high (one). If PORTxn is written logic zero when the pin is configured as an output pin, the port pin is driven low (zero).

high = VCC (oder in Maßen GND)

Benötige ich Widerstände zwischen den Pins und den Trasistoren
für die 7-Segment-Anzeige?

Ja. In die Leitung zur Basis jedes Transistors musst Du einen Widerstand schalten. Wie groß der sein muss, kannst Du anhand des Datenblatts des Transistors berechnen. Wenn Du normale, so 1 bis 2 cm große LED-Anzeigen ansteuern willst, wirst Du das wahrscheinlich mit einem BC337 oder BC546 oder ähnlich tun wollen, und dann kannst Du 4.7 kΩ als „Hausnummer“ für den Basisvorwiderstand nehmen. Zusätzlich braucht dann jedes Segment natürlich auch noch einen Vorwiderstand, z. B. 220 Ω, abhängig vom Betriebsstrom der LEDs.

Ich komm irgendwie nicht drauf,
welcher Strom zwischen Basis und PinX herrscht…

Ungefähr I = VCC/Basisvorwiderstand. Dieser Strom sollte etwa 1 % des Stroms durch die LEDs der Anzeigen groß sein.

Was den Code Betrifft:

Der Code ist grauenvoll. Eigentlich ist daran fast alles unklar:

In welchem Zeitintervall die ISR TIMER0_COMP_vect aufgerufen wird, ist unklar.

Was „TCCR0 = 9“ bewirkt, ist unklar (warum verwendest Du nicht die Bitnamen?).

Außerdem geht aus dem Code hervor, dass Du die Anzeigen mit extrem hoher Geschwindigkeit multiplext, geschätzt ein halbes MHz. Ob und wenn ja warum Du das willst, ist unklar (400 Hz Multiplexfrequenz reicht bei vier Panels völlig).

Warum realisierst Du die Funktion toSegment über ein switch-case-Konstrukt, wo es ein simples Konstantenarray auch tun würde?

Die Bedeutung von case 16 und case 32 in der ISR ist unklar.

Die Bedeutung von lastpress_min ist unklar.

Wenn Du hier auf zielführende Hilfe hoffst, versuchst Du am besten erstmal, das Ding so zu schreiben, dass mans auch versteht.

Gruß
Martin

Danke für diese konstruktive (auch wenn sie sich beim ersten Lesen eher destruktiv anhört - soll jetzt aber nicht böse gemeint sein) Antwort. Ich hab eine Antwort in der Richtung befürchtet…

Zu deinen Fragen:

  • ISR -> case 16: wenn man den Stunden-Taster an Pin 36 des µC anschließt und für mindestens eine sekunde schließt, wird die Stunde um 1 erhöht (bzw. auf 0 gesetzt).
  • ISR -> case 32: siehe case 16, nur mit minuten.
  • millisekunden: ich weiß, das keine Sekunde 5000 ms hat, es hat sich herausgestellt, dass die genauigkeit zwischen 10000 und 5000 Schritten in der Sekunde um ein vielfaches steigt. Eigentlich müsste millisekunden fuenftelmillisekunden heißen, so ein Variablennamen stört aber eher (Länge!).
  • lastpress_min : speichert den „Zeitpunkt“ des letzten Tastendrucks für Minuten
  • toSegment: ehrlich gesagt: nicht drüber nach gedacht. Aber Du hast recht, simpler wärs.
  • Multiplexing: Habe es so gemacht, da es eigentlich nicht in den ISR gehört und quasi Zeit-unkritisch (solang es ja mehr als 30 Hz sind) ist.
  • Zeitintervall: Der µC läuft mit 1MHz. => Alle 0,0002 (= 1/5000) Sekunden

Sollte wohl mehr Kommentare verwenden…

grtz
michi