Hallo,
Ich möchte einen Attiny24 mit folgendem Programm versehen:
1
#include<avr/io.h>
2
#include<stdint.h>
3
#include<avr/interrupt.h>
4
#ifndef F_CPU
5
#define F_CPU 1000000UL
6
#endif
7
#ifndef TIMER0_OVF_vect
8
#define TIMER0_OVF_vect TIMER0_OVF0_vect
9
#endif
10
11
#include<util/delay.h>
12
intmain(void)
13
14
{
15
struct
16
{
17
unsignedeingangspin1:1;//Speicher Richtung1
18
unsignedeingangspin2:1;//Speicher Richtung2
19
unsignedschaltpin1:1;//Richtungsumschalter
20
21
}x;
22
23
DDRA=0b00011;
24
PORTA=0b11100;
25
TCCR0|=(1<<CS02)&(1<<CS00);//Timer mit 1/1024 der Taktfrequenz
26
TIMSK|=(1<<TOIE0);
27
sei();
28
while(0)
29
{
30
if(PINA&(1<<PINA2))
31
{
32
x.eingangspin1=1;//Richtung 1 Einfahrt
33
}
34
if(PINA&(1<<PINA3))
35
{
36
x.eingangspin1=0;//Richtung 1 Ausfahrt
37
}
38
if(PINA&(1<<PINA4))
39
{
40
x.eingangspin2=1;//Richtung 2 Einfahrt
41
}
42
if(PINA&(1<<PINA5))
43
{
44
x.eingangspin2=1;//Richtung 2 Ausfahrt
45
}
46
47
//Sprungadresse
48
}
49
return(0);
50
ISR(TIMER0_OVF_vect)
51
{
52
53
}
54
if(0<<x.eingangspin1&(1<<x.schaltpin1))
55
{
56
PORTA=(1<<PORTA0)&(0<<PORTA1);
57
x.schaltpin1=0;
58
}
59
if(0<<x.eingangspin2&(0<<x.schaltpin1))
60
{
61
PORTA=(0<<PORTA0)&(1<<PORTA1);
62
x.schaltpin1=1;
63
}
64
65
66
67
68
}
Meine Probleme mit diesem Programm:
1)Scheint mit der Timer noch nicht definiert zu sein. Stimmt das?
Der Compiler zeigt bei fast allen Befehlen, die mit dem Timer
zusammnenhängen, Fehler an.
2)Ich suche schon vergebens nach den Befehlen für Sprünge im Programm.
Sowohl die Forensuche als auch das Tutorial fördern nichts brauchbares
zu Tage.
Hoffe auf Hilfe.
Gruß Jannis
> Der Compiler zeigt bei fast allen Befehlen, die mit dem Timer> zusammnenhängen, Fehler an.
Fehler z.B. dass du die ISR innerhalb von main() definierst?
Und Warnungen, dass der Code nach return (0); nie erreicht werden kann?
Sprünge im Programm vermeidet man.
Einerseits weil der Anfänger sich mit Sprüngen der Lächerlichkeit preis
gibt und andererseits weil es in 99.9% der Fälle eine sprunglose
Variante gibt.
Hallo,
erstmal Danke für die Antworten.
Wie macht man es denn besser?
Ich habe noch nie Interrupts benutzt, deshalb weiß ich auch nicht wie es
geht. Ich habe das zum großteil aus dem Tutorial.
Gruß Jannis
Im Tutorial stehen aber keine so vergurkten Beispiele, oder?
Es hapert an der elementaren Schreibweise eines C-Programms:
# Funktionsdefinition innerhalb einer Funktion...
# Code nach einem return auf oberster Funktionsebene...
Die C Syntax musste du einigermaßen beherrschen, bevor es an komplexere
Funktion des Programmes wie Interrupts geht.
Noch'n Tip:
Bevor du loscodest, schreib dir in normaler Sprache auf, was du machen
willst. Welche Eingaben hast du, welche Ausgaben soll es geben und wie
wirken die Eingaben auf die Ausgaben.
Und wenn du fit bist, setzt du diese umgangssprachliche Beschreibung in
eine Statemachine um. In diesem Artikel siehst du auf den ersten
beiden Seiten, wie Karl-Heinz das Problem "Ampelsteuerung" ohne C-Code
beschrieben hat. Wenn du so in deinen Projekten vorgehst, wird es auf
die Dauer einfacher, als das bisherige loscoden und nach Hilfe suchen.
Hallo,
ein Softwarekonzept existiert bereits, da ich dieses Programm erst
geschrieben habe, nachdem ich mich mit meinen Partnern über die späteren
Aufgaben unterhalten habe.
>Code nach einem return auf oberster Funktionsebene
denn Code habe ich da hingeschrieben, weil ich Sprungadressen benutzen
wollte. Davon hast du mir gerade abgeraren, d.h. ich muss das erstmal
änderen.
> Funktionsdefinition innerhalb einer Funktion
Wie macht man es denn richtig?
Muss ich ein extra void benutzen?
Gruß Jannis
Da hapert es an allen Ecken und Kanten, auch an den grundlegendsten
1
if(0<<x.eingangspin1&(1<<x.schaltpin1))
Ich vermute, dass du folgendes realisieren wolltest:
1
Wenn eingangspin1 Null ist und schaltpin1 Eins ist, dann ...
Die Codezeile macht das noch nicht mal ansatzweise. Du hast
offensichtlich einfach nur wild geraten.
Du kannst C aber nicht einfach durch Raten, Rumprobieren und Kopieren
anderer Sourcen lernen. Du solltest dir ein C-Buch beschaffen, und das
mal richtig von Anfang an durcharbeiten (notfalls auch ein
Online-Tutorial (*)). Sämtliche Fragen hier hätten sich damit dann schon
mal erledigt. Danach kannst du dich dann daran machen, ein konkretes
Programm für deinen AVR zu schreiben, und hier Fragen zu konkreten
Details zu stellen. Ich weiß, dass das eine extrem unbeliebte Antwort
ist, aber es ist das einzig Sinnvolle in so einem Fall.
(*): Damit meine ich aber nicht das Tutorial hier, denn das ist für
Leute gedacht, die bereits C können.
Hallo,
das C-Buch ist bereits bestellt, aber leider noch nicht da.
Da in meinen vorrangegangenden Fragen immer auf das hiesige Tutorial
verwiesen wurde, habe ich nur das zu Rate gezogen.
Was schreibt man den an Stelle von if
(0<<x.eingangspin1&(1<<x.schaltpin1))?
Gruß Jannis
Jannis C. schrieb:>>Code nach einem return auf oberster Funktionsebene> denn Code habe ich da hingeschrieben, weil ich Sprungadressen benutzen> wollte. Davon hast du mir gerade abgeraren, d.h. ich muss das erstmal> änderen.>> Funktionsdefinition innerhalb einer Funktion> Wie macht man es denn richtig?> Muss ich ein extra void benutzen?
Auch das sind alles grundlegende Dinge, die sich komplett erledigen
würden, würdest du mal C richtig von Anfang an lernen, statt wild drauf
los zu probieren.
> Was schreibt man den an Stelle von if> (0<<x.eingangspin1&(1<<x.schaltpin1))?
Was würde es dir nützen, wenn ich da jetzt die korrekte Zeile
hinschreiben würde? Du wärst dann trotzdem noch nicht in der Lage, den
Rest des Programms selber zu schreiben (ich habe diese eine Zeile ja nur
als Beispiel raus gefischt). Es würde darauf hinauslaufen, dass quasi
das komplette Programm von uns (dem Forum) geschrieben würde, und das
ist nicht Sinn der Sache.
Hallo,
>Es würde darauf hinauslaufen, dass quasi
das komplette Programm von uns (dem Forum) geschrieben würde, und das
ist nicht Sinn der Sache.
Stimmt, dafür ist ein Forum nicht da. Hast du denn einen Vorschlag für
ein gutes C-Tutorial, welches du ansprachst?
Ein Anhaltspunkt oder die Richtung der Fehler wären auch eine Lösung.
Nebenbei möchte ich auch nicht jedesmal, wenn ich ein Programm schreibe,
mit jeder Kleinigkeit hier aufschlagen müssen.
Gruß JAnnis
> Stimmt, dafür ist ein Forum nicht da. Hast du denn einen Vorschlag für> ein gutes C-Tutorial, welches du ansprachst?
Ich kann keines konkret (aus eigener Erfahrung) empfehlen.
Hier ist eines, das ich so auf die Schnelle gefunden habe:
http://www.c-howto.de/tutorial-einfuehrung.html> Ein Anhaltspunkt oder die Richtung der Fehler wären auch eine Lösung.
Ein großer Teil der Fehler hat mit AVRs im Speziellen nichts zu tun,
sondern sind einfach nur mangelnde C-Grundkenntnisse.
Wie bereits gesagt, stelle dein AVR-Programm erst mal zurück, und
konzentriere dich auf das C-Lernen. Danach sieht die Sache dann schon
gleich ganz anders aus.
Hallo,
ist es richtig für die Abfrage von Variablen
if ( Variable1 & (1<<Variable2)) zu schreiben, oder habe ich da das
Tutorial missverstanden?
Gruß Jannis
Jannis C. schrieb:> Hallo,> ist es richtig für die Abfrage von Variablen
nicht Variablen
> if ( Variable1 & (1<<Variable2)) zu schreiben, oder habe ich da das> Tutorial missverstanden?
diese Schreibweise benutzt man wenn man wissen will, ob das Bit
'Variable2' in Variable1 gesetzt ist oder nicht.
Willst du wissen ob am PINA das Bit PA2 gesetzt ist (weil da zb ein
Taster drann hängt), dann schreibst du
if( PINA & ( 1 << PA2 ) )
mach was
Danke,
wieder was gelernt, habe jetzt ein Beispielprogramm zu der Abfrage von
Variablen gefunden und da verwenden die ((Variable1>1)&(Variable2>1)).
Ist das besser?
Gruß Jannis
> ((Variable1>1)&(Variable2>1))
Falls das von dir richtig abgeschrieben wurde, ist es ein Gefummel im
Originalprogramm.
Logische Bedingungen verknüpft man mit einem logischen Operator. Wenn
ein logisches UND gewollt ist, dann ist && der entsprechende Operator.
... Variable1 größer 1 UND Variable2 größer 1 ...
Jemand der an dieser Stelle ein bitweises UND & als Operator benutzt,
sollte einen guten Grund dafür haben. Sorry, einen guten Grund sehe ich
an obiger Stelle nicht. Und damit sieht die Stelle nach "da weiss jemand
nicht was er macht" (oder Schreibfehler) aus und entsprechend
vorbelastet würde ich an den Rest des Codes oder des Tutorials ran
gehen.
Hallo,
Ich habe mein Buch, welches sich speziel auf die AVRs bezieht nach einem
Ähnlichen Fall wie bei mir durchsucht und rausgekommen sind halt die
oben genannten Zeilen. Jetzt habe ich das C-Tutorial, welches schon
genannt wurde, konsulidiert.
http://www.c-howto.de/tutorial-verzweigungen-if-else.html. Ich denke,
was da über die Verwendung von Variablen steht, past auch zu meinem
Fall?
Gruß Jannis
Du bist auf dem richtigen Weg, wenn du das C-Howto-Tutorial oder ein
anderes durch arbeitest.
Behalte aber im Hinterkopf, dass
1. die Sachen dort C auf einem PC erklären. Es wird später bei C auf dem
AVR Unterschiede und Feinheiten geben. Da setzt das AVR-GCC-Tutorial
dann an.
2. das C-Howto-Tutorial hat auch Fehler (z.B. bei der Erklärung
Deklaration und Definition von Variablen). Vergleiche mehrere Tutorials
oder Bücher zu einem Thema oder frage bei Unklarheiten nach.
Hallo,
ich habe das Programm noch mal nach Syntaxfehlern überarbeitet und die
eine Lösung für mein Sprungadressenproblem gefunden.
Jetzt habe ich ein Problem mit dem Timer.
Ohne den Befehl TIMSK kann ich es vollständig compillieren, mit wirft er
mit Error um sich.
Mein Code:#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#ifndef F_CPU
#define F_CPU 1000000UL
#endif
#ifndef TIMER0_OVF_vect
#define TIMER0_OVF_vect TIMER0_OVF0_vect
#endif
struct
{
unsigned eingangspin1:1; //Speicher Richtung1
unsigned eingangspin2:1; //Speicher Richtung2
unsigned interuptbit:1; //Wenn die Weiche schalten soll
unsigned schaltpin1:1; //Richtungsumschalter
}x;
ISR (TIMER0_OVF_vect)
{
x.interuptbit=1;
}
int main(void)
{
DDRA = 0b00011;
PORTA = 0b11100;
TCCR0 |= (1<<CS02)&(1<<CS00); //Timer mit 1/1024 der Taktfrequenz
TIMSK |= (1<<TOIE0);// Overflow Interrupt erlauben
sei();// Global Interrupts aktivieren
while (0)
{
if (PINA&(1<<PINA2))
{
x.eingangspin1=1; //Richtung 1 Einfahrt
}
if (PINA&(1<<PINA3))
{
x.eingangspin1=0; //Richtung 1 Ausfahrt
}
if (PINA&(1<<PINA4))
{
x.eingangspin2=1; //Richtung 2 Einfahrt
}
if (PINA&(1<<PINA5))
{
x.eingangspin2=1; //Richtung 2 Ausfahrt
}
if (1<<x.interuptbit)
{
if ((x.eingangspin1==0)&&(x.schaltpin1==1))
{
PORTA = (1<<PORTA0)&(0<<PORTA1); //Richtung1Stellung
x.schaltpin1=0;
}
if ((x.eingangspin1==0)&&(x.schaltpin1==0))
{
PORTA = (0<<PORTA0)&(1<<PORTA1); //Richtung2Stellung
x.schaltpin1=1;
}
x.interuptbit=0;
}
return (1);
}
}
Tja.
> while (0)> {> was hier ausgeführt werden soll wird NIE ausgeführt> }
Der AVR-GCC ist wahrscheinlich so schlau den kompletten Anweisungsblock
des while rückstandsfrei zu entsorgen.
> Ohne den Befehl TIMSK kann ich es vollständig compillieren, mit wirft er> mit Error um sich.
Bei manchen AVR heisst dieses Timer-Mask-Register anders. Beim
Attiny24 gibt es z.B. ein TIMSK0, ein TIMSK1 und ein TIMSK2, je nach
dem ob du Timer0, Timer1 oder Timer2 beeinflussen willst.
TCCR0 ist der nächste Kandidat. Das gibt es beim Attiny24 so nicht.
Dort gibt es mehr Einstellmöglichkeiten und dafür braucht es zwei
Register TCCR0A und TCCR0B.
Steht aber alles im Datenblatt.
Hallo,
>TIMSK
selber übersehen.
Heißt natürlich
TIMSK0.
>TCCR0A |=(0<<COM0A1)&(0<<COM0A2);
Diese Zeile ist falsch. Ich bin aber auch ein Depp.
Der Compiller spuckt immernoch eine Warnug bezüglich der
Interuptdeklaration aus. Muss ich da noch was ändern?
Gruß Jannis
Welche Warnung?
> PORTA = (1<<PORTA0)&(0<<PORTA1); //Richtung1Stellung> PORTA = (0<<PORTA0)&(1<<PORTA1); //Richtung2Stellung
Beeinflussen auch die internen Pullups. Das solltest du nicht machen!
> PORTA = 0b11100;
Da fehlt ein Pullup.
> if (PINA&(1<<PINA2))> if (PINA&(1<<PINA3))
Diese Programmlogik gibt PINA3 einen Vorrang vor PINA2. Ist das
beabsichtigt?
> if (PINA&(1<<PINA2))> if (PINA&(1<<PINA3))
Diese Programmlogik verhindert, dass x.eingangspin1 einen neuen
definierten Wert bekommt, wenn beide if-Bedingungen nich zutreffen. Darf
der alte Wert von x.eingangspin1 dann weiter benutzen?
> if (1<<x.interuptbit)
Ist immer wahr, selbst wenn x.interuptbit == 0 ist: 1<<0 == 1 und 1<<1
== 2. Beides ist ungleich 0. C-Tutorial lesen.
> if ((x.eingangspin1==0)&&(x.schaltpin1==1))> if ((x.eingangspin1==0)&&(x.schaltpin1==0))
Programmlogik ist nicht durchdacht.
>>> Bevor du loscodest, schreib dir in normaler Sprache auf, was du machen>>> willst. Welche Eingaben hast du, welche Ausgaben soll es geben und wie>>> wirken die Eingaben auf die Ausgaben.
Ich weiss zwar nicht was du dir davon versprichst und ich kann es auch
nicht erraten, weil dein Programm extrem konfus ist. Aber das macht mit
Sicherheit nicht das, was du denkst das es machen sollte. Was auch immer
das sein mag.
Kleiner Tip:
Wenn du umgangssprachlich bei dir denkst:
Och, jetzt mach ich das UND dann mach ich noch das
dann bedeutet das in den seltensten Fällen, dass in einem formalen
Ablauf wie zb in einem Programm, ein UND auftaucht. Das ist einfach nur
eine Abfolge von Ereignissen und dieses umganssprachliche UND ist
lediglich ein Füllwort ohne weitere Bedeutung.
Du willst:
den Pin PA0 auf 1 setzen UND du willst den Pin PA1 auf 0 setzen.
UNd genau hier haben wir so einen Fall, wo dieses UND keine weitere
Bedeutung hat und auf keinen Fall irgendetwas mit einem logischen oder
binären UND zu tun hat. Dieses UND kennzeichnet einfach nur, dass eine
Aktion abgeschlossen ist und dass eine neue Aktion anfängt.
Welche Aktionen sind das.
Da ist zum ersten die Aktion: Pin PA0 auf 1 setzen
UNd zum zweiten ist die andere Aktion: Pin PA1 auf 0 setzen
Und dafür setzt du jetzt die kanonischen Lösungen ein. Einen Pin auf 1
setzen macht man mit
port |= ( 1 << Pin )
und einen Pin auf 0 setzen macht man mit
port &= ~( 1 << Pin )
Diese Dinge sind wie Phrasen in einer Umgangsprache und können meistens
auch so verwendet werden. Wenn du bei dir denkst: Ach, wäre das jetzt
schön, wenn ich den Pin auf 1 setzen würde, dann bedeutet das in C
Schreibweise
port |= ( 1 << Pin )
Das muss wie ein Automatismus sein: Du denkst 'Pin auf 1 setzen' und
deine Finger schreiben die C-Form dieses Gedankens.
Sinngemäss natürlich für Pin auf 0 setzen genauso
Angewendet auf dein Beispiel bedeutet das, das nicht das hier
Hallo,
die Warnung:
../SchleifeMEC.c:17: warning: 'TIMER0_OVF0_vect' appears to be a
misspelled signal handler
Wieso beienflusst das die Pull-Ups? Das ist mit irgendwie nicht ganz
klar.
Den fehlenden habe ich schon ergänzt. Danke.
Der Vorzug ist nicht relevant.
Danke für den Hinweis, die Eingangspins müssen aber immer neu abgefragt
werden, sonst bringt das Programm nicht das, was es soll. Nach erneutem
Nachdenken musste aber der Code geändert werden:
1
#include<avr/io.h>
2
#include<stdint.h>
3
#include<avr/interrupt.h>
4
#ifndef F_CPU
5
#define F_CPU 1000000UL
6
#endif
7
#ifndef TIMER0_OVF_vect
8
#define TIMER0_OVF_vect TIMER0_OVF0_vect
9
#endif
10
struct
11
{
12
unsignedeingangspin1:2;//Speicher Richtung1
13
unsignedeingangspin2:2;//Speicher Richtung2
14
unsignedinteruptbit:2;//Wenn die Weiche schalten soll
15
unsignedschaltpin1:2;//Richtungsumschalter
16
}x;
17
ISR(TIMER0_OVF_vect)
18
{
19
x.interuptbit=1;
20
}
21
intmain(void)
22
23
{
24
25
DDRA=0b000011;
26
PORTA=0b111100;
27
TCCR0B|=(1<<CS02)&(1<<CS00);//Timer mit 1/1024 der Taktfrequenz
>>> if (1<<x.interuptbit)
Nóchmal danke für den Hinweis, das habe ich vergessen zu Ändern.
Sonst glaube, das es jetzt so funktioniert, wie ich es geplant hatte.
Gruß Jannis
Jannis C. schrieb:> ../SchleifeMEC.c:17: warning: 'TIMER0_OVF0_vect' appears to be a> misspelled signal handler
Schmeiss endlich das vermaledeite #define raus
1
#ifndef TIMER0_OVF_vect
2
#define TIMER0_OVF_vect TIMER0_OVF0_vect
3
#endif
> Wieso beienflusst das die Pull-Ups? Das ist mit irgendwie nicht ganz> klar.
Weil du an den ganzen Port eine Zuweisung machst! Jedes einzelne Bit wir
dneu beschrieben. Unter anderem auch die Bits PA2 bis PA5. Sie werden
auf 0 gesetzt. Und damit sind dann die Pullup Widerstände an diesen Pins
abgeschaltet.
> Den fehlenden habe ich schon ergänzt. Danke.> Der Vorzug ist nicht relevant.> Danke für den Hinweis, die Eingangspins müssen aber immer neu abgefragt> werden, sonst bringt das Programm nicht das, was es soll.
Das tut es offenbar auch jetzt nicht
> Nach erneutem> Nachdenken musste aber der Code geändert werden:
Genau:
Schmeiss das Programm weg und schreib ein neues. Aber diesmal vorher
anfangen zu überlegen und vor allen Dingen nicht künsteln. Deine
Bitflags kannst du dir alle in die Haare schmieren, braucht kein Mensch.
Und nenn die Dinge nicht .....pin
Deine Variablen haben eine logische Bedeutung! Das sind Bezeichnungen,
die du als Variablenname benutzen kannst.
So wie ich das sehe, brauchst du auch keinen Timer. Der erfüllt keinen
vernünftigen Zweck.
Hallo,
Sorry mein vorheriger Beitrag kamm leider bevor ich eure gelesen habe.
@Karl-Heinz:
Kannst du Gedanken lesen?
Du hast recht, so habe ich gedacht.
Ist aber schon korriegiert.
Gruß Jannis
Jannis C. schrieb:> Okay,> bevor ich jetzt ein neues Programm schreibe, noch eine Frage:> Wie verhindere ich, dass ich die Pull-Ups beienflusse?> Gruß Jannis
indem du um während des Programmlaufs um solche Dinge
1
PORTA=...wasauchimmer...;
(also Zuweisungen an den kompletten Port) einen grossen Bogen machst,
und immer mittels
1
PORTA|=(1<<PORTA0);
2
PORTA&=~(1<<PORTA1);
immer nur das eine Bit ansprichst, das du auf 0 oder 1 setzen willst.
Es ist wirklich ganz einfach. Durch die letzte Form ist gewährleistet,
dass die anderen Bits an diesem Port nicht verändert werden.
Was soll es denn eigentlich werden?
Deine Kommentare erinnern mich irgendwie an eine Art Ampelsteuerung in
einer Parkhaus Ein/Ausfahrt.
Allerdings: So wird das höchst wahrscheinlich nichts.
Aber ehe ich da jetzt weiter spekuliere, warte ich mal auf die
Projektbeschreibung.
Jannis C. schrieb:> Okay,> bevor ich jetzt ein neues Programm schreibe,
Erst über das Problem nachdenken!
Dann einen Ablaufplan auf Papier malen.
Dann diesen Plan mit dem Finger durchspielen und nachsehen ober
funktioniert. Dabei beachten: Dein µC arbeitet rasend schnell. Deine
Hauptschleife wird in ein paar µs einmal, in einer Sekunde also viele
tausend mal abgearbeitet. Daraus folgt: Aus Sicht des µC sind externe
Ereignisse selten und seeeeeehr langsam.
Und vor allem sollten die Einrückungen auch der entsprechenden
Schachtelungstiefe entsprechen. Selbst wenn der Code aus dem obigen
Listung einigermaßen korrekt wäre, würde er nach einem
Schleifendurchlauf ins Nirvana springen. Mit sehr viel Glück (oder eher
Pech...) würde die Programmausführung dann irgendwann wieder von vorne
beginnen.
Hallo,
also Projektbeschreibung:
Es handelt sich um eine Wendeschleife für das Carsystem, die Einspurig
in beide Richtung befahrbahr sein soll. Am Anfang befindet sich eine
Weiche die später mal mit Hilfe des Timers umgeschaltet werden soll.
Dies darf aber nur passieren, wenn die Schleife leer ist. Ich muss in
jede Richtung also Ein-und Ausfahrt kontrollieren mit jeweils einer
Variablen. Wenn der Interupt jetzt eintritt, muss geschaut werden, ob
die Schleife leer ist und wenn ja, dann schaltet er um.
Gruß Jannis
Hallo,
ich habe jetzt ein neues Programm geschrieben, welches dem ersten doch
recht änlich sieht, weil es das gleiche tun soll, was es aber vielleicht
noch nicht tut.
Ich habe mich jetzt um volgende Dinge gekümmert:
1)Ich habe versucht es korreckt Einzurücken.
2)Ich bin von meinem Bitfeld abgerückt und habe jetzt richtige
Variablen.
3)Die Variablen haben jetzt praktische Namen, die sich auf die
Verwendung beziehn.
Ersteinmal der neue Code, zu dem ich noch eine Frage habe:
Ist die while-Schleife okay oder muss ich die noch modifizieren?
1
#include<avr/io.h>
2
#include<stdint.h>
3
#include<avr/interrupt.h>
4
#ifndef F_CPU
5
#define F_CPU 1000000UL
6
#endif
7
#include<util/delay.h>
8
uint8_trichtung1;
9
uint8_trichtung2;
10
uint8_tumschalter;
11
uint8_tinterupt;
12
13
ISR(TIMER0_OVF_vect)
14
{
15
interupt=1;
16
}
17
intmain(void)
18
19
{
20
21
DDRA=0b000011;
22
PORTA=0b111100;
23
TCCR0B|=(1<<CS02)&(1<<CS00);//Timer mit 1/1024 der Taktfrequenz
Die while-Schleife ist immer noch Mist, weil ein return 0; darin steht.
Sie wird daher nur einmal ausgeführt, dann nie mehr.
Deine Beschreibung in
Beitrag "Re: Problem mit Sprungadressen und Timer" geht in die richtige
Richtung, aber eine Skizze wäre besser. In der Beschreibung fehlen alle
Angaben wo die Sensoren (Eingaben) sitzen. Ohne diese Angaben kann die
Programmlogik nicht kontrolliert werden.
Das Programm kann man lesbarer schreiben (s. unten). Korrigiert wurden
die ### markierten Stellen. Die gewünschte Funktion der Umschaltung habe
ich mir aus der Beschreibung zusammengereimt und abgeändert.
1
/*
2
* Controller für Wendeschleife
3
* Attiny24 @ 1 Mhz
4
*/
5
#include<avr/io.h>
6
#include<stdint.h>
7
#include<avr/interrupt.h>
8
9
#ifndef F_CPU
10
#define F_CPU 1000000UL
11
#endif
12
#include<util/delay.h>
13
14
#define PRELLZEIT_MS 0 /* 100 */
15
#define BESETZT 1
16
#define FREI 0
17
#define RICHTUNG1 1
18
#define RICHTUNG2 0
19
20
uint8_trichtung1;
21
uint8_trichtung2;
22
uint8_tumschalter;
23
volatileuint8_tinterupt;// ###
24
25
ISR(TIMER0_OVF_vect)
26
{
27
interupt=1;
28
}
29
30
voidentprellen(void)
31
{
32
// Diese Zeit geht von der Reaktionszeit
33
// auf den Timer0 Interrupt ab! Nicht zu
34
// lange einstellen!
35
#if PRELLZEIT_MS
36
_delay_ms(PRELLZEIT_MS);
37
#endif
38
}
39
40
intmain(void)
41
{
42
// PA5 ... PA2: interne Pullups ein
43
PORTA=0b00111100;
44
45
// Grundstellung Wendeschleife
46
PORTA|=(1<<PORTA0);
47
PORTA&=~(1<<PORTA1);
48
richtung1=FREI;
49
richtung2=FREI;
50
umschalter=RICHTUNG1;
51
52
// PA1 ... PA0: Ausgang Wendeschleife
53
// PA5 ... PA2: Eingang Sensoren
54
DDRA=0b00000011;
55
56
// Timer0 einstellen
57
// t = 1/(1000000/256/1024) = ~262 ms
58
TCCR0A=0;// Normal Port Operation
59
TCCR0B|=(1<<CS02)|(1<<CS00);// 1/1024 der Taktfrequenz ###
60
TIMSK0|=(1<<TOIE0);// Overflow Interrupt erlauben
61
sei();// Global Interrupts aktivieren
62
63
while(1){
64
// Ständig überwachen, ob Wendeschelife besetzt ist
65
// Sensor Richtung 1 Einfahrt überfahren?
66
if((PINA&(1<<PINA2))){
67
richtung1=BESETZT;
68
entprellen();
69
}
70
// Sensor Richtung 1 Ausfahrt überfahren?
71
if((PINA&(1<<PINA3))){
72
richtung1=FREI;
73
entprellen();
74
}
75
// Sensor Richtung 2 Einfahrt überfahren?
76
if((PINA&(1<<PINA4))){
77
richtung2=BESETZT;
78
entprellen();
79
}
80
// Sensor Richtung 2 Ausfahrt überfahren?
81
if((PINA&(1<<PINA5))){
82
richtung2=FREI;
83
entprellen();
84
}
85
86
// Regelmäßig und häufig (beim Timer0-Interrupt alle ~262 ms)
Hallo,
das Programm ist ja der Hammer. DANKE.
Ich habe aber noch zwei Verarständnisproblem:
1)Brauche ich bei einem Interupt immer volantine, wenn ich im Interupt
eine Variable ändere?
2)Können sich jetzt auch mehere Autos in eine Richtung in der Schleife
befinden?
Sonst ist das für mich ein klasse Anschauungsprogrammm. Nicht nur für
den Stil.
Und wenn ich jetzt für den Timer ein externes Signal nehme, kann ich da
einen Quarz verwenden? Ich muss dann natürlich noch TCCR0B ändern.
Gruß Jannis
1) Nein, nicht für alle. Aber für die gemeinsam mit dem
Nicht-Interrupt-Teil benutzen Variablen. Ist im Artikel Interrupt
erklärt.
2) Weiss ich nicht. Ich habe nur nebulöse Vorstellungen was ein
Carsystem und eine Wendeschleife sein konnte. Deine Beschreibung ist für
einen Laien auf diesem Gebiet wie mich zu dünn. Du hast jetzt das
Problem, vor dem ich auch stand: Du versuchst aus dem Programmcode die
Hardwaresituation zu ermitteln. Du merkst anscheinend wie schwer das
ist.
3) In AVR-Tutorial: Equipment ist erklärt, wie du den AVR takten
kannst. Ein externer Quarz kann Sinn machen, wenn du später mal eine
rel. genaue Zeitnahme machen willst oder Datenübertragung zum PC planst.
Im Moment ist ein Quarz nicht nötig.
Jannis C. schrieb:> Hallo,> ich meinte,dass ich den Timer extern Takte.
Wozu soll das gut sein?
Um Entprellung kommst du sowieso nicht herum.
ALso kannst du auch in Software zählen wieviele Autos in der Schleife
sind. (Nach einem Stromausfall stimmt die Zahl sowieso nicht mehr)
Hallo,
ich habe versucht, die Methode von Helfer, auf ein neues Programm zu
übertragen. Ich wollte mal wissen, ob ich das mit den Abstufungen und
den Deklarationen jetzt richtig verstanden habe. Der schon fertige Teil
des Codes:
1
/*ParkplatzMEC
2
*@Atmega8 mit 8MHZ
3
*/
4
#include<avr/io.h>
5
#include<stdint.h>
6
#include<avr/interrupt.h>
7
8
#ifndef F_CPU
9
#define F_CPU 8000000UL
10
#endif
11
#include<util/delay.h>
12
13
#define Prellzeit_MS 0
14
#define Parkplatz1 1
15
#define Parkplatz2 2
16
#define Parkplatz3 3
17
#define Parkplatz4 4
18
#define Frei 0
19
#define Besetzt 1
20
21
uint8_tEinfahrt1;
22
uint8_tEinfahrt2;
23
uint8_tEinfahrt3;
24
uint8_tEinfahrt4;
25
uint8_tAusfahrt;
26
volatileuint8_tAusfahrttimer;
27
volatileuint8_tBusrunde;
28
29
ISR(TIMER0_OVF_vect)
30
{
31
}
32
ISR(EXT_INT0_vect)
33
{
34
Busrunde=1;
35
}
36
ISR(EXT_INT1_vect)
37
{
38
}
39
intentprellen(void)
40
{
41
_delay_ms(100);
42
43
#if Prellzeit_MS
44
_delay_ms(Prellzeit_MS);
45
#endif
46
}
47
intbusfahrt(void)
48
{
49
50
}
51
intmain(void)
52
{
53
;
54
DDRB=0b0;
55
DDRC=0b0;
56
DDRD=0b0;
57
PORTB=0b0;
58
PORTC=0b0;
59
PORTD=0b0;
60
MCUCR|=(1<<ISC10);
61
MCUCR|=(1<<ISC00);
62
GICR|=(1<<INT0);
63
GICR|=(1<<INT1);
64
sei();
65
/*Grundstellung
66
*/
67
68
while(1)
69
{
70
if(Busrunde==1){
71
}
72
73
}
74
return0;
75
}
Ich habe noch nicht alle Teile vollständig ausgefüllt. Zum Beispiel den
Timerl
Gruß Jannis
Tut mir leid. Ich bin schwer von Begriff. Deine Skizze verstehe ich
immer noch nicht. Die Richtung 1 und 2 sowie die Zuordnung der vier
Sensoren ist mir immer noch ein Rätsel. Ich will auch nicht weiter mit
"Zeig mal", "Mach doch" nerven und ziehe mich deshalb aus diesem Thread
zurück. Einem Pferd, dass 46 Runden gelaufen ist, sollte man das
Gnadenbrot gönnen.
Hallo,
also
@Helfer: Meinen Skizze ist absoluter Mist. Ich werde eine neue machen,
die man auch verstehen kann. Ich habe die meinen Partnern gezeigt, die
wusten, worum es geht und die haben es auch nicht verstanden. Und
desweiteren nervst du mich überhaupt nicht, ich freue mich immer über
Intresse an meinen Projekten. Und wenn ich bedenke wie ich euch hier mit
meinem Raten genervt habe, bin ich euch sehr dankbar, dass das hier
überhaupt noch jemand liest.
Gruß Jannis
Jannis C. schrieb:> Hallo,> also> @Helfer: Meinen Skizze ist absoluter Mist. Ich werde eine neue machen,> die man auch verstehen kann.
Beschreib auch den Ablauf, was passieren soll.
Aus Sicht eines Autos und aus Sicht der Wechselschleife
Hallo,
mal eine Frage offtopic:
Was rechnet der Prozessor wenn ich inkremintieren (also ++x) ?
Wo liegt der Unterschied zwischen ++x und +x ?
Gruß Jannis
Jannis C. schrieb:> Hallo,> mal eine Frage offtopic:
Nicht wirklich.
Deine Frage zeigt ganz klar, dass du ganz dringend ein C-Buch brauchst
und das auch durcharbeiten musst.
> Was rechnet der Prozessor wenn ich inkremintieren (also ++x) ?
inkrementieren bedeuet: 1 dazuzählen
In C gibt es 2 Formen:
++x und x++
i sei gleich 5
* j = ++x
j erhält den inkrementierten Wert von i und i wird inkrementiert
j ist dann gleich 6
i ist dann gleich 6
* j = x++
j erhält den Wert von i und i wird inkrementiert
j ist dann gleich 5
i ist dann gleich 6
> Wo liegt der Unterschied zwischen ++x und +x ?
+x ist kein Inkrement und hat auch nichts damit zu tun. das + an dieser
Stelle ist einfach nur ein Vorzeichen, so wie auch - einfach nur ein
Vorzeichen ist und -x den negativen Wert von x angibt. Nur dass sich bei
einem + ganz einfach nichts tut und x sich nicht verändert.
-x kann man als mathematisch kürzere Schreibweise für (0-x) auffassen.
In diesem Sinne kann man +x auch als kürzere Schreibweise für (0+x)
auffassen und da 0 plus irgendeine Zahl wieder die Zahl ergibt, ändert
sich da nichts am Ergebnis.
Hallo,
ich hoffe meine neue Skizze ist übersichlicher.
Situationsbeschreibung:
Aus sicht des µC:
Wenn ein Auto in Richtung 1 in die Schleife fährtund den Kontakt
überfährt wird die Richtung auf besetzt geschaltet. Wenn es die Schleife
wieder verläst und über den Kontakt fährt wird diese wieder auf Frei
gesetzt. Das gleiche gilt auch für die andere Richtung.
Wenn nun der Timer überläuft, wird überprüft ob die Schleife Frei ist
und wenn ja dann schaltet er die Weiche um.
Ich hoffe das erfüllt eure Wünsche. :)
Gruß Jannis