PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Input abfragen mit dem Attiny12



niklas90
13.12.2008, 21:25
Hallo,
Das Thema Microcontroller hat mich fasziniert, vor allem weil ich mich schon lange mit Elektronik beschäftige. Also habe ich mir ein paar Attiny12 bestellt, die entsprechende Software geladen und ein ISP-Dongle gelötet. Mit Wavrasm erstell ich mir den Assemblerquelltext und mit PonyProg2000 programmier ich den Chip. Das funktioniert auch wunderbar; habe mir zum Anfang ein kleines Lauflicht geschrieben. Nun wollte ich aber eine Tastenabfrage realisieren, jedoch komme ich da nicht weiter. Ich habe da ein generelles Problem in dem Zusammenhang entdeckt: Diese Befehle um Bits in Registern oder Ports zu vergleichen funktionieren scheinbar nicht, zumindest passiert da immer nichts. Also z.B. SBRC, SBIS, SBI. Wahrscheinlich benutze ich sie aber nur falsch.
Jedenfalls, mein erster Ansatz für die Abfrage wäre die (Die LED zum Anzeigen sitz auf Pin5 (PB0) und ich die Abfrage soll auf Pin6 (PB1) geschehen):

.include "C:\avrtools\appnotes\8515def.inc"

.def Temp = R19
.org 0
rjmp RESET

RESET:
ldi Temp, 1
out DDRB, Temp
CBI PORTB, 1

Main:
SBIC PINB, 2
SBI PORTB, 1
rjmp Main

Ich dachte halt, dass man die Bits direkt abfragen kann, bzw. ausgeben. Naja, bei meinen ersten Versuchen habe ich das aber auch nicht gemacht, mich wundert bloß, wie das funktioniere soll mit den Bits. dann habe ich noch ein "realistischeres" Programm geschrieben, das auch ganz gut geht, nur muss man extern einen Widerstand an den Eingabe-Pin nach Plus setzen. (Wie setzt man die internen???)

.include "C:\avrtools\appnotes\8515def.inc"

.def Rein = R20
.def Temp = R19
.org 0
rjmp RESET

RESET:
ldi Temp, 1
out DDRB, Temp
ldi R21, 2

Main:
ldi Temp, 1
IN Rein, PINB
CPSE Rein, R21
ldi Temp, 0
out PORTB, Temp
rjmp Main


Eigentlich wollte ich ja vermeiden mit Assembler zu programmieren, da ich schon ein paar Hochsprachen kann, aber weder Bascom noch WinAVR haben bei mir funktioniert. Bascom wollte nix compilieren, egal was ich geschrieben hab - außerdem hat der Attiny12 keinen Ram - und WinAVR hat nie das gemacht was es sollte, obwohl ich alles zu 100% nach den Anleitungen im Netz gemacht habe. Außerdem war mir die Sache mit dem Makefile zu stressig.
Wie dem auch sei, ich würde gerne wissen wie man solch eine Eingabe besser macht, also ohne widerstand und wie das mit den Bits funktioniert, ich hoffe ihr könnt mir helfen.

BTW: wieso schreiben alle immer die Zahlen in Hexadezimal- oder Binärform?? (0x02, 0b00000020, statt einfach 2 ;-)) der Compiler macht doch eh alles zu hex. Ich habe den Test gemacht: kein Unterschied!

Besserwessi
14.12.2008, 00:27
Ohne RAM werden weder BASCOM noch WINAVR weiterhelfen. Da geht wohl nur ASM.
Das mit den Zahlen als Hexadezimal oder Binär wird gemacht, weil man da besser die zuordnung zu den einzelenen Bits erkennen kann. Gelegentlich wird auch noch octal benutzt. Man muss sich etwas dran gewöhnen, aber irgendwann kann man dann sogar Heaxadezimalzahlen im Kopf addieren. Bei mir geht es meistens ziehmlich durcheinander. Da kann schon mal (0x80 + 5)stehen.

Edit:
So und jetzt zum eigentlichen Problem:
Soweit ich das sehe liest das erste Programme den Port richtig ein und reagieren auch darauf. Allerdings ist die Reaktion nur in die eine Richtung. Denn es wird nur der Ausgabewert in die eine Richtung verändert. Die erste Version läßt sich recht schwer verbessern. Die 2 te Version sollte eigentlich gehen.

Also Hilfe ist der Simulator in AVR studio ganz sinnvoll.


Die internen Pullups setzt man durch schreiben einen 1 in PORTB, wenn der Pin ein Eingang ist.

niklas90
14.12.2008, 16:15
Danke erst mal,
Also mit dem ersten Programm wollte ich eigentlich nur mein Problem mit den Bits setzen oder lesen verdeutlichen. Es funktioniert nicht. Was ich mir DACHTE: mit dem Befehl SBI PORTB, 1 schaltet der Chip direkt den PB0 an, also die LED leuchtet, aber in WIRKLICHKEIT passiert nix. Kann man also Ports nur mit Hilfe von Registern schalten? also:
ldi Temp, 1
out PORTB, Temp

Denn ich verstehe absolut nicht, was SBI macht. Mit SBIC (also die Abfrage) verhält es sich analog.

Dann verstehe ich nicht, wieso man einen externen Widerstand benutzen muss, gibt es nicht die Möglichkeit interne Widerstände zu schalten, z.B. mit
ldi Temp, 2
out PORTB, Temp
für mein Beispiel (also bei ist ja die Abfrage auf PB1)? Ich hab's ausprobiert, es geht nicht.

Also, ich glaube mit dem Attiny12 habe ich mir wohl den blödesten AVR geholt, den ATMEL anbietet https://www.roboternetz.de/phpBB2/images/smiles/eusa_doh.gif

Besserwessi
14.12.2008, 17:44
Der Tiny12 ist einer der Leistungsschwächsten AVRs. Als Anfang für die Programmierung sollte man eher so etwas wie einen Mega48 oder Mega8 nehmen. Da kann man ohne Probleme in Basic oder C programmieren und hat auch Funktionen wie AD Wandler und UART mit drin. Der ASM Code ist aber den den Controllern fast gleich, bis auf ein paar Befehle, die nur die größeren haben. Der tiny12 braucht ja nicht mal einen Zugriff aufs RAM.

Der SBI befehl setzt schon das entsprechende Bit. Es wird aber das Bit nicht wieder zurückgenommen, wenn SBI nicht ausgeführt wird. Der Befehl SBI PortB,1 entspricht einem:
in temp,PortB
ori temp, (1<<1) ; ( (1<<1) = 2^1 = 2)
out PortB,temp
nur als ein Befehl und ohne ein temp register zu brauchen.

Der SBIC Befehl ist ein ganz spezieller bedingter Sprung. Die Erklärungen in der Hilfe von AVRstudio sind für die Befehle meistens recht gut. Für den Anfang fand ich die Sprünge BREQ und BRNE einfacher.

bax
14.12.2008, 17:44
SBI verhält sich anders als SBR!!

Mit SBI wird immer nur ein einzelnes Bit gesetzt, Adressierung ist also 0...7. Mit SBI PORTB, 1 hast Du also PB1 geschaltet, nicht PB0.

Das mit den internen pullups funktioniert schon. Du mußt allerdings drauf achten, das Du bei Ausgaben in der Art out PORTB, Temp immer alle 8bit beschreibst, da in Deinem Programm in der Schleife Temp mit 0 oder 1 geladen wird überschreibst Du das vorher gesetzte Bit 1 im PortD.

Zu guter letzt: beim einlesen von PINB isteine Maskierung des Einganges sinnvoll. Also ANDI Temp, 0x02. Auch die von Dir als Ausgang eingeschalteten Pins werden nämlich als "1" im PIND zurückgelesen.

Rajko

niklas90
15.12.2008, 14:06
Ah, danke. Das bringt mir etwas Licht ins Dunkel. Ich habe gestern noch eine funktionierende Zählschleife mit dem SBRS hingekriegt. (Die Schleife wird soundso oft abgespielt) Schade das es keinen fertigen Befehl dafür gibt, das ein Codefragment eine bestimmte Anzahl wiederholt wird. (Ja, ich habe schon Unterprogramme mit RCALL gemacht, aber wenn ich das 100 mal abspielen will, möchte ich das nicht 100 mal reinschreiben.) Ich werde mich mal hinsetzen und mit dem SBI rumexperimentieren, damit ich nicht für so banale Sachen wie einen Ausgang zu schalten ein ganzes Register verschwenden muss.

jetzt fällt es mir auch auf: Port0 ist ja nicht Bit 1 sondern 0, ich komme damit dauernd durcheinander ;-)

Besserwessi
15.12.2008, 18:32
Feste Schleifen, um etwas z.B. 100 mal zu durchlaufen, macht man am besten mit DEC und BRNE. Das sind dann nur 3 Befehle wenn man unter durchläufen 256 bleibt.