Hallo zusammen,
ich hoffe Ihr könnt mit weiterhelfen. Ich bin grad erst dabei mich in
die Microcontrollerprogrammierung einzuarbeiten und habe mir deshalb mal
das Lernpaket von Franzl besorgt. Ist ja auch soweit ganz schön, nur
steht da recht wenig über C drin. Da ich aber C schonmal in der Schule
hatte möchte ich auch dabei bleiben und nicht auf Assembler umswitchen.
Nun zu meinem ersten Problem:
Die Ports 0,1,2 sollen Eingänge (mit eingeschalteten Pull-up
Widerständen) und 4,5 Ausgänge sein. Bei anliegender Masse an Port 0
soll nun eine LED an Port 3 zum leuchten gebracht werden. Aus dem
GCC-Tutorial habe ich mir dafür folgende Befehle hereuasgesucht, aber
die LED bleibt bisher dunkel.
#include <avr/io.h>
void main (void) {
PORTB = ((0<<PB4) |(0<<PB3) |(1<<PB2) |(1<<PB1) |(1<<PB0));
DDRB = ((1<<DDB4)|(1<<DDB3)|(0<<DDB2)|(0<<DDB1)|(0<<DDB0));
while (1) {
if ( !(PINB & (1<<PINB0))) {
PORTB |= (1<<PB3);
}
} return 1;
}
Weiß irgendwer was ich falsch gemacht habe? Ich habe schon stundenlang
alles mögliche ausprobiert :-S
Vielen Dank schonmal!!!
P.S. Ist die obligatorische Endlosschleife, um das fehlende
Betriebssystem zu kompensieren so in Ordnung (while (1) { ... } return
1;)?
Da stimmt was nicht:
> Die Ports 0,1,2 sollen Eingänge (mit eingeschalteten Pull-up> Widerständen) und 4,5 Ausgänge sein. Bei anliegender Masse an Port 0
^^^^^^^^^^^^
> soll nun eine LED an Port 3 zum leuchten gebracht werden. Aus dem
^^^^^^
Hallo Stefan,
nein natürlich will ich das eigentlich nicht. Mir geht es momentan nur
darum mal dahinterzusteigen ob wie ich einzelne Ports ein- und
ausschalten kann.
Das Programm hier soll ja nur ein erster Test sein. Danach geht's dann
ans verkomplizieren der Bedingungung, aber ich dachte mir das ich das
ganze lieber Stück für Stück aufbaue, weil ich halt noch blutiger
Anfänger bin.
Köntest du mir bitte sagen wo genau ich den oder die Fehler gemacht
habe?
Christian schrieb:
> Köntest du mir bitte sagen wo genau ich den oder die Fehler gemacht> habe?
Den von meinem Namensvetter angekreideten Fehler hast du nirgendwo
gemacht. Das ist nämlich nur ein sprachlicher Fehler, der sich im Code
nicht widerspiegelt.
Erst mal was grundlegendes: welcher AVR?
Das Programm passt ja nicht zur Beschreibung. Vielleicht passt auch die
Schaltung nicht zum Programm?
Das Programm könnte funktionieren, wenn eine LED korrekt an Pin 3 von
PORTB angeschlossen ist.
Korrekt heisst hier active-high Beschaltung (s. AVR-GCC-Tutorial
Abschnitt IO) mit richtiger Polung der LED und richtigem Wert für den
Vorwiderstand (s.
http://www.mikrocontroller.net/articles/LED#Vorwiderstand)
Vorwiderstand LED
PB3 )-------####---- -------->|-----( GND
Oh da hab ich mich wohl vertippt. Sind natürlich die Ausgänge 3 und 4
gemeint. Der Quellcode ist aber richtig und passt somit auch.
Der MC ist ein ATtiny13, programmiert mit AVR Studio 4. Richtig
angeschlossen ist die LED auch
Christian schrieb:
> Der MC ist ein ATtiny13, programmiert mit AVR Studio 4. Richtig> angeschlossen ist die LED auch
Nur um sicher zu gehen
* wie hast du festgestellt, dass die Programmierung geklappt hat?
* wie hast du festgestellt, dass die LED richtig rum drinnen ist?
Weil wenn ich das Programm so laufen lasse (LED manuell & dauerhaft
eingeschaltet), die LED leutet:
#include <avr/io.h>
void main (void) {
PORTB = ((0<<PB4) |(1<<PB3) |(1<<PB2) |(1<<PB1) |(1<<PB0));
DDRB = ((1<<DDB4)|(1<<DDB3)|(0<<DDB2)|(0<<DDB1)|(0<<DDB0));
while (1) {
} return 1;
}
Erst wenn ich die If-Bedingung ins Spiel Bringe und die LED erst nach
dem Kontakt von PB0 und GND anfangen dürfte zu leuchten, tritt das
Problem auf (die LED bleibt aus):
#include <avr/io.h>
void main (void) {
PORTB = ((0<<PB4) |(0<<PB3) |(1<<PB2) |(1<<PB1) |(1<<PB0));
DDRB = ((1<<DDB4)|(1<<DDB3)|(0<<DDB2)|(0<<DDB1)|(0<<DDB0));
while (1) {
if ( !(PINB & (1<<PINB0))) {
PORTB |= (1<<PB3);
}
} return 1;
}
P.S.: Ja ich benutze die Franzis-Platine
Moment, es lag noch ein Wckelkontakt vor!
Die LED leuchtet zwar in auch in der zweiten Version des Programms (mit
der If-Schleife).
Allerdings auch ohne vorher PB0 an GND zu legen.
Logischer Hintergrund:
PB0 soll an Masse liegen --> der Wert von PINB0 muss = 0 sein
-->
/* Fuehre Aktion aus, wenn Bit Nr. 0 (das "nullte" Bit) in PINB
geloescht (0) ist */
if ( !(PINB & (1<<PINB0)) ) {
/* Aktion */
}
...
Der Fehler muß also in der Wenn-Bedingung ( !(PINB & (1<<PINB0)) ) { ...
} liegen. Diese habe ich jedoch 1:1 aus dem GCC-Tutorial übernommen.
Versorgst du die Platine über den RS232 Port deines PCs oder über eine
Batterie an RTS (+ Pol) und GND (- Pol)?
Wenn über den RS232 Port deines PCs:
Wenn DTR ausgeschaltet ist, können bis zu -12V dort auf der Leitung
sein. -12V zerren über den 100K Widerstand den logischen Pegel an dem
PB0 auch ganz gut in Richtung LOW. Es ist die Frage, ob der interne
Pullup an PB0 dann genug Strom nachliefern kann. Noch besser wäre es,
wenn du ein Multimeter hast und die Spannung auf DTR gegen GND messen
kannst.
Vergiss nicht:
Wenn in deinem Programm die LED einmal angeschaltet wurde, dann bleibt
die bei deinem if-Anweisungsblock an.
Spekulation: Das einmalige Umschalten könnte beim Übergang
ISP-Programmierung zur Stromversorgung der Platine über RS232 geschehen,
wenn die RS232 vom PC aus uminitialisiert wird.
Ich würde auf jeden Fall den else-Anweisungsblock ergänzen, der die LED
ggf. auch abschaltet.
Ja die Stromversorgung läuft über rs232, abe aber kein Multimeter zur
Hand.
Habe die else Aweisung entsprechend ergänzt (s.o.).
Ergebnis:
Die LED leuchtet nach wie vor von Beginn an.
Unterschied zu Vorher:
Lege ich VCC auf PB0 geht sie aus (GND an Masse ändert nichts).
Ist ja schonmal ein Fortschritt. Ich kann jetzt die LED schonmal über
PB0 beeinflussen. Zwar nicht so wie ich es will aber immerhin :)
Aber wie kann das sein? Stimmen die Befehle im Tutorium etwa nicht?
Wie schaffe ich es jetzt das die Lampe erst bei PB0 gegen GND angeht?
Hänge die HEX-Datei mal an. Ich möchte das gerne im AVR Studio Simulator
sehen.
Wenn du einen Digifotoknips hast: Mache mal ein Bild von deiner
Schaltung so wie du das Programm laufen lässt. Bildformate beachten.
> Lege ich VCC auf PB0 geht sie aus
Vorsicht bei solchen Versuchen. Du musst 110% sicher sein, dass der Pin
auf Eingang steht. Wenn nicht, röstest du u.U. den Pin genauer die
Schutzdiode(n) intern. Bei solchen Versuchen (Logikpegel an Pin legen)
besser Vcc mittels Pull-up-Widerstand zur Strombegrenzung abgreifen.
Pull-up-
widerstand
ca. 10K
Pin )------####----- ( Vcc
Die LED könnte ausgehen, weil der Attiny13 in den RESET Zustand fällt.
Der AVR wird in den RESET Zustand fallen, wenn seine Versorgungsspannugn
einbricht. Die Versorgungsspannung kann einbrechen, wenn du eine
Schaltung mit zu hoher Stromaufnahme produziert hast - im Extremfall
durch einen Kruzschluss. Die Stromversorgung aus der RS232 ist nicht
soooo belastbar (paar mA) und wenn zu viel entnommen wird, sackt Vcc ab.
> GND an Masse ändert nichts.
GND an was?
> Stimmen die Befehle im Tutorium etwa nicht?
Das Tutorial hier im Wiki?
Das ist nicht für das Franzis-Lernpaket bzw. dessen Hardware
geschrieben.
Wenn du also das Tutorial wortwörtlich übernimmst, kommt ein Programm
für eine andere Hardware raus. Das auf deiner Hardware funktioniert
nicht.
Man muss also Änderungen machen. Die Änderungen betreffen u.U. den
Anschluss der Hardware (Widerstand, LED, Taster), das Kompilieren des
Programms (Einstellungen) und das Flashen des Programms.
Die Änderungen sind im Prinzip nicht schwer. Aber eine Unsicherheit bei
mir ist die Beeinflussung der Schaltung durch die RS232-Verbindung zum
PC. Ich kenne das Handbuch des Franzis-Lernpakets nicht.
Keiner der vier Punkte ist bisher 100% sicher abgeklärt.
Daher meine Frage nach dem Foto (Hardware), dem Hexfile (Programm).
Offen ist noch, ob das Programm tatsächlich im Attiny13 ist. Ich vermute
nicht, denn die LED leuchtet, wie du schreibst, egal ob zu Beginn PB3
auf LOW oder HIGH initialisiert wird! Wenn du den Attiny13 AUSLESEN
kannst, hänge das ausgelesene HEXfile an.
Alles klar dann lass ich das mal lieber mit dem VCC :-S
Ich meinte natürlich GND an PB0 ändert nix.
Im Franzis-Handbuch steht nur wenig über C sondern das meißte in
Assembler.
Was drin steht ist aber, das ein geöffneter Schalter den Wert Null ins
PINB-Register übergibt.
Daraufhin hab habe ich folgenden Befehl aus dem Tutorial herausgesucht
um Port 3 einzuschalten wenn Port 0 an GND liegt:
--> if ( PINB & (1<<PINB0) ) { PORTB |= (1<<PB3); }
Ich denke schon das das Programm wirklich auf den ATtiny13 geschrieben
wird, da wenn ich innerhalb der if-Bedingung den Teil zum einschalten
des PB3 weglasse, die LED nicht an geht.
if ( PINB & (1<<PINB0) ) { /* PORTB |= (1<<PB3); */ }
Das Bild ist gemäß Bildformate viel zu groß für den Inhalt. Es geht
kleiner siehe Anhang.
Dein HEXfile sieht im Simulator OK aus. Jetzt die Frage: Ist das auch im
Attiny13 drin?
Das kann man beantworten, wenn man ein Programm einspielt, welches
mehrere Aktionen macht. Z.B. das Blinkprogramm im Anhang. Ich habe die
Source und das HEXfile hochgeladen.
Bei richtiger Funktion sollte die LED mehrmals blinken und dann erst auf
den Taster reagieren.
Das Blinken zeigt: PB3 funktioniert grundsätzlich als Ausgabepin und das
Flashen funktioniert.
Bei deiner Schaltung wäre der Taster eine Drahtbrücke zwischen PB0 und
GND, die entweder gesteckt (LED an) oder nicht gesteckt (LED aus) ist.
> Aber eine Unsicherheit bei> mir ist die Beeinflussung der Schaltung durch die RS232-Verbindung zum> PC. Ich kenne das Handbuch des Franzis-Lernpakets nicht.
In der Online-Beschreibung des Franzis-Lernpaketes steht:
"Außerdem kann die Verbindung zwischen PC und Controller auch statisch
genutzt werden. Zwei Leitungen dienen dann als Eingänge des
Mikrocontrollers. Der PC legt 1- oder 0-Zustände an, die ein
Controllerprogramm über die Anschlüsse PB0 und PB2 lesen kann."
http://www.elo-web.de/elo/mikrocontroller-und-programmierung/avr-grundlagen/experimente-mit-dem-attiny13
Du solltest im Handbuch nachsehen, wie man den PC dazu bringt, an PB1
den 1 Zustand anzulegen. Wenn du das nicht findest, ist es einen Versuch
Wert, statt PB0 mit seinem Pull-Up einen anderen Pin mit seinem Pull-Up
zu benutzen, der nicht vom PC aus kontrolliert wird: Vorschlag PB4.
Hab den Schalter einfach auf PB4 gelegt und es hat endlich geklappt!
Dann das Ganze nochmal auf PB0 jedoch nicht mit RS232 sondern mit
externer Stromversorgung & es klappt auch!
Endlich...
... und ich war schon fast am verweifeln. Das mir der RS232 da einen
Strich durch die Rechnung gemacht hat hätt ich nie gedacht.
DANKE DANKE DANKE Stefan B. 1000 Dank für den SUPER - TIP !!!
Kannst du mir vielleicht noch verraten wie genau du den hex-file
getestet hast? Gibt es bei Studio 4 oder anderswo, eine Option die
Schaltung nachzustellen und dann verschiedene MC zu simulieren?
Das würde mir auf jeden Fall weiterhelfen weil ich den ATtiny bestimmt
jetzt schon 100 mal beschreiben mußte um verschiedene Programmänderungen
zu testen.
Geht das so weiter kann ich ihn bald weg schmeißen.
Christian schrieb:
> Geht das so weiter kann ich ihn bald weg schmeißen.
Mach Dir keine Sorgen, mindestens 10.000 mal Proggen ist doch
garantiert.
Peter
Klasse, dass du weiter gekommen bist!
Leider kann man im nackten AVR Studio nur auf Registerebene debuggen
und simulieren aber keine Schaltungen eingeben. Man muss also wissen,
welche Signale in welchen Registern was in der Schaltung bewirken und
umgekehrt.
Auch deswegen ist es enorm wichtig, bei der Ferndiagnose und beim
Ferndebuggen die Schaltung leicht zugreifbar zu haben. Leider
unterschätzen viele Fragesteller diesen Punkt.
Im Artikel AVR-Simulation sind weitere Simulationstools genannt.
Persönlich habe ich keine Erfahrung damit.