Hallo Zusammen
Ich habe gestern versucht einen Code zu Schreiben , und wollte heute
Messtechnisch prüfen ob das was ich Programmiert habe funktioniert,
leider kammen irgendwie merkwürdige Werte zustande.
Ich bin ein neuling in C und hab mir durch mehrere Tutorials diesen Code
zusammen gestellt, nur leider bin ich mir nicht sicher ob ich dort einen
Fehler hab , da für mich alles inordnung aussieht aber vielleicht sieht
ja jemand ob ich einen unbedachten fehler hinterlassen hab (kann mir
auch Tipps geben).
Es wird ein ATtiny45 verwendet , ich hänge ein bild für die Pin
belegungen an.
1
#define F_CPU 1000000UL // 1Mhz
2
#include<avr/io.h>
3
#include<util/delay.h>
4
5
6
7
intmain(void)
8
{
9
10
DDRB=0b011101;
11
PORTB=0b011101;
12
while(1)
13
{
14
if(!(PINB&(1<<PINB1)))// PB1 = Error Input
15
{
16
PORTB&=~((1<<PB2));// Set Error Output to "Low"
17
if(PINB&(1<<PINB5))// If Switch on then start "On" LED
18
{
19
PORTB|=(1<<PB4)|(1<<PB0);
20
}
21
else// If switch not on then start "Standby" LED
22
{
23
PORTB|=(1<<PB3);
24
}
25
return0;
26
}
27
else
28
{
29
PORTB&=~((1<<PB4)|(1<<PB3)|(1<<PB0));// Start "Error" LED and deactivate the LED ON/Standby Output
30
PORTB|=(1<<PB2);
31
_delay_ms(200);
32
PORTB&=~((1<<PB2));
33
_delay_ms(200);
34
PORTB|=(1<<PB2);
35
_delay_ms(200);
36
PORTB&=~((1<<PB2));
37
_delay_ms(200);
38
PORTB|=(1<<PB2);
39
_delay_ms(200);
40
PORTB&=~((1<<PB2));
41
_delay_ms(2000);
42
}
43
return0;
44
}
45
46
}
Vielen dank schonmal an die , die sich mit meinem Problem beschäftigen.
Gruß Sascha
return in main()
Dir ist aber schon klar, dass der Tiny dein Programm in 0 komma Nix
abgearbeitet hat und dann nur noch rumsteht und Däumchen dreht?
Ein µC Programm sieht so aus
1
intmain()
2
{
3
Initialisierungen
4
zumBeispielPortpinsaufInputoderOutputschalten
5
6
while(1){
7
8
LogikdesProgramms
9
10
}
11
}
d.h. der Prozessor ist im Endeffekt in einer Endlosschleife gefangen,
die er nie wieder verlässt, solange der Strom da ist. Auch nicht durch
einen return in irgend einem Fall.
Im übrigen.
Wenn du ein Neuling bist, dann sollte dein erstes Programm so aussehen
1
#define F_CPU 1000000UL
2
#include<avr/io.h>
3
#include<util/delay.h>
4
5
intmain()
6
{
7
DDRB=0xFF;// alles auf Output
8
9
while(1){
10
PORTB=0x00;
11
_delay_ms(1000);
12
13
PORTB=0xFF;
14
_delay_ms(1000);
15
}
16
}
das haust du mal in den Prozessor und siehst nach, ob du das Blinken an
den Portpins 'sehen' kannst.
Ein einfaches Programm ist deswegen wichtig, damit du mal deinen ganzen
Prozess durchtesten kannst. Compilieren, Linken, Hex-File erstellen,
Hex-File brennen, µC eigenständig laufen lassen.
Überall in dieser Kette gibt es potentielle Fehler. Das blödeste was du
tun kannst, ist mit einem komplizierten Programm sofort auf den µC los
zu gehen. Denn wenn dann nichts funktioniert hast du keine Ahnung, ob
das jetzt an deinem Programm oder an der Toolchain liegt. Ergo brauchst
du ein Programm, von dem du 100% sicher bist, dass es funktionieren
wird.
Und erst dann fängst du an, dein Programm komplexer zu machen. Wobei du
wieder nicht eine halbe Seite Code schreibst, sondern immer nur ein paar
Zeilen. Gerade soviel, dass du die neuen Zeilen testen kannst.
Karl Heinz schrieb:> int main()> {> Initialisierungen> zum Beispiel Portpins auf Input oder Output schalten>> while( 1 ) {>> Logik des Programms>> }> }
Hab ich das nicht so gemacht?
und was möchtest du mir mit " return in main() " sagen ? Das dies in der
Main untersagt ist ??
> Das dies in der Main untersagt ist ??
untersagt ist das falsche Wort.
Denn niemand kann dir etwas untersagen.
Der springende Punkt ist eben, dass der Prozessor nie wieder aus der
Hauptschleife entlassen wird. Nie. Auch nicht mit einem return.
Karl Heinz schrieb:>> int main()> {> DDRB = 0xFF; // alles auf Output>> while( 1 ) {> PORTB = 0x00;> _delay_ms( 1000 );>> PORTB = 0xFF;> _delay_ms( 1000 );> }> }>
Zeilen. Gerade soviel, dass du die neuen Zeilen testen kannst.
Vielen dank für dieses beispiel , du hast recht ich hab mich an was
gewagt wo mein wissen scheitert.
Ich wert es mal in kleinen Schritten Versuchen.
Karl Heinz schrieb:>> Das dies in der Main untersagt ist ??>> untersagt ist das falsche Wort.> Denn niemand kann dir etwas untersagen.>> Der springende Punkt ist eben, dass der Prozessor nie wieder aus der> Hauptschleife entlassen wird. Nie. Auch nicht mit einem return.
Dann heißt es , das die "return's" unnötig waren?
Sascha schrieb:> Dann heißt es , das die "return's" unnötig waren?
Nicht unnötig, hinderlich.
Denn das Programm hört an dieser Stelle auf, d.h. beim ersten Auftreten
eines return innerhalb von main wird main verlassen ... und nie
wieder aufgerufen (solange Du keinen Hardware-Reset auslöst bzw. den
Strom aus- und wiedereinschaltest).
Übrigens wird der Plural nicht durch Anhängen von Apostroph-s gebildet.
Nie.
Rufus Τ. Firefly schrieb:> Sascha schrieb:>> Dann heißt es , das die "return's" unnötig waren?>> Nicht unnötig, hinderlich.>> Denn das Programm hört an dieser Stelle auf, d.h. beim ersten Auftreten> eines return innerhalb von main wird main verlassen ... und nie> wieder aufgerufen (solange Du keinen Hardware-Reset auslöst bzw. den> Strom aus- und wiedereinschaltest).>> Übrigens wird der Plural nicht durch Anhängen von Apostroph-s gebildet.> Nie.
Achso jetzt versteh ich das, und ähm danke für den "Deutsch" Tipp :D
Karl Heinz schrieb:>> Das dies in der Main untersagt ist ??>> untersagt ist das falsche Wort.> Denn niemand kann dir etwas untersagen.>> Der springende Punkt ist eben, dass der Prozessor nie wieder aus der> Hauptschleife entlassen wird. Nie. Auch nicht mit einem return.
ich habe jetzt weiter experementiert , aber hänge immer wieder in der
Selben Zeile fest ...
1
#define F_CPU 1000000UL // 1Mhz
2
#include<avr/io.h>
3
#include<util/delay.h>
4
5
6
7
intmain()
8
{
9
DDRB=0b00000111;// Ab. 1.1
10
while(1)
11
{
12
13
14
if(!(PINB&(1<<PINB4)))// Ab. 1.2
15
{
16
17
PORTB|=(1<<PB0);// Start TEST
18
}
19
else// Ab. 1.3
20
{
21
PORTB|=(1<<PB1);
22
_delay_ms(500);
23
PORTB&=~(1<<PB1);
24
_delay_ms(500);
25
PORTB|=(1<<PB1);
26
_delay_ms(500);
27
PORTB&=~(1<<PB1);
28
_delay_ms(500);
29
PORTB|=(1<<PB1);
30
_delay_ms(500);
31
PORTB&=~(1<<PB1);
32
_delay_ms(500);
33
}
34
}
35
}
Bei der if Abfrage spring er sofort zu "Ab. 1.3" obwohl an diesem Pin
kein Signal Anliegt.
Ich habe mir sämtliche tutorials durchgelesen, aber ich finde keinen
fehler ...
Hoffe das jemand mir auf die sprünge helfen kann.
Fragst Du jetzt PINB5 (wie am Anfang) oder PINB4 (letzter Post) ab?
Bei PINB5 solltest Du beachten, dass dieser per Default als RESET-PIN
mit Pullup definiert (Fuses) ist:
• RESET: External Reset input is active low and enabled by unprogramming
(“1”) the RSTDISBL Fuse. Pullup is
activated and output driver and digital input are deactivated when the
pin is used as the RESET pin.
PINB4 würde aber nicht mit Deiner Anschlussbelegung zusammenpassen ...
da sollte ja wohl eine LED dranhängen - oder?
Dieter Frohnapfel schrieb:> Fragst Du jetzt PINB5 (wie am Anfang) oder PINB4 (letzter Post)> ab?>> Bei PINB5 solltest Du beachten, dass dieser per Default als RESET-PIN> mit Pullup definiert (Fuses) ist:>> • RESET: External Reset input is active low and enabled by unprogramming> (“1”) the RSTDISBL Fuse. Pullup is> activated and output driver and digital input are deactivated when the> pin is used as the RESET pin.>> PINB4 würde aber nicht mit Deiner Anschlussbelegung zusammenpassen ...> da sollte ja wohl eine LED dranhängen - oder?
Ich habe den RESET Pin erstmal weg gelassen , also am PINB4 würde in der
Praxis eine LED dran hängen aber mir würde erstmal reichen das dort eine
Spannung anliegt ( zum Messen )
Dieter Frohnapfel schrieb:> PINB4 würde aber nicht mit Deiner Anschlussbelegung zusammenpassen ...> da sollte ja wohl eine LED dranhängen - oder?
Warum soll am PIN PB4 eine definierte Spannung anliegen?
Der Pin ist auf Eingang geschaltet und solange du nichts tust, ist es
nicht vorhersehbar, ob der Pin als 0 oder als 1 gewertet wird.
Entweder du hast da drann eine Schaltung hängen, die eine Spannung
vorgibt, oder du aktivierst den internen Pullup WIderstand, der dafür
sorgt, dass ein offener Pin auch einen definierten Spannungspegel hat.
Und ja.
Das macht einen Unterschied: Ein Pin, an dem nichts hängt, hat nicht
automatisch den Pegel 0. Die Eingänge eines AVR sind hochohmig genug,
dass die Pins wie Antennen wirken, die sich jedes dahergelaufene
elektromagnetische Feld einfangen.
DDRB=(1<<LED);// Anschluss mit der LED als Ausgang
9
10
PORTB|=(1<<INPUT);// Pullup am Eingangspin
11
12
while(1)
13
{
14
if(!(PINB&(1<<INPUT))
15
PORTB|=(1<<LED);
16
else
17
PORTB&=~(1<<LED);
18
}
19
}
Häng dein Voltmeter an den Pin PB3
Wenn am PB4 nichts angeschlossen ist, dann zeigt es 0V.
Verbindest du PB4 (mit einem Draht oder drücken eines Tasters) mit GND,
dann wechselt PB3 auf 5V.
Karl Heinz schrieb:> Warum soll am PIN PB4 eine definierte Spannung anliegen?
Habe ich weder geschrieben noch gemeint - mich lediglich auf das
"Anschlussbild" im Ursprungs-Post bezogen.
Sascha schrieb:> Ich habe den RESET Pin erstmal weg gelassen
sehr vernünftig.
Den solltest du auch noch für lange Zeit 'erst mal weglassen'. Oder hast
du einen Hochvoltprogrammer?
N
Karl Heinz schrieb:> Dieter Frohnapfel schrieb:>>> PINB4 würde aber nicht mit Deiner Anschlussbelegung zusammenpassen ...>> da sollte ja wohl eine LED dranhängen - oder?>> Warum soll am PIN PB4 eine definierte Spannung anliegen?>> Der Pin ist auf Eingang geschaltet und solange du nichts tust, ist es> nicht vorhersehbar, ob der Pin als 0 oder als 1 gewertet wird.>> Entweder du hast da drann eine Schaltung hängen, die eine Spannung> vorgibt, oder du aktivierst den internen Pullup WIderstand, der dafür> sorgt, dass ein offener Pin auch einen definierten Spannungspegel hat.>> Und ja.> Das macht einen Unterschied: Ein Pin, an dem nichts hängt, hat nicht> automatisch den Pegel 0. Die Eingänge eines AVR sind hochohmig genug,> dass die Pins wie Antennen wirken, die sich jedes dahergelaufene> elektromagnetische Feld einfangen.
Oh nein entschuldigung an PINB4 würde ein Schalter mit einem Pull-Down
widerstand liegen , für die Activ High Methode.
An PB0 würde eine LED anliegen
Dieter Frohnapfel schrieb:> Karl Heinz schrieb:>> Warum soll am PIN PB4 eine definierte Spannung anliegen?>> Habe ich weder geschrieben noch gemeint - mich lediglich auf das> "Anschlussbild" im Ursprungs-Post bezogen.
Entschuldigung. Da hab ich das falsche Posting für die Antwort
herangezogen.
Ich wollte eigentlich den TO erreichen. Mein Bauchgefühl sagt mir
nämlich, dass er 'kein Signal' mit 'offener Pin' gleichsetzt.
Sascha schrieb:> Oh nein entschuldigung an PINB4 würde ein Schalter mit einem Pull-Down> widerstand liegen , für die Activ High Methode.Würde oder er liegt ?
Das macht einen Unterschied. Von würde stabilisiert sich dort nichts.
Anders ausgedrückt: Ein Konjunktiv interessiert nicht. Am allerwenigsten
den µC.
Karl Heinz schrieb:> Sascha schrieb:>>> Oh nein entschuldigung an PINB4 würde ein Schalter mit einem Pull-Down>> widerstand liegen , für die Activ High Methode.>> Würde oder er liegt ?>> Das macht einen Unterschied. Von würde stabilisiert sich dort nichts.
würde , hab mir gedacht das man erst den code haben sollte bevor man
sich die schlatung zusammen baut.
Also mit zusammen bauen meine ich Lötem etc. , eine schlatung selbst
habe ich.
Sascha schrieb:> Karl Heinz schrieb:>> Sascha schrieb:>>>>> Oh nein entschuldigung an PINB4 würde ein Schalter mit einem Pull-Down>>> widerstand liegen , für die Activ High Methode.>>>> Würde oder er liegt ?>>>> Das macht einen Unterschied. Von würde stabilisiert sich dort nichts.>> würde , hab mir gedacht das man erst den code haben sollte bevor man> sich die schlatung zusammen baut.
Nun. jetzt weisst du es besser.
Und das du dir mit deinem Bestehen auf 'Active High' auch keinen
Gefallen tust.
Bei Active High brauchst du einen externen Pulldown (und zwar von der
ersten Entwicklungssekunde an).
Bei Active Low hättest du den eingebauten Pullup nehmen können. Einfach
den Taster an den Portpin gegen GND verschalten, den internen Pullup
akrivieren, und gut ists.
Aber ich geb dir recht: das wär zu einfach.
gibts den
Karl Heinz schrieb:> Sascha schrieb:>> Karl Heinz schrieb:> Nun. jetzt weisst du es besser.>
Dann weiß ich schonmal für die Zukunft bescheid.
Karl Heinz schrieb:> Und das du dir mit deinem Bestehen auf 'Active High' auch keinen> Gefallen tust.>> Bei Active High brauchst du einen externen Pulldown (und zwar von der> ersten Entwicklungssekunde an).> Bei Active Low hättest du den eingebauten nehmen können. Einfach den> Taster an den Portpin gegen GND verschalten und gut ists.> Aber ich geb dir recht: das wär zu einfach.
Oh ja an den internen Pull-Up Widerstand habe ich gar nicht gedacht,
wäre es den trotzdem fals die Activ High methode anzuwenden oder wäre
diese viel komplizierter ? , im Tutorial sah die recht logisch aus .
Sascha schrieb:> hab mir gedacht das man erst den code haben sollte bevor man> sich die schlatung zusammen baut
Da muss man erst mal drauf kommen - Du arbeitest lediglich mit dem
Simulator im AVR-Studio - oder? Es gibt noch gar keine reale Schaltung!
Im AVR-Studio ist lustiger weise PINB4 per default auf high gesetzt ...
Dieter Frohnapfel schrieb:> Sascha schrieb:>> hab mir gedacht das man erst den code haben sollte bevor man>> sich die schlatung zusammen baut>> Da muss man erst mal drauf kommen - Du arbeitest lediglich mit dem> Simulator im AVR-Studio - oder?
Hahaha , das wäre schön ...
Ich kriege diesen Sch*** Simulator nicht zum laufen , wie es so schön
von Atmel in einem Video gezeigt wurde ...
Habe alles versucht aber nunja vielleicht liegt es an der Version
Sascha schrieb:> Oh ja an den internen Pull-Up Widerstand habe ich gar nicht gedacht,> wäre es den trotzdem fals die Activ High methode anzuwenden oder wäre> diese viel komplizierter ? , im Tutorial sah die recht logisch aus .
Das ist nur Gewöhnungssache, ob du im Programm eine Aktion auslöst, wenn
der Pin auf 1 oder auf 0 ist. Programmtechnisch spielt das keine große
Rolle. In C ist der Unterschied gerade mal ein '!'.
Hardwaremässig ist der UNterschied, dass du in dem einen Fall "Taster +
Widerstand" brauchst und im anderen Fall nur "Taster".
Es gibt natürlich Fälle, bei denen man den internen Pullup nicht nehmen
kann. Wenn die Leitung vom Taster zum µC beispielsweise recht lang ist
(wir reden da von Meter). Aber im Normalfall nimmt man einfach den
internen Pullup und ist geistig flexibel genug, dass es einen nicht
stört, dass der Ruhepegel einer Leitung eine 1 ist und bei 0 zu schalten
ist. Das ist etwas, was man im Programm ganz simpel ausgleichen kann.
Karl Heinz schrieb:>> Das ist nur Gewöhnungssache, ob du im Programm eine Aktion auslöst, wenn> der Pin auf 1 oder auf 0 ist. Programmtechnisch spielt das keine große> Rolle. In C ist der Unterschied gerade mal ein '!'.>> Hardwaremässig ist der UNterschied, dass du in dem einen Fall "Taster +> Widerstand" brauchst und im anderen Fall nur "Taster".>> Es gibt natürlich Fälle, bei denen man den internen Pullup nicht nehmen> kann. Wenn die Leitung vom Taster zum µC beispielsweise recht lang ist> (wir reden da von Meter). Aber im Normalfall nimmt man einfach den> internen Pullup und ist geistig flexibel genug, dass es einen nicht> stört, dass der Ruhepegel einer Leitung eine 1 ist und bei 0 zu schalten> ist. Das ist etwas, was man im Programm ganz simpel ausgleichen kann.
Aso Danke , ja hast schon recht . Laut meinem Code wäre die Active High
die richtige Methode aber es würde nur 2 Sekunden dauern um diesen auf
für die Active Low Methode Kompatibel zu machen.
Hast du denn jetzt das kurze Testprogramm schon mal in den µC gebrannt?
Damit man mal weiss, ob deine ganze Toolchain inklusive Brennen in den
µC überhaupt funktioniert?
Sascha schrieb:> Aso Danke , ja hast schon recht . Laut meinem Code wäre die Active High> die richtige Methode
Wenn du einen Schalter hast, dann gibt es kein richtig oder falsch.
Du nimmst das, was dir sympatischer ist und/oder was einfacher ist.
Anders sieht es aus, wenn dir von ausserhalb eine Spannung aufs Auge
gedrückt wird. Dann kannst du es dir nicht mehr aussuchen.
Der wichtige Punkt lautet:
ein offener Pin am AVR ist nicht automatisch 0 (und er ist auch nicht
automatisch 1). Du brauchst einen Pullup oder Pulldown Widerstand.
Pullup hast du im AVR eingebaut. Pulldown musst du selbst drann löten.
Karl Heinz schrieb:> Hast du denn jetzt das kurze Testprogramm schon mal in den µC> gebrannt?> Damit man mal weiss, ob deine ganze Toolchain inklusive Brennen in den> µC überhaupt funktioniert?
Ich benutzte Atmel Studio 6.2 nur zum Programmieren zum Brennen benutzte
ich myAVR ProgTool V1.39 und damit funktioniert es.
Sascha schrieb:> Karl Heinz schrieb:>> Hast du denn jetzt das kurze Testprogramm schon mal in den µC>> gebrannt?>> Damit man mal weiss, ob deine ganze Toolchain inklusive Brennen in den>> µC überhaupt funktioniert?>> Ich benutzte Atmel Studio 6.2 nur zum Programmieren zum Brennen benutzte> ich myAVR ProgTool V1.39 und damit funktioniert es.
Also an an deinem Test Programm liegt am PB3 5V an
1
#include<avr/io.h>
2
3
#define LED PB3
4
#define INPUT PB4
5
6
intmain(void)
7
{
8
DDRB=(1<<LED);// Anschluss mit der LED als Ausgang
npn schrieb:> Sascha schrieb:>> Also an an deinem Test Programm liegt am PB3 5V an>> Aber nicht immer. Es hängt von PB4 (INPUT) ab, was an PB3 (LED) anliegt.
Ja natürlich an in meinem fall liegen dort jetzt 5V an , wobei es ja
auch so sein soll.
Input ist 0 , und deswegen ist LED = 1
Sascha schrieb:> npn schrieb:>> Sascha schrieb:>>> Also an an deinem Test Programm liegt am PB3 5V an>>>> Aber nicht immer. Es hängt von PB4 (INPUT) ab, was an PB3 (LED) anliegt.>> Ja natürlich an in meinem fall liegen dort jetzt 5V an , wobei es ja> auch so sein soll.> Input ist 0 , und deswegen ist LED = 1
Und ändert sich denn PB3, wenn du PB4 umschaltest?
npn schrieb:> Sascha schrieb:>> npn schrieb:>>> Sascha schrieb:>>>> Also an an deinem Test Programm liegt am PB3 5V an>>>>>> Aber nicht immer. Es hängt von PB4 (INPUT) ab, was an PB3 (LED) anliegt.>>>> Ja natürlich an in meinem fall liegen dort jetzt 5V an , wobei es ja>> auch so sein soll.>> Input ist 0 , und deswegen ist LED = 1>> Und ändert sich denn PB3, wenn du PB4 umschaltest?
Ja wenn am Input was Anliegt wird , LED (PB3) Abgeschaltet ( auf 0
gesetzt)
Karl Heinz schrieb:> Sascha schrieb:>>> Aso Danke , ja hast schon recht . Laut meinem Code wäre die Active High>> die richtige Methode>> Wenn du einen Schalter hast, dann gibt es kein richtig oder falsch.> Du nimmst das, was dir sympatischer ist und/oder was einfacher ist.> Anders sieht es aus, wenn dir von ausserhalb eine Spannung aufs Auge> gedrückt wird. Dann kannst du es dir nicht mehr aussuchen.>> Der wichtige Punkt lautet:> ein offener Pin am AVR ist nicht automatisch 0 (und er ist auch nicht> automatisch 1). Du brauchst einen Pullup oder Pulldown Widerstand.> Pullup hast du im AVR eingebaut. Pulldown musst du selbst drann löten.
Ich hab es jetzt gelösst , habe mir dein Test Programm als stütze
genommen.