Durch Tastendrucke + 7 Segment Ports Schalten

Hallo zusammen,
Nein das musst du schon explizit so programmieren

Kani meinte wahrscheinlich, den Zählerwert bei jeder Änderung abspeichern, so daß man sich eine Memo-Taste spart. Das geht schon, allerdings muß man berücksichtigen, daß man nur bis maximal 100.000mal eine EEPROM-Adresse beschreiben sollte, und das erreicht man hier eventuell ... also wenn Kani ständig die DMX-Adresse ändert ;).


Grüße,
Dirk
 
Achso! Und ich dachte er wollte die Variable direkt im EEPROM zu anlegen.

Naja, die 10.000 .. 100.000 könnte man etwas ausdehnen indem man in einer EEPROM-Adresse abspeichert wieviele EEPROM-Zellen man schon zerstört hat, und die Position des Zählwert im EEPROM immer weiter wandern lässt. Bis eines schönen Tages der ganze EEPROM hinüber ist.

EDIT: Wenn es sein muss kann man die Sache ja so programmieren dass der Zählwert automatisch in den EEPROM gerettet wird wenn die DMX-Adresse ein paar Minuten lang nicht verändert wurde.
 
Ich löse das immer so, indem ich einen Spannungsteiler aufbaue, der die Betriebsspannung vor zB. dem 5V Regler teilt und am Komparatoreingang des AVR angeschlossen ist. Wird das Gerät ausgeschaltet, wird der Komparatorinterrupt ausgelöst, der die Speicherung im EEPROM übernimmt. Man muß nur darauf achten, dass der AVR ausreichend Zeit zum Speichern hat, bevor die Spannung zu klein wird. Zusätzlich lese ich vorher den Wert aus dem EEPROM und prüfe, ob überhaupt gespeichert werden muss. So wird immer nur beim Ausschalten des Gerätes gespeichert.

Dirk
 
Code:
if (zaehlwert>9)
   {          ??          //Zählwert auf 0 setzen
   }
Praktisch habe ich noch nicht so viel gemacht.
Sodürfte das doch gehen oder?

Wie schreibe ich, das der Zählwert auf einen höher einen niedriger gesetzt wird?
zahlwert+/-1 oder wie?
 
@Dirk
Dein externer Bronout detektor ist natürlich die geschickteste lösung.

@Kani
um den Zählwert zu erhöhen schreib einfach.
Code:
zaehlwert++;
Du musst ihn aber noch auf 511 begrenzen, außerdem darf er nicht kleiner 0 werden.
also:
Code:
if(zaehlwert > 511)
{
  zaehlwert = 0;
}
if(zaehlwert < 0)
{
  zaehlwert = 511;
}
 
Oh, ich habe vergessen zu aktualisieren. xD
Ich würde das mit dem ->Wenn ausschalten->EEPROM speichern gut finden.

Dann wird auch nur gespeichert, wenn es nötig ist.
 
Code:
if (zaehlwert>9)
   {          ??          //Zählwert auf 0 setzen
   }
Praktisch habe ich noch nicht so viel gemacht.
Sodürfte das doch gehen oder?
Ich hab mir gedacht, das du dir da schwer tuhst.

Angenommen dein Zählwert ist 321.
Was machst du um an die Höherwertigste stelle zu kommen?
Richtig! Da der Computer immer Abrundet brauchst du nur durch 100 zu dividieren und du erhältst 3.

Doch wie komm ich jetzt auf die mittlere Ziffer?
Richtig! Eine Möglichkeit wäre den Zählwert durch 10 zu dividieren. Das Ergebniss wäre dann 32, dann brauchen wir nur den 3er von der höherwertigen Stelle mit 10 zu multiplizieren und erhalten den Wert 30.
Wenn man jetzt von den 32, 30 abzieht erhält man 2, also genau das was wir wollten.


Und jetzt programmier mir den Code da unten so, dass die Variablen Stelle1 bis 3 mit den richtigen Werten gefüllt werden.
Code:
unsigned char Stelle1,Stelle2,Stelle3;
Zaehlwert=321;



Ich würde das mit dem ->Wenn ausschalten->EEPROM speichern gut finden.
Machen wir, aber eins nach dem anderen.
 
Ich versteh das mit dem abrunden noch nicht ganz. 321 ist doch eine Ganze/natürliche Zahl. Was soll man da runden? Es gibt doch keine Stellen hinter dem Komma.

Im Anhang mal die Belegung der 7-Segment-Anzeigen.
 

Anhänge

  • kingbrightsa5211rt7segmlt7.jpg
    kingbrightsa5211rt7segmlt7.jpg
    11,6 KB · Aufrufe: 14
Ja 321 ist eine ganz natürliche Zahl, sobald du sie jedoch durch 100 teilst ist es nur noch 3,21. Da du diese Zahl aber in einem Integer gespeichert hast gibt es keine Stellen nach dem Komma 321/100=3.

So ein Computer verhält sich nämlich wie ein Otto Normalverbraucher, weshalb aus beispielsweise 3,99Euro 3Euro werden.

Wenn du dich jetzt fragst woher du weißt wie eine Variable abgespeichert wird:
Code:
/*
Ein Integer kennt kein Komma! Weil Zaehler von seiner deklaration an
ein Integer ist, wird er sich, wenn er duch etwas geteilt wurde, immer abrunden
*/
int Zaehler;

Edit:
Die Wahrheitstabelle für die 7Segmentanzeige erarbeiten wir später, zuerst schreiben wir noch den "Zahl auf Ziffer aufspalt-Algorithmus".
 
Zu deiner Aufgabe oben:

Code:
unsigned char Stelle1,Stelle2,Stelle3; 
Zaehlwert=321;

Also muss ich für Stelle 1 wie gesagt durch 100 dividieren, abgerundet sind es dann 3.

Stell1, Stelle2 und Stelle3 ist deklariert als unsigned char = Länge: 8bit Dezimalbereich: 0-255 und Anwendung: Zeichen. Das hat unser Lehrer auf seinem C-Tutorial stehen. (Das sind bist jetzt 50 Seiten mit Grundstruktur, Schleifen usw). Also wir machen das seit 2 Wochen in der Schule, jedoch mit so C-Windows-Programmen.

Stelle1=zaehlwert/100
Stelle2=zaehlwert/10-(stelle1*10)
Stelle3=zaehlwert/ (Hm und wie bekomme ich Stelle3?)
 
Stelle3=zaehlwert/ (Hm und wie bekomme ich Stelle3?)

Na komm schon, streng deine Birne an!
Eine zusätzliche Variable wäre zu empfehlen.

Code:
unsigned char Stelle1,Stelle2,Stelle3; 
Zaehlwert=321;

unsigned char StelleZwischenschritt;

Stelle1=zaehlwert/100;
StelleZwischenschritt = zaehlwert/10;
Stelle2=StelleZwischenschritt - (stelle1*10);
Stelle3=zaehlwert - (StelleZwischenschritt*10);
Ach! Da hab ich jetzt aber irgendwie die Geduld verloren.(eigentlich hätt ich dich das Problem lösen lassen sollen)

Edit: Weiter im Text.
Füll das mit einer Wahrheitstabelle aus: (nicht nur Eine, die für die 7 Segmentanzeige natürlich)
Code:
unsigned char array[] = {	0b00000000,//0
			0b00000000,//1
			0b00000000,//2
			0b00000000,//3
			0b00000000,//4
			0b00000000,//5
			0b00000000,//6
			0b00000000,//7
			0b00000000,//8
			0b00000000};//9
Übrigens Rechts ist niederwertig: Also PC0
 
Achso, ja. So geht das natürlich. Aber ohne Variable ist es net so leicht.
Ok, also die Grund-Aufteilung welche Ziffer auf welcher Anzeige angezeigt werden soll, steht schonmal.

Jetzt könnte man sich darum kümmern, wie er bei einem Tastendruck hoch/runterzählen lasse.
 
Wie geht das mit der Wahrheitstabelle? Ich weiß, manchmal überschätzt und manchmal unterschätzt. xD

Code:
unsigned char array[] = 
{ 
0b00000000,//0 
0b00000000,//1 
0b00000000,//2 
0b00000000,//3 
0b00000000,//4 
0b00000000,//5 
0b00000000,//6 
0b00000000,//7 
0b00000000,//8 
0b00000000;//9
}
Diese 0000000, wo sehe ich, welche Pins das sind? Das ist doch binär.
 
Jetzt könnte man sich darum kümmern, wie er bei einem Tastendruck hoch/runterzählen lasse.


Gut! Die Wahrheitstabelle machen wir aber gleich nacher.

Einen Taster fragt man wie folgt ab:
Code:
if( ! (PINA & (1<<PA4) ) )
{
  //der Taster ist gedrückt 
}
else
{
  //Der Taster ist nicht gedrückt
}
Wie das genau funktioniert kannst du in dem von dir verlinkten Tutorial nachlesen.

Du kannst dich sicher noch erinnern als ich dir den Programmrumpf gepostet hat, und wahrscheinlich auch daran dass ich dir gesagt habe das für eine Flankenerkennung einen merker brauchst.
Also! Da ich jetzt keinen Nerv habe dir das aus der Nase zu kitzeln schreib ich dir jetzt einfach ein Beispiel:
Code:
int main(void)
{
  /*
  Variablen Definieren.
  z.b. auch das Array
  */ 
  unsigned char letzteTastenposition1,letzteTastenposition2;
  int Zaehlwert=0;

  while(1)
  {
    /*
    hier villeicht eine Funktion aufrufen, die sicherstellt 
    dass die Schleifendurchläufe nicht zu kurz werden.
    Die Transistoren sollen nicht zu oft schalten.
    */ 

     /*
    Taster Abfragen.
    */
    if( ! (PINA & (1<<PA4) ) )
    {
      //der Taster ist gedrückt
      if(!letzteTastenposition1)
      {
        /*
        Der Taster wurde gerade gedrückt.
        Selbst wenn er weiterhin gedrückt          
        werden würde, würde das Programm 
        nicht mehr hier her Springen
        */

        Zaehlwert++;
      }
      letzteTastenposition1=1;
    }
    else
    {
      //Der Taster ist nicht gedrückt
      letzteTastenposition1=0;
    }


    /*
    Zeit sich um die 7Seg-Anzeige zu kümmern
    */ 

    /*
    Zählwert für DMX ausgeben
    */
  }
  return 0;
}

Edit: hab ergessen zu aktualisieren. Ja das sind die Pins für deine 7Seg,
die linke 0 steht für den PC7 und die rechte steht für PC0.
Die erste Zeile Steht dabei für die Ziffer 0 die Letzte für 9.
Du musst nun von 0 bis 9 und von PC7 bis PC0 die Nullen durch Einsen ersetzen und zwar an den Bits, an denen die Segmente leuchten sollen.
Für die Ziffer 0 wäre es beispielseise 0b11110011;
 
Nochmal zu der Wahrheitstabelle.
Geht das nicht so:
Code:
unsigned char array[] = 
{ 
     DDRA = 0xA6 //0
     DDRA = 0x03 //1
Das sind jetzt nur Beispiele. Also alles in Hexadezimal machen.
Geb mir am besten ein paar Aufgaben und ich überlege weiter und melde mich dann.
Kann ich den Array einen namen geben? Zb. segment_a oder so?
 
Nein!

Nachdem wir unsere Wahrheitstabelle definiert haben,
Code:
unsigned char array[] = 
{ 
0b00000000,//0 
0b00000000,//1 
.
.
.
}
können wir jederzeit auf die Werte darin zugreifen

Dafür brauchen wir nur den namen des Arrays zu schreiben und dem Namen gefolgt, in eckigen Klammern, die Nummer des Elementes auf das wir zugreifen wollen.
So etwa:
Code:
PORTA=array[3];
/*
PORTA wir jetzt mit dem Byte aus der 4.Zeile(es fängt ja bei 0 an) unseres 
array belegt. Wir haben im 4.Element dieses Arrays definiert, welche Segmente
der 7Seg leuchten müssen, wenn die Ziffer 3(es fängt ja bei 0 an) angezeit 
werden soll.

(
eigentlich müsste man "PORTA= ~ array[3];" schreiben da die Segmente 
leuchten wen der jeweilige Ausgang gegen Masse geschalten wird.
~ dreht alle Bits in einer variable um. 0 wird 1, 1 wird 0
)

*/

Zu beachten ist dass, das 4. Element das Element Nummer 3 ist,
weil das Element 0 das erste Element ist.

Edit:
Wenn du Aufgaben willst bitte(hausaufgaben bis Morgen):
1)Mach die Wahrheitstabelle fertig und benenne sie wie du willst(schreib statt array meinetwegen jimmy). Wies funktioiert habe ich am Ende von Post #34 nnochmal geschrieben.
2) Les das Tutorial das du verlinkt hast bitte nochmal, es gibt viel das du noch nicht verstanden hast
3)Das Beispiel mit der Tastflankenerkennung kannst du gleich auf die 2te Taste erweitern.
4)Such eine Funktion die deine Programmschleife um eine Millisekunde verzögern kann. Die Zykluszeit deines Programms ist warscheinlich zu niedrig, wenn du die Transistoren fürs Multiplexen zu oft schaltest werden disch Schaltverluste zu hoch.(außerdem kannst du den unschönen Effekt bekommen dass Ziffern Schatten auf die nächsten Ziffern werfen weil die Transistoren nicht schnell genug abschalten)
 
------------------------------ Aufgabe 1 ------------------------------
Code:
unsigned char array[] = 
{ 
	0b11100111,   //0 
	0b10000100,   //1 
	0b11010011,   //2 
	0b11010110,   //3 
	0b10110100,   //4 
	0b01110110,   //5 
	0b01110111,   //6 
	0b11000100,   //7 
	0b11110111,   //8 
	0b11110110;   //9
}
Fertig! =)
attachment.php

Die Anschlüsse sind wie folgt:
PC0 = 1
PC1 = 2
PC2 = 3
PC3 = 4
PC4 = 5
PC5 = 6
PC6 = 7
PC7 = 8

So ist die gemessene Belegung der 7-Segment-Anzeige. So passt es auch. Hier nach habe ich die Tabelle gemacht.
Der Controller weiß doch, für welchen Port das gilt, weil man es ihm hier "PORTA=array[3]; " sagt, richtig? Also muss man später PORTC statt PORTA schreiben.
------------------------------ Aufgabe 1 - done! ------------------------------

------------------------------ Aufgabe 2 ------------------------------
Dafür brauch ich noch 3-4 Stunden. Das mache ich heute Abend nicht mehr. xD

------------------------------ Aufgabe 3 ------------------------------
Code:
int main(void)
{
  /*
  Variablen Definieren.
  z.b. auch das Array
  */ 
  unsigned char letzteTastenposition1,letzteTastenposition2;
  int Zaehlwert=0;

  while(1)
  {
    /*
    hier villeicht eine Funktion aufrufen, die sicherstellt 
    dass die Schleifendurchläufe nicht zu kurz werden.
    Die Transistoren sollen nicht zu oft schalten.
    */ 

     /*
    Taster Abfragen.
    */
    if( ! (PINA & (1<<PA4) ) )
    {
      //der Taster ist gedrückt
      if(!letzteTastenposition1)
      {
        /*
        Der Taster wurde gerade gedrückt.
        Selbst wenn er weiterhin gedrückt          
        werden würde, würde das Programm 
        nicht mehr hier her Springen
        */

        Zaehlwert++;
      }
      letzteTastenposition1=1;
    }
    else
    {
      //Der Taster ist nicht gedrückt
      letzteTastenposition1=0;
    }

 while(1)
  {
    /*
    hier villeicht eine Funktion aufrufen, die sicherstellt 
    dass die Schleifendurchläufe nicht zu kurz werden.
    Die Transistoren sollen nicht zu oft schalten.
    */ 

     /*
    Taster Abfragen.
    */
    if( ! (PINA & (1<<PA3) ) )
    {
      //der Taster ist gedrückt
      if(!letzteTastenposition2)
      {
        /*
        Der Taster wurde gerade gedrückt.
        Selbst wenn er weiterhin gedrückt          
        werden würde, würde das Programm 
        nicht mehr hier her Springen
        */

        Zaehlwert--;
      }
      letzteTastenposition2=1;
    }
    else
    {
      //Der Taster ist nicht gedrückt
      letzteTastenposition2=0;
    }

	

    /*
    Zeit sich um die 7Seg-Anzeige zu kümmern
    */ 

    /*
    Zählwert für DMX ausgeben
    */
  }
  return 0;
}
Ich bin mir hier nicht ganz sicher, ich glaube, man kann das auch alles in eine while-Schleife schreiben.
------------------------------ Aufgabe 3 - done! ------------------------------
------------------------------ Aufgabe 4 ------------------------------
Öhm. Die komplette Programmschleife anhalten?
Wie wäres es mit "delay_ms(1);". Aber eine Millisekunde ist doch "nichts". Ich glaube aber, für den Mikrocontroller ist das schon eine "Menge"!
------------------------------ Aufgabe 4 - done! ------------------------------

Und? Wie war ich? xD
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)