Hallo zusammen, mein Programm soll folgendes Erledigen: Ich habe 64 digitale Ausgänge die ich zu 8 Segmenten á 8 Ausgänge zusammenfasse. Die Segmente werden von einem ATmega32 an PortC in einem Timer-Interrupt ausgewertet. Die Segmente werden nacheinander von PortA aktiviert. Das Ergebnis soll mir an PortB angezeigt werden. Ein Beispiel: Segment 1 aktiviert , Ausgang 1 = 1 , Ergebnis sollte 1 sein. Segment 1 aktiviert , Ausgang 8 = 1 , Ergebnis sollte 8 sein. Segment 2 aktiviert , Ausgang 9 = 9 , Ergebnis sollte 9 sein. Segment 2 aktiviert , Ausgang 16 = 16 , Ergebnis sollte 16 sein. ... Nun mein Problem: PortA = 0b00000001 , Ausgang 1 = 1 , Ergebnis = 9 PortA = 0b00000001 , Ausgang 8 = 1 , Ergebnis = 16 PortA = 0b00000010 , Ausgang 9 = 1 , Ergebnis = 17 PortA = 0b00000010 , Ausgang 16 = 1 , Ergebnis = 24 PortA = 0b00000100 , Ausgang 17 = 1 , Ergebnis = 25 PortA = 0b00000100 , Ausgang 24 = 1 , Ergebnis = 32 PortA = 0b00001000 , Ausgang 25 = 1 , Ergebnis = 33 PortA = 0b00001000 , Ausgang 32 = 1 , Ergebnis = 40 PortA = 0b00010000 , Ausgang 33 = 1 , Ergebnis = 41 PortA = 0b00010000 , Ausgang 40 = 1 , Ergebnis = 48 PortA = 0b00100000 , Ausgang 41 = 1 , Ergebnis = 49 PortA = 0b00100000 , Ausgang 48 = 1 , Ergebnis = 54 PortA = 0b01000000 , Ausgang 49 = 1 , Ergebnis = 55 PortA = 0b01000000 , Ausgang 54 = 1 , Ergebnis = 64 PortA = 0b10000000 , Ausgang 55 = 1 , Ergebnis = 1 PortA = 0b10000000 , Ausgang 64 = 1 , Ergebnis = 8 Ich finde meinen Fehler nicht. Das Assembler-Programm habe ich angehängt. Mir ist klar, dass man einen Interrupt so kurz wie möglich halten sollte, und die Auswertung separat machen sollte. Dieses Programm habe ich nur geschrieben, um dessen korrekte Funktionsweise zu überprüfen. Ich hoffe ihr könnt mir helfen. MfG EXA
Gast
#1457012
timer0_overflow: push r16 in r16, SREG ;SREG Register retten push r16 ldi r18, 0b00000001 ;Erstes Segment auswählen wird am Anfang des overflow-irq r18 immer auf 1 intialisiert, obwohl es am ende nach links verschoben wird?
Gast
#1457013
brcc auslesen sorry, hab ich übersehen
Ich vermute, bei sbrs r17, 0 ;Segmenteingang 1 den ldi r16, 0x01 ;Wert 1 zuweisen sbrs r17, 1 ;Segmenteingang 2 den ldi r16, 0x02 ;Wert 2 zuweisen sbrs r17, 2 ;Segmenteingang 3 den ... wolltest Du springen, wenn das Bit gelöscht ist. Ausserden würde ich zur Sicherheit bei dem ROL Befehl vorher das Carry löschen, da es sonst von der vorhergehenden Addition übernommen wird. gruss HerrMueller
@ Lutz: Ja, am Anfang setze ich r18=1. Das steht aber auserhalb der 'auslesen:'-Schleife und sollte daher nur einmal am Anfang passieren. @ Herr Mueller: Sorry hätte ich dazu sagen sollen, PortC wird über externe PullUps auf 0xFF gehalten und wenn eine Ausgang durchschaltet dann wird der entsprechende Pin auf LOW gezogen. (Interne PullUps konnten nicht verwendet werden, da der Widerstandswert für meine Zwecke zu hoch ist) MfG EXA
Stefan P. schrieb: > Die Segmente werden nacheinander von PortA > aktiviert. Das Ergebnis soll mir an PortB angezeigt werden. Du tappst in diese Falle: http://www.mikrocontroller.net/articles/AVR-Tutorial:_IO-Grundlagen#Stolperfalle_bei_Matrixtastaturen_etc. (Link zeigt Bug in der Forumsoftware. Gehe zum Abschnitt "Stolperfalle bei Matrixtastaturen etc.") z.B. an dieser Stelle:
1 | |
2 | |
3 | |
Stefan B. schrieb: > Du tappst in diese Falle: > http://www.mikrocontroller.net/articles/AVR-Tutorial:_IO-Grundlagen#Stolperfalle_bei_Matrixtastaturen_etc. Auch mit einem zusätzlichem NOP funktionierts leider nicht. Ein weiterer komischer Effekt, den ich mir nicht erklären kann ist folgender: Das Ergebnis wird mir an PortB durch LEDs angezeigt. Beim Auslesen von Segment 1-6 (PA0-5) und Segment 8 (PB7) flackern die LEDs, da ja im Interrupt ausgelesen wird. Soweit ist das ja ok. Beim Abfragen von Segment 7 (PA6) leuchten die LEDs kontinuirlich. Wenn ich Segment 7 auslese sollten die LEDs doch auch flackern, da ja ebenfalls im Interrupt ausgelesen wird. Dafür finde ich absolut keine Erklärung. Bei der Simulation im AVR-Studio funktioniert alles wunderbar. MfG EXA
Hat keiner eine Idee? Ich kann mir nicht erklären, wo der Fehler liegen soll. MfG EXA
Ich habe versucht das per Simulation nachzuvollziehen, bin aber daran schon kläglich gescheitert. Im ASM-Code ist eine Eingabe über PINC nötig und aus dem Begleittext der Frage wird überhaupt nicht darauf eingegangen, welche Eingaben an PINC zu welcher Ausgabe und zu welchem Ergebnis führen sollen. Die komplette Simulation wäre daher 8 Segmentmöglichkeiten * 256 Zustände an PINC = 2048 Möglichkeiten groß - zuviel für mich. Und ich habe dieses Wunschergebnis nicht verstanden. > Segment 1 aktiviert , Ausgang 8 = 1 , Ergebnis sollte 8 sein. > Segment 2 aktiviert , Ausgang 9 = 9 , Ergebnis sollte 9 sein. ^ Ich würde weitermachen, wenn ich die Rechenvorschrift für Ausgang = f(Segment, PINC) Ergebnis = f(Segment, PINC) in einfachen Worten lesen könnte und sie mir nicht aus möglicherweise falschen ASM-Code zusammenreimen müsste ;-)
@Stefan P. (exa) Immer unter der Voraussetzung, daß ich nicht völlig auf einem falschen Dampfer bin: Wie ist denn elektronisch/physikalisch die Verbindung zwischen Port A und Port C aufgebaut? Da sind doch -wenn ich Dich richtig verstanden habe- noch irgendwelche Schaltungselemente/Register dazwischen. Vielleicht postest Du mal die Schaltung? So wie ich das verstanden habe, kann da auch von jedem Segment nur ein Ausgang aktiv sein? Das Ganze ist mir noch recht unklar, kann aber auch daran liegen, daß ich mich altersmäßig langsam der Senilitätsgrenze nähere :-) Reinhard
Was mir auf die Schnelle aufgefallen ist: Du sammelst das Ergebnis für Segment 1 und gibst es auf Port B aus. Dann springst Du wieder zurück und sammelst das Ergebnis für Segment 2 und gibst dieses auf Port B aus. Dazwischen liegen geschätzt 40 Prozessortakte, dann wird schon das nächste Segmentergebnis ausgegeben. Du hast schnelle Augen... :-) Vielleicht solltest Du bei jedem Interrupt nur ein Segment ausgeben und Dir das Ergebnis erst mal ansehen? Reinhard
Ok ich gebe zu, mein erster Post war nicht leicht verständlich ... Ich habe mal den Schaltplan vom Prinzip her angehängt. Ich habe 8 Segmente mit je 8 Eingängen. Die restlichen Segmente sind paralell zu Segment1 geschaltet und werden ebenfalls über PortA + Transistor aktiviert. Zur besseren Übersichtlichkeit ist im Schaltplan nur ein Segment eingezeichnet. Von allen 64 Eingängen ist IMMER höchstens EINER durchgeschaltet ! Am Ausgang PortB will ich jetzt sehen, welcher der 64 Eingänge geschalten ist, oder ob garkeiner durchgeschalten ist. PortC wird durch externe PullUPs auf HIGH-Pegel gehalten. Schaltet jetzt einer der Eingänge eines Segments durch sieht der AVR am entsprechenden Pin LOW-Pegel. Wenn also PINC = 0b11111111 (also kein Eingang geschaltet) soll Ausgang = 0 sein. Ansonsten soll folgende Beziehung gelten: PortB = Ausgang Ausgang = Nummer des durchgeschalteten Eingangs Ausgang = (Nummer des aktiven Segments - 1)*8 + Nummer des Pins der LOW-Pegel sieht Ausgang = (LOG2(PortA) - 1)*8 + LOG2(invertierter PortC) An PortA wird ein nach links rotierendes Register ausgegeben und damit die Segmente nacheinander aktiviert. Der Befehl LOG2() erwartet als Argument eine Konstante, bei mir ändern sich jedoch die Zustände an PortA und PortC. Deshalb wird (LOG2(PortA) - 1)*8 folgendermaßen erledigt:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
LOG2(invertierter PortC) wird folgendermaßen realisiert:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
Später soll das Ergebnis via UART an den Rechner geschickt werden. Die Ausgabe an PortB mit den LEDs dient nur während der Entwicklungsphase zur Kontrolle, ob das Program so läuft wie ich mir das vorstelle. Ich hoffe Ihr könnt damit mehr anfangen, wie mit dem ersten Post :-) MfG EXA
Atmega32... PORTC... Wie ist eigentlich die JTAG Fuse eingestellt?
Daran hab ich auch schon gedacht. Müsste aber passen. Bild von den Fuses unter PonyProg im Anhang. MfG EXA
Hier addierst Du r16 und r20, gibst aber r16 aus, egal ob Addition oder nicht:
1 | |
2 | |
3 | |
4 | |
5 | |
Versuch mal die Sprungmarke hinter den OUT-Befehl zu setzen, dann wird auch nur das Additionsergebnis ausgegeben:
1 | |
2 | |
3 | |
4 | |
5 | |
Viel Erfolg. Reinhard
r16 wird am anfang auf 0 gesetzt. Ist kein Eingang durchgeschaltet bleibt r16 = 0 und ich will auch 0 als Ausgabe bekommen. Wenn ich die Sprungmarke hinter den OUT-Befehl setzte bekomme ich als Ausgabe den Wert vom vorhergehenden Interrupt und nicht 0. MfG EXA
Stefan P. schrieb: > r16 wird am anfang auf 0 gesetzt. Ist kein Eingang durchgeschaltet > bleibt r16 = 0 und ich will auch 0 als Ausgabe bekommen. Wenn ich die > Sprungmarke hinter den OUT-Befehl setzte bekomme ich als Ausgabe den > Wert vom vorhergehenden Interrupt und nicht 0. Richtig, aber wenn Du den einen eingeschalteten Schalter detektiert und auf Port B ausgegeben hast, wird r16 -und damit wieder der Port B nach ca. 40 Takten, im nächsten Schleifendurchgang innerhalb des gleichen Interrupts- wieder auf 0 gesetzt. Reichen Dir ca. 40 Takte um die LEDs und damit den Schalter zu erkennen? Oder sehe ich da wieder was falsch? Reinhard
48+8 = 56 nicht 54 ;-)
Gast
#1460712
Mal ne dumme Frage: Ist der Atmega so verschaltet wie auf dem Plan im Post von 18:58 Uhr? Also ist wirklich der Reset-Pin nicht angeschlossen? Ich verwende nur PICs aber da ist das ne dumme Idee keinen Pull-Up zu verwenden. Vielleicht kommt das Problem daher. Aber wie gesagt, ich hab von Atmegas keine Ahnung.
Gast
#1460740
Hi
>Ist der Atmega so verschaltet wie auf dem Plan im Post von 18:58 Uhr? A
Hoffentlich nicht. Es fehlen z.B. alle Vorwiderstände für die Leds.
MfG Spess
Gast
#1460758
Hi Stefan, 1)im Schaltplan würde ich die Dioden(LED) bei 0- Leuchten lassen, weil die Porttreiber des AVR's bei Low den höheren Strom abdrücken können. 2) Vorwiderstände für die LED's sind Pflicht ! 3) Den maximal zulässigen Portstrom nicht überschreiten! 4) Gesamtstrom zw. VCC und GND nicht überschreiten !
In der Simulation sehe ich keine Probleme, Code ist im Anhang. Beachte alle Tipps der Vorredner bzgl. Hardware. Da liegt es anscheinend im Argen. AVcc und GND Pin 31 auch beschalten.
Gast
#1460791
>Hi > >>Ist der Atmega so verschaltet wie auf dem Plan im Post von 18:58 Uhr? A > >Hoffentlich nicht. Es fehlen z.B. alle Vorwiderstände für die Leds. > >MfG Spess Deshalb schrieb ich ja "dumme Frage" da ich mir auch denk, dass das nur schematisch sein soll damit man weiß, was wo dran hängt. Aber grade den Pull-Up am Reset-Pin vergisst man im Eifer des Gefechts mal schnell. ;)
Reinhard R. schrieb: > Richtig, aber wenn Du den einen eingeschalteten Schalter detektiert und > auf Port B ausgegeben hast, wird r16 -und damit wieder der Port B nach > ca. 40 Takten, im nächsten Schleifendurchgang innerhalb des gleichen > Interrupts- wieder auf 0 gesetzt. Reichen Dir ca. 40 Takte um die LEDs > und damit den Schalter zu erkennen? Prinzipiell gesehen hast du natürlich Recht. Die LEDs dienen aber nur zum Debuggen, die kommen später weg und das Ergebnis wird via UART an den Rechner geschickt. Der Schaltplan von 18:58 Uhr war nur schematisch, damit Ihr wisst, wie wo was dranhängt. Den kompletten Schaltplan vom Versuchsaufbau hab ich mal angehängt. Die Fuses könnt ihr weiter oben im Thread anschaun. Stefan B. schrieb: > In der Simulation sehe ich keine Probleme ... Das ist es ja gerade was ich nicht verstehe, Simulation ist bei mir auch ok aber aumf Chip gehts dann nicht ... Trotzdem bis hier hin schon mal vielen Dank für eure Unterstützung :) MfG EXA
Also wenn ich folgfende Stelle im Quellcode ändere
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
und den Rest nicht verändere, dann bekomme ich die richtige Ausgabe an PortB! Allerdings wird dann auch nur Segment1 ausgelesen. Anscheinend hat es also etwas mit dem rotieren von r18 zu tun. Aber wie soll ich das anders lösen? Die Rechenvorschrift für r18 wäre: r18 = 2^x wobei x=[0;7] Ich habe auch schon versucht, den ROL-Befehl folgendermaßen auszudrücken:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
Hat aber auch nicht funktioniert. MfG EXA
Gast
#1461852
Hallo Stefan,
in der Simulation läuft dein Programm nur, wenn man den Zustand von Port
C genau zwischen der Ausgabe auf Port A und dem Einlesen von Port C
ändert.
Macht man diese Änderung zu spät, kommt es zu Deinem Effekt. Nehme an,
das der Transistor nicht schnell genug sperrt. Füge entsprechende NOP's
ein um Ihm mehr Zeit zu geben.
Bsp.
out PORTA, r18 ;Segment aktivieren
.
Mehr Nop's
in r17, PINC ;Segment einlesen
Hallo Holger, unglaublich, es funktioniert !!! Klasse ! Habe 21 mal NOP eingefügt (mehr geht nicht, weil rjmp ja nur 63 Zeilen springen kann). Vielen Dank du hattest Recht. 21 NOPs im Code sind ja nicht gerade befriedigend, werde mich morgen mal auf die Suche eines geeigneten Transistios oder FETs? machen. Momentan verwende ich den BC547A, habt ihr irgendwelche Vorschläge? Danke für die Unterstützung, ohne euch hätt ich's nicht soweit geschafft ... :) MfG EXA
Gast
#1461985
Hallo Stefan, freut mich das es klappt. Du kannst die Nop's auch durch eine Warteschleife ersetzen. Hatte mit weniger NOP's gerechnet. Denke mal darüber nach, die Zuordnung der Werte durch Addition bzw Schieben in Schleifen zu lösen (Das Programm wird Kürzer) ;-) Wenn es wirklich sicher ist,dass nur ein Eingang betätigt werden kann, dann sollte die Ausgabe auf Port B erst am Ende der Auswertung erfolgen. Damit vermeidest Du das "flackern" der LED's.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.


