Hallo Leute,
Folgendes:
Ich möchte am selben Port über unterschiedliche Pins Ein- und Ausgänge
haben.
Als Ausgänge habe ich drei Pins für ein Freigabe, Richtungs, und
Taktsignal für einen Schrittmotor.
Als Eingang haben ich einen Taster der sobald er ausgelöst wird über
interrupts den Schrittmotor stoppt.
Beides fürs sich funktioniert wenn ich es getrennt probiere.
Sobald ich jedoch beides gleichzeitig in den Controller lade
funktioniert die Ansteuerung für den Motor über die drei Leitungen nicht
mehr.
Daher meine Frage:
Ist es überhaupt möglich am selben Port gleichzeitig Ein- und Ausgänge
zu verarbeiten?
Wenn ja würde ich um eine kurze Hilfestellung bitten wie die
Konfiguration der I/Os in dem Fall auszusehen hat.
Verwendet wird ein ATmega6450 und programmiert wird mit AVR-GCC in AVR
Studio 5.
Vielen Dank schon mal für eure Hilfe! :)
lg Attila
Vielen Danke einmal für die schnellen Antworten! Immer wieder ein
Wahnsinn :)
Ja ich dachte mir schon, dass das gehen muss.
Meine Code sieht wie folgt aus (die relevanten Sachen):
1
DDRH=(1<<PH0)|(1<<PH4)|(1<<PH5)|(0<<PH6)|(0<<PH7);// PH0, PH4 und PH5 als Ausgang und PH6 und PH7 als Eingang
2
PORTH=(0<<PH0)|(0<<PH4)|(0<<PH5)|(1<<PH6)|(1<<PH7);// PH6 und PH7 Pullup einschalten
Attila schrieb:> ISR (PCINT2_vect) // ISR Routine für Endlagentaster 2> {> _delay_ms(2000);> endlagentaster2 = 1;> }
Und was genau ist endlagentaster2 ?
Zeig doch bitte möglichst den kompletten Code. So komplex wird der schon
nicht sein.
Irgendwo hast du höchst wahrscheinlich eine Zuweisung an einen Port
gemacht, wo du eigentlich mittels | bzw & ein Bit setzeh bzw. löschen
müsstest. Du siehst es selber nicht, aber wir werden die Stelle finden.
Nur: Dazu brauchen wir deinen Code.
Eine andere Möglichkeit ist ein vergessenes volatile. Aber auch das kann
man nur erkennen, wenn man den kompletten Code sieht.
Über das was du da mit dieser ISR verbrochen hast, reden wir dann später
noch.
Der komplette Code is echt ziemlich viel, aber bitte :)
Das komische ist ja das es solange die Interrupts für den einen Pin
deaktiviert sind alles einwandfrei funktioniert.
Das ich nicht sehr effektiv programmiere ist mir bewusste, aber naja :P
Attila schrieb:> ISR (PCINT2_vect) // ISR Routine für Endlagentaster 2> {> _delay_ms(2000);> endlagentaster2 = 1;> }
Dir ist aber schon klar das du in der ISR den uC für 2 SEKUNDEN
"schlafen" legst und er nichts anderes mehr machen kann? Ist das
wirklich nötig? Kommentiere die Zeile mal aus und versuche's nochmal.
Alternativ: Erkläre uns wofür du das delay.... benötigst.
Gruß Dietmar
Hallo
DDRH = (1<<PH0) | (1<<PH4) | (1<<PH5) | (0<<PH6) | (0<<PH7);
PORTH = (0<<PH0) | (0<<PH4) | (0<<PH5) | (1<<PH6) | (1<<PH7);
Schau doch bitte mal in das Tutorial, wie das mit der Bitmanipulation
ist. Eine 0 irgendwohin geschoben und dann verodert bringts
irgendwie nicht.
Gruß
Joachim
Nicht sehr effizient ist gut gesagt. Das ist so ziemlich genau so wie
man es nicht macht.
Die Ansteuerung der Schrittmotoren macht man mittels Interrupts (um das
Timing einzuhalten), während Taster ruhig gepollt werden können, bzw.
die Endtaster werden ganz einfach vor der Ausgabe eines Schrittes
abgefragt, ob man überhaupt noch einen Schritt in diese Richtung machen
kann.
Abgesehen davon wimmelt es nur so von delays, die deinem Programm ein
Reaktionsverhalten aufzwingen, welches dich in den Wahsinn treiben wird.
Aber abgesehen davon.
1
voiddrehrichtung(void)
2
{
3
// X-Richtung
4
if(xrichtung==0)
5
{
6
PORTA=(1<<PA2)|(0<<PA6);
7
}
8
if(xrichtung==1)
9
{
10
PORTA=(1<<PA2)|(1<<PA6);
11
}
12
// Y-Richtung
13
if(yrichtung==0)
14
{
15
PORTH=(1<<PH0)|(0<<PH4);
16
}
17
if(yrichtung==1)
18
{
19
PORTH=(1<<PH0)|(1<<PH4);
20
}
21
}
Hier zb sind ein ganzer Haufen Fehler enthalten.
Du willst ein paar Pins schalten, schaltest aber jeweils den kompletten
Port um! Ein absolutes NoNo. Die Funktion soll nur IHRE Pins bedienen
und alle anderen in Ruhe lassen. Dazu brauchst du die Bit-setz bzw.
Bit-Lösch Operationen
Bit Setzen
PORTA |= ( 1 << PA2 );
Bit löschen
PORTA &= ~( 1 << PA2 );
Die Quittung, die du erhältst, wenn du das nicht sauber machst, hast du
ja jetzt gesehen. Ob du dasselbe auch noch an anderen Stellen machst,
hab ich nicht weiter kontrolliert.
Abgesehen davon: Du hast ein graphisches LCD drann. Das eignet sich
wunderbar um in einer Ecke Kontroll und Statusmeldungen während der
Debug Phase auszugeben. Dadurch kann dir dein Programm selber erzählen
warum es was macht bzw. nicht macht. Nutze diese Möglichkeit.
das wird nix.
Weder _delay_us noch _delay_ms kann man mit einer Variablen benutzen.
Das muss zwingend eine konstanter Zahlenwert sein, sonst stimmen die
Zeiten hinten und vorne nicht.
Nope.
Das ganze Konzept, dass die Endlagentaster auf einen Interrupt gehen,
ist murks
Frag doch hier
1
voidmotorinit(void)
2
{
3
// X-Achse Ansteuerung
4
sei();
5
do
6
{
7
xrichtung=1;
8
drehrichtung();
9
PORTA^=(1<<PA7);
10
_delay_us(1);
11
}
12
while(endlagentaster2==0);
13
14
.....
ganz einfach den Taster selber ab anstatt dass sich der erst kompliziert
über einen Pin Change Interrupt samt globaler Variabler (die einmal
volatile und einmal nicht volatile ist) bemerkbar machen kann. Ist doch
viel einfacher und zuverlässiger.
Ok vielen Dank für die rasche Hilfe, es funktioniert jetzt.
Danke für die vielen Ratschläge was das programmieren betrifft, werde
mir diese du Herzen nehmen :)
lg Attila
Attila schrieb:> Ok vielen Dank für die rasche Hilfe, es funktioniert jetzt.> Danke für die vielen Ratschläge was das programmieren betrifft, werde> mir diese du Herzen nehmen :)>
Fang gleich damit an, dir ein paar Ausgabefunktionen zu schreiben. Das
immer gleiche
1
itoa(yposition,ausgabe_yposition,10);
2
if(100<=yposition&&yposition<=200)
3
{
4
GLCD_WriteText(ausgabe_yposition,5,16);
5
}
6
if(10<=yposition&&yposition<100)
7
{
8
GLCD_WriteText(null,5,16);
9
GLCD_WriteText(ausgabe_yposition,6,16);
10
}
11
if(0<=yposition&&yposition<10)
12
{
13
GLCD_WriteText(null,5,16);
14
GLCD_WriteText(null,6,16);
15
GLCD_WriteText(ausgabe_yposition,7,16);
16
}
geht doch auf keine Kuhhaut. Das ist doch immer derselbe Code in den
einzelnen Zahlen-Ausgaben, bis auf den Variablennamen und die Position,
wo die Ausgabe hin soll. Ein perfekter Kandidat für eine Funktion, die
auf diese Spezialaufgabe spezialisiert ist.
und schon ist dein Code an dieser Stelle um über 80% kürzer geworden,
und was das Beste ist: er hat auch noch an Klarheit und Übersicht
gewonnen. Was vorher 3 Bildschirmseiten gebraucht hat, geht jetzt auf
etwas mehr als eine halbe Seite. (und wenn man wollte, könnte man die
Funktion noch kürzer machen)
Und so gibt es in deinem Code noch viele andere Dinge, die man mit ein
wenig Organisation kürzer und überschaubarer machen kann. Du läufst
nämlich Gefahr, dass du dir selbst eine Unüberschaubarkeit und
Komplexität zurecht programmierst, die du nicht mehr beherrschen und
überblicken kannst. Völlig unnötiger Weise. Wenn ein Code funktioniert,
dann ist man noch lange nicht fertig. Dann heißt es zurücklehnen, sich
das Machwerk ansehen und überlegen, wie man das Machwerk besser machen
kann.
Und wenn du dann in einiger Zeit drauf kommen wirst, dass du den Fall
negative Zahlen ja komplett übersehen hast, dann hast du genau nur eine
einzige Stelle, nämlich diese Funktion, die du pimpen musst, damit alle
Ausgaben auch mit negativen Zahlen korrekte Anzeigen produzieren.
(Kann es sein, dass du in C mit der Argumentübergabe auf Kriegsfuss
stehst? Wenn ich mir deine Funktionen so ansehe fällt mir auf, dass du
alles immer über globale Variablen abhandelst. Selbst dann, wenn sich
für die Funktion ein Argument förmlich aufdrängt!)
Attila schrieb:> Ok vielen Dank für die rasche Hilfe, es funktioniert jetzt.
Du hast Dein Programm anhand Karl Heinz' Tipps innerhalb einer knappen
Stunde derart umschreiben können, dass es nun funktioniert? Ich bin
jetzt echt baff...
Das Problem war nur wie Karl Heinz Buchegger geschrieben hat, dass ich
ständig den ganzen Port geschrieben und nicht nur die einzlenen Bits.
Der restliche Code funktioniert ja, wenn auch über 1000 Ecken und
teilweise sehr umständlich. Warum ich die Endlagentaster mit Interrupts
gelöst habe weiß ich mittlerweile selber nicht mehr...
Vielen Dank für die Tipps bezüglich der besseren Programmgestaltung. Ich
weiß selber das ich teilweise sehr umständlich programmiert habe, aber
ich bin etwas im Zeitdruck gewesen und von daher ging es mir in erster
Linie nur darum das es funktioniert.
lg und nochmals vielen vielen Dank für die rasche und tolle Hilfe
Attila