Hallo,
irgendwie versteh ich nicht ganz das Verhalten des Programms. Der uC ist
ein at90usb162.
Sobald das Programm ins ISR springt aktiviert es PB7. (Wieso)
Wenn es die Zeile PORTB = (PORTB<<1) | 1; ausführt springt das PORTB um
eins weiter aber nicht PINB. PINB springt erst um eins weiter wenn es
wieder in die Zeile der if-Bedingung springt.
Das nächste Problem ist auch das die if-Bedingung nicht ausgeführt wird.
Hoffe ihr könnt mir helfen.
MfG
halllo schrieb:> Wenn es die Zeile PORTB = (PORTB<<1) | 1; ausführt springt das PORTB um> eins weiter aber nicht PINB. PINB springt erst um eins weiter wenn es> wieder in die Zeile der if-Bedingung springt.
Also im Simulator?
Das ist normales Verhalten der Hardware. Das PIN-Register gibt ja den
Eingangspegel an den Pins wieder. Und da dieser erst synchronisiert
werden muss, steht er nicht sofort, sondern erst verzögert zur
Verfügung.
> Das nächste Problem ist auch das die if-Bedingung nicht ausgeführt wird.
Das liegt daran, dass PB0..PB7 anders definiert sind also du denkst.
Mach dich mal schlau, wie man im avr-gcc die einzelnen Pins abfragt.
halllo schrieb:> Hast du noch eine Idee wieso PB7 aktiviert wird wenn es ins ISR springt.
meinst du mit aktiviert auf 1 gesetzt?
Das hast du doch schon vorher gemacht
>> Andere Frage: Wie kann man das Byte 11011101 getrennt shiften.
andere Frage: was meinst du damit?
if(PB1==1 && PB2==1 && PB3==1 && PB4==1 && PB5==1 && PB6==1 && PB7==0)
Das ist eine umständliche Schreibweise der Anweisung
if (1)
PB1 hat nämlich den Wert 1, damit ist bereits der erste Vergleich
wahr, der Rest interessiert nicht mehr. Da das alles bereits zur
Compilezeit konstant ist, eliminiert der Compiler dann das "if"
auch noch.
if (bedingung == true)
ist Humbug. Noch "Boolscher" als "bool" gibt es nicht, und da
"bedingung" bereits vom Typ "bool" ist, kannst du einfach
schreiben:
if (bedingung)
>> Hast du noch eine Idee wieso PB7 aktiviert wird wenn es ins ISR springt.>meinst du mit aktiviert auf 1 gesetzt?>Das hast du doch schon vorher gemacht
Sobald der Debugger ins ISR springt wird PB7 auf Low gesetzt. Nach der
Zeile PORTB = (PORTB<<1) | 1; wirds durch das shiften wieder auf High
gesetzt.
Aus irgendeinem Grund wird PB7 durch das Interrupt immer auf Low
gesetzt.
Wenn ich 11011101 habe, würde ich zuerst gerne die 3 höchten Bits
shiften und dann die unteren.
1101 1101
1011 1101
1011 1011
0111 1011
0111 0111
Jörg Wunsch schrieb:> if(PB1==1 && PB2==1 && PB3==1 && PB4==1 && PB5==1 && PB6==1 && PB7==0)>> Das ist eine umständliche Schreibweise der Anweisung>>> if (1)
Nö, "if (0)".
> PB1 hat nämlich den Wert 1, damit ist bereits der erste Vergleich> wahr, der Rest interessiert nicht mehr.
Bei "&&"?
Nun ja, jeder hat mal einen schlechten Tag. ;-)
Hat jemand noch einen Tipp für dieses Problem:
Wenn ich 11011101 habe, würde ich zuerst gerne die 3 höchten Bits
shiften und dann die unteren.
1101 1101
1011 1101
1011 1011
0111 1011
0111 0111
Deine Beschreibung ist ein wenig mehrdeutig.
Kann es sein, dass du gar nicht 'shiften' willst, sondern im Kreis
rotieren?
Das würde zumindest zu deinem Beispiel passen.
Bit 5-7 will ich immer von rechts nach links shiften und Bit 1-4 will
ich zuerst nach links und dann nach rechts shiften. Die zwei Funktionen
soll man aber getrennt ausführen können.
Du hast das Programm - bestimmt irrtümlich - versucht in der sog.
"Sprache C" zu schreiben. Solche Kompilate sind hinlänglich dafür
bekannt, genau - nicht das - zu tuen, für das sie geschrieben wurden!
ernst schrieb:> Du hast das Programm - bestimmt irrtümlich - versucht in der sog.> "Sprache C" zu schreiben. Solche Kompilate sind hinlänglich dafür> bekannt, genau - nicht das - zu tuen, für das sie geschrieben wurden!
Schwachsinn. Assemblerprogramme sind auch berüchtigt dafür nicht das zu
tun, wofür sie programmiert sind - wenn man keine Ahnung vom
Programmieren hat. Das ist mit C nicht anders. Oder Pascal. Oder Java.
Oder Python. Oder Wasauchimmer.
>Du hast das Programm - bestimmt irrtümlich - versucht in der sog.>"Sprache C" zu schreiben. Solche Kompilate sind hinlänglich dafür>bekannt, genau - nicht das - zu tuen, für das sie geschrieben wurden!
Was willst du damit sagen?
halllo schrieb:> Bit 5-7 will ich immer von rechts nach links shiften und Bit 1-4 will> ich zuerst nach links und dann nach rechts shiften. Die zwei Funktionen> soll man aber getrennt ausführen können.
Na dann mach das doch
Du hast einen Wert
Von dem holst du dir die Bits 5-7 in eine neue Variable und setzt alle
anderen Bits auf 0 (damit sie dir beim nachfolgenden Shiften nicht in
die Quere kommen)
die shiftest du um 1 stelle nach links
dann setzt du noch das Bit 5 (so willst du das anscheinend)
und überträgst das Ergebnis wieder zurück in die originale Variable
(dort die Bits 5-7 auf 0 setzen und mit dem geshifteten Ergebnis
verodern)
Wie würdest du es denn von Hand machen, wenn du nur Operationen zur
Verfügung hast, die auf alle 8 Bit gemeinsam wirken? Doch auch nicht
anders.
ernst schrieb:> Du hast das Programm - bestimmt irrtümlich - versucht in der sog.> "Sprache C" zu schreiben. Solche Kompilate sind hinlänglich dafür> bekannt, genau - nicht das - zu tuen, für das sie geschrieben wurden!
Ziemlicher Unsinn.
Wenn man das Programm so formuliert, dass der Programmtext genau dem
entspricht, was man eigentlich tun möchte, dann tun C Programme genau
das was sie tun sollen. So wie Programme in anderen Programmiersprachen
auch.
Die Krux liegt normalerweise an 4 Stellen
* der Programmierer weiß nicht, was er eigentlich will bzw. hat keine
klare Vorstellung davon
* der Programmierer weiß nicht, wie er das Problem völlig losgelöst
von einer Programmiersprache lösen will/kann.
* der Programmierer weiß nicht, wie er das in seiner Programmiersprache
umsetzen kann. Dieser Punkt geht normalerweise Hand in Hand mit dem
nächsten Punkt, der da lautet
* der Programmierer kennt seine Programmiersprache nicht oder nicht
richtig.
Meistens ist das Hauptproblem schon im Punkt 1 oder 2 zu finden, bzw. an
der Kombination aus Punkt 2 und Punkt 4. Da werden dann zur
Problemlösungen 'Wunderoperationen' aus dem Hut gezaubert, die so gar
nicht in der realen Programmiersprache vorhanden sind.
Im "Idealfall" sollte dann ein Schachprogramm so aussehen
1
intmain()
2
{
3
play("Chess");
4
}
und um alles andere hat sich der Compiler zu kümmern.
Aber so, wie ein Werkzeugkasten eben nicht von alleine die IKEA Möbel
zusammenbaut, so muss man eben auch in einer Programmiersprache seinen
Werkzeugkasten kennen um zu wissen, was man eigentlich alles zur
Verfügung hat. Und dann muss man eben die gewünschte Operation Stück für
Stück aus dem was man hat zusammensetzen.
Danke!
Habe noch eine Frage. :-)
Bei Timer1 verwende ich Channel A und B im CTC Mode. Wenn Channel A
ausgeführt wird, setzt es den TCNT wieder auf 0 sodass Channel B nicht
dran kommt.
Gibt es einen Weg dass Channel B trotzdem ausgeführt wird.
halllo schrieb:>>Du hast das Programm - bestimmt irrtümlich - versucht in der sog.>>"Sprache C" zu schreiben. Solche Kompilate sind hinlänglich dafür>>bekannt, genau - nicht das - zu tuen, für das sie geschrieben wurden!>> Was willst du damit sagen?
Ich vermute, er will sagen, daß er es nicht schafft, ein lauffähiges
C-Programm zu schreiben und den Grund dafür nicht bei sich selbst,
sondern bei der Sprache sucht.
halllo schrieb:> Bei Timer1 verwende ich Channel A und B im CTC Mode. Wenn Channel A> ausgeführt wird, setzt es den TCNT wieder auf 0 sodass Channel B nicht> dran kommt.>> Gibt es einen Weg dass Channel B trotzdem ausgeführt wird.
was soll 'Channel B wird ausgeführt' bedeuten?
Dein Timer zählt. 0, 1, 2, 3, 4, 5, .....
Im CTC Modus wird der momentane Wert des Timers (der Zählerstand) mit
einem anderen Register verglichen. Sind sie gleich, dann wird der Zähler
wieder auf 0 zurückgestellt und er beginnt wieder von vorne. 0, 1, 2, 3,
...
Mit welchem Register verglichen wird, das findet sich im Datenblatt. Da
gibt es eine schöne Tabelle, in der alle Modi aufgelistet sind und in
der auch steht, welches Register für diesen Wert (den TOP Wert)
zuständig ist.
Davon unabhängig (sofern die Register nicht für den jeweiligen Modus
laut Tabelle eine bestimmte Bedeutung haben) sind die Compare Register
OCR1A bzw. OCR1B. Wann immer der momentane Zählerstand mit einem der
beiden Register übereinstimmt, hat man einen Compare Match und kann da
eine Aktion daran binden.
Und das wars dann schon. Mehr gibt es dazu eigentlich fürs erste nicht
zu sagen. Wenn du einen Compare Match beim Zählerstand 300 einstellst,
der Timer aber immer nur von 0 bis 250 zählt, dann wird dieser Compare
Match nie auftreten.
>was soll 'Channel B wird ausgeführt' bedeuten?
Ich verwende bei bei Timer1 OCR1A UND OCR1B. OCR1A ist zb. 30 und OCR1B
zb. 60.
Wenn der Zählerstand 30 erfolgt ein COMPARE MATCH, das Interrupt wird
ausgelöst und der Zählerstand wird wieder auf 0 gesetzt.
Da der OCR1B aber 60 und der Zählerstand bei 30 zurück gesetzt wird, ist
die Folge dass OCR1B nie ausgelöst wird.
Du hast ein konzeptionelles Problem. Man kann nicht "Kanal A und
Kanal B im CTC-Modus" benutzen. (Gut, das hast du mehr oder weniger
gemerkt.)
Bitte gehe auf "Los!" zurück, ziehe nicht EUR 2000 ein und erzähle
uns die Aufgabe, die du lösen möchtest, statt einer halb angedachten
und dann doch nicht funktionierenden Lösung.
Mit Timer1 will ich zwei Lauflichter ansteuern und mit Timer0 will ich
PWM ansteuern.
Somit sind alle Timer besetzt.
Wenn man Channel A;B;C bei Timer 1 nicht getrennt benützen kann, welchen
nutzen haben sie dann.
halllo schrieb:> Mit Timer1 will ich zwei Lauflichter ansteuern und mit Timer0 will ich> PWM ansteuern.
Bitte erzähle mehr darüber.
> Somit sind alle Timer besetzt.
Naja. Vermutlich könnte man das alles mit einem einzigen Timer
machen. Der macht dann in der Hardware die PWM, und per Software
organisiert er das Timing für die Lauflichter (bei dem es vermutlich
nicht auf 'ne Mikrosekunde ankommt).
> Wenn man Channel A;B;C bei Timer 1 nicht getrennt benützen kann, welchen> nutzen haben sie dann.
Natürlich kann man diese getrennt benutzen, solange man nicht auf die
Idee kommt, alle für einen CTC-Modus benutzen zu wollen. So eine
compare/match unit kann ja noch mehr machen als nur den Zähler zurück
zu setzen.
Bei PB1-PB4 läuft ein Lauflicht und bei PB5-PB7 läuft das andere
Lauflicht mit unterschiedlicher Frequenz.
Bei PB0 wird eine Led über PWM gedimmt.
>Vermutlich könnte man das alles mit einem einzigen Timer machen.
Bei PWM ändert sich die Frequenz, deswegen bracht der ja einen extra
Timer.
>Natürlich kann man diese getrennt benutzen
Für was kann man die Channel zb. benützen. Was kann die compare/match
unit noch machen.
halllo schrieb:> Bei PB1-PB4 läuft ein Lauflicht und bei PB5-PB7 läuft das andere> Lauflicht mit unterschiedlicher Frequenz.> Bei PB0 wird eine Led über PWM gedimmt.
Ist erst mal noch kein Hinernissgrund für nur einen Timer.
> Bei PWM ändert sich die Frequenz, deswegen bracht der ja einen extra> Timer.
Bei PWM verändert sich keine Frequenz.
> Für was kann man die Channel zb. benützen. Was kann die compare/match> unit noch machen.
Das wofür sie designed wurde.
Stimmt Registerwert und Timerwert überein, dann kann man sich einen
Interrupt auslösen lassen. Oder aber die Hardware so schalten, dass sie
einen Pin toggelt.
>Ist erst mal noch kein Hinernissgrund für nur einen Timer.
Wenn sich das Duty Cicle ständig ändert, wie würdest du die Zeit messen.
Am Overflow?
Wenn der Pin High toggelt, muss dann auch der Port toggeln?
Habe versucht per PWM die Led zu dimmen jedoch toggelt nur der PIN und
nicht der Port. Die Folge ist dass die Led nicht die Helligkeit ändert.
halllo schrieb:>>Ist erst mal noch kein Hinernissgrund für nur einen Timer.>> Wenn sich das Duty Cicle ständig ändert, wie würdest du die Zeit messen.> Am Overflow?
Was ist falsch daran?
Ja, genau so würde ich das machen.
Auch wenn sich der Duty Cycle dauernd ändert, die Overflows kommen
weiterhin regelmässig. Die hängen ja nur davon ab, was der Top Wert der
PWM ist. Und der bleibt auch bei einer PWM immer gleich. Nur sollte man
auch eine PWM nehmen, bei der ein Overflow ausgelöst wird.
Beim letzten Bsp., wieso wird da das TCNT Register auf 0 gesetzt wenn es
mit dem OCR übereinstimmt. Sollte das TCNT nicht weiter bis 255 zählen
und nur den PIN toggeln.