Forum: Mikrocontroller und Digitale Elektronik Eingangsport auslesen und in den Ausgang(port) schreiben


von Gerhard H. (oderlachs)


Lesenswert?

Hallo Freunde !
Wieder mal komme ich als Anfänger nicht weiter. Ich möchte gerne einen 
Port"D" bitweise auslesen und die pegel an den Port"B" als Ausgang 
schreiben, in einer Schleife und bekomme es einfach nicht hin weder in 
Bascom noch Assembler...
Ich habe versucht :

.....
...
config PortD = input
config PortB = output
dim P as bit

do
P = PortD.0
PortB.0 =P
....
....
P= PortD.7
PortB.7 = P
loop

end

-----------------------------------------

in ASSR:
------------

.include "m8515def.inc"      ; Definitionsdatei für den Prozessortyp

         ldi r16, 0xFF       ; lade Arbeitsregister r16 mit der 
Konstanten 0xFF
         out DDRB, r16       ; Inhalt von r16 ins IO-Register DDRB 
ausgeben

         ldi r16, 0b11111111 ; 0b11111111 in r16 laden
         out PORTB, r16      ; r16 ins IO-Register PORTB ausgeben

abfrage:    ldi r17, PORTD

      out PORTB, r17


    rjmp abfrage           ; Sprung zur Marke "abfrage" -> 
Endlosschleife

-----------------------------------------

es kann ja sein das meine Gedankengänge grundlegende Fehler haben, wie 
gesagt bin ja noch im Lernen..

Am Port D ist  jeder Pin eingangsmässig low-aktiv, d.h. bei Auslösung 
einer Schaltaktion wird der Pegel von Hi nach Low gezogen. Dann soll der 
entsprechende Pin im B-Port ebenfalls nach Low gehen.
Damit will ich erst mal die Funktion erreichen, später kommen noch 
programmierte Bedingungen dazu wie sich das mit Eingan -Low- und Ausgang 
-Hi- verhält, es soll ein Kontrollbaustein werden, der 8 Eingänge 
überwacht und diese dann Programmbedingt auf den Port B signalisiert..
Als Chip soll der 8515 erst mal in Betracht kommen, aber es geht mir ja 
erst mal darum die Funktion der Ports so zu erreichen wie oben erwähnt.

Gruss und Dank

Gerhard

von Adi (Gast)


Lesenswert?

Du willst nicht den Port lesen, sondern den Pin
Auszug aus Bascom

reading the PORT, will read the latch, that is the value
you have written to the PORT.
This is not the same as reading the logical values on the pins!
When you want to know the logical state of the attached hardware,
you MUST use the PIN register.

von Vivil (Gast)


Lesenswert?

Auch Dir kann ich nur sagen. Schreibe hinter jeden Befehl was du dir da 
gedacht hast. So wirst du Merken das Du gar nicht soviel dabei denkst.
1
         ldi r16, 0xFF       ; lade Arbeitsregister r16 mit der Konstanten 0xFF
2
         out DDRB, r16       ; Inhalt von r16 ins IO-Register DDRB ausgeben
3
4
         ldi r16, 0b11111111 ; 0b11111111 in r16 laden
5
         out PORTB, r16      ; r16 ins IO-Register PORTB ausgeben

Nicht beschreiben was der Befehl macht sondern warum Du ihn machst.

So wird Dir z.B. auffallen das du r16 nicht mit 0b11111111 laden musst 
da du ihn ja vorab mit 0xFF geladen hast und er sich seitdem nicht 
geändert hat.

Nein das ist nicht dein Fehler aber Zeigt auf das Du nicht mitdenkst bei 
dem was Du machst.

Also fein hinter jedem Befehl schreiben warum du das machst was du damit 
bezwecken möchtest. Und schwups die Wups wird Dir geholfen :-)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

1
      ldi r16, 0xFF       ; lade Arbeitsregister r16 mit der Konstanten 0xFF
2
      ldi r16, 0b11111111 ; 0b11111111 in r16 laden
Das sind überhaupt die allerblödsten Kommentare, den es je geben kann.
Denn morgen nehme ich diese Zeile, kopiere sie und passe sie an:
1
      ldi r16, 0xFE       ; lade Arbeitsregister r16 mit der Konstanten 0xFF
Und vergesse dabei den Kommentar...

Vivil schrieb:
> Auch Dir kann ich nur sagen. Schreibe hinter jeden Befehl was du dir da
> gedacht hast.
> So wird Dir z.B. auffallen...
Das Dahinterschreiben hilft da überhaupt nichts, man muß Sehen und 
Erkennen was man da tut, und da hilft nur Übung...

von Vivil (Gast)


Lesenswert?

Für ein Anfänger hilft es sehr viel weil er merkt das er da nicht denkt. 
Seine Gedanken zu Selektieren, Sortieren ist das a und o.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Vivil schrieb:
> Für ein Anfänger hilft es sehr viel weil er merkt das er da nicht denkt.
Nein, denn die Pattern-Erkennung bei einem Anfänger funktioniert noch 
nicht so gut, dass er automatisch erkennt FF == 11111111

von Vivil (Gast)


Lesenswert?

Wenn er hinter seinen befehl schreibt warum er das macht was er sich 
dabei denkt wird ihm auffallen das es zwei die gleichen gedankengänge 
sind.

lass sie doch mal überlegen. und da der E da schon nicht mit anfängt 
mitzuarbeiten warum sollten ihm dan user aus dem forum alles vorkauen?

von Dietmar (Gast)


Lesenswert?

Vivil schrieb:
> Für ein Anfänger hilft es sehr viel weil er merkt das er da nicht denkt.
> Seine Gedanken zu Selektieren, Sortieren ist das a und o.

Das ist im Prinzip ja auch nicht falsch. Nur in dem Kommentar sollte 
nicht die Erklärung des Befehls stehen. Sondern zusatzliche 
Informationen, die nicht direkt aus dem lesen des Quelltextes 
ersichtlich sind.

z.B. so:
  /////////////////////////////////////////////////////////
  // Timer 2 konfigurieren, wird für das multiplexen der LEDS benötigt
  // alle 0,1 ms wird ein CompareMatch-Interrupt ausgeloest

  TCCR2  = (1<<CS01);   // Prescaler CPU/8
  TCCR2 |= (1<<WGM01);  // CTC-Modus einstellen
  OCR2 = 149;           // OCR2-Register laden für 0,1 ms
  TIMSK |= (1<<OCIE2);  // CompareMatch-Interrupt aktivieren

ist zwar "C" aber fürs Prinzip:

Programm in einezelne kleinere Blöcke aufteilen. Am Anfang eines Blockes 
schreiben was er bewirken soll.
Die Zeile selber ist eigentlich selbst erklärend. Da ich mir aber die 
Register und deren Bezeichnungen nicht alle Merken kann, habe ich mir 
hier ebenfalls dahinter geschrieben was diese Zeile bewirken soll.
Das ersparte mir schon so manchmal einen Blick ins Datenblatt.

just my 2 cent
Dietmar

von spess53 (Gast)


Lesenswert?

Hi

>in einer Schleife und bekomme es einfach nicht hin weder in
>Bascom noch Assembler...

>abfrage:    ldi r17, PORTD

Damit lädst du r17 mit der Adresse ($12) von PORTD.

Den Zustand der Pins bekommst du mit 'in r17,PIND'.

MfG Spess

von Vivil (Gast)


Lesenswert?

Dietmar schrieb:
> Das ist im Prinzip ja auch nicht falsch. Nur in dem Kommentar sollte
>
> nicht die Erklärung des Befehls stehen. Sondern zusatzliche
>
> Informationen, die nicht direkt aus dem lesen des Quelltextes
>
> ersichtlich sind.

Deswegen tippte ich:

Vivil schrieb:
> Nicht beschreiben was der Befehl macht sondern warum Du ihn machst.

von Vivil (Gast)


Lesenswert?

Aber wie wir sehen möchte er nicht.

von Dietmar (Gast)


Lesenswert?

Wenn er aber hätte, könnte man auch die Diskrepanz zwischen Befehl und 
Kommentar erkennen.
--> Hilfe wäre einfacher

von Vivil (Gast)


Lesenswert?

Meine Rede und eventuell würde er die Wiedersprüche auch selber 
erkennen.

von Gerhard H. (oderlachs)


Lesenswert?

Hallo Freunde,

Habt vielen Dank für alle Erläuterungen und Hinweise, ich habe mich auch 
vielleicht falsch noch ausgedrückt , weiss immer noch nicht so recht wie 
ich es beschreiben soll, eben noch Anfänger der lernt.
Ich mache zur Zeit die Schaltung fertig und stelle sie dann auf meinen 
Webspace, da kann man vieleicht besser erkennen was ich da meine..

Vorerst allen recht herzlichen Dank, Ihr seid wie immer, mir eine grosse 
Hilfe !!

Gruss Gerhard

von Erbsenzähler (Gast)


Lesenswert?

Vivil schrieb:
> ldi r16, 0xFF       ; lade Arbeitsregister r16 mit der Konstanten 0xFF
>          out DDRB, r16       ; Inhalt von r16 ins IO-Register DDRB ausgeben
>
>          ldi r16, 0b11111111 ; 0b11111111 in r16 laden
>          out PORTB, r16      ; r16 ins IO-Register PORTB ausgeben
>
> Nicht beschreiben was der Befehl macht sondern warum Du ihn machst.

DU selbst hast in Deinem Beispiel unübertreffbar genau das exakte 
Gegenteil von dem gemacht, was Du (völlig korrekterweise!) als falsch 
beschreibst:

Du dokumentierst dort lediglich, WAS Du programmierst (oder treffender: 
was die CPU ausführt), OHNE auch nur anzudeuten, WARUM.

Sonst hättest Du bspw. in den Kommentaren darauf hingewiesen, daß Du 
Einser-Bit nicht "nur einfach nur so" in das DDRB Register schreibst, 
sondern weil die CPU den jeweils dazugehörenden Port-Pin als Ausgang 
verwenden soll.

Oder noch besser - um Dich noch näher dem praktischen Betrieb des 
Systems anzunäheren - mußt Du im Kommentar erklären, warum das eine oder 
andere Port überhaupt gegenüber dem Post-Reset-Status des Controllers 
als Ausgang eingerichtet werden muß.

Also erklären, welche Systemanforderung jeder einzelne Programmschritt 
wie erfüllt.

Erst Beschreibungen dieser Qualität sind kompatibel mit Deiner eigenen 
Forderung.

Das was Du im Beispiel oben rechts hinter die Semikoli "gedichtet" hast, 
ist dagegen nichts weiter als eine sinngemäße 1:1-Wiedergabe aus der 
Befehlssatzbeschreibung des Controllers - und entsprechend redundant.

MfG

von Vivil (Gast)


Lesenswert?

Wenn Du schon Erbsen zählst so zähle richtig.

Das war ein  Auszug aus seinem Code wie du oben nachlesen kannst.
Also auch Du erst Denken, richtig lesen und dann motzen.

Also hau mich hier nicht so an, schon klar das in diesem Forum dieses 
gerne gemacht wird. Aber Obacht wenn schon dan richtig grins

von Gerhard H. (oderlachs)


Lesenswert?

Hallo Leute, bitte streitet Euch doch nicht, ich denke jeder kann mal 
was falsch machen oder ein Anderer sieht es anders als man selbst.

So ich habe mal die Schaltung ,noch mehr Entwurf und nicht komplett 
vollständig, ins Web geladen :

http://werkstatt.oderlachs.de/avr/pictures/signal_controll.gif

Diese Schaltung ist noch mit dem AM8535, drum nicht wundern warum ich 
oben vom 8515 schrieb, den habe ich zum experimentieren, vor allem zum 
Lernen auf den STK 500...
Also wird eine der Tasten in der Schaltung betätigt soll der 
entsprechende Ausgang vom µC den dazugehörigen Optokoppler schalten und 
das ziemlich schnell, ein Durchlauf der Portabfrage(Eingang) sollte max 
1 Sec. dauern und dann ausgegeben werden.
Vielleicht ist es jetzt besser zu verstehen, was ich machen möchte, will 
Euch ja auch nicht übermässig mit meinen Anfängerproblemen  belasten.
Später soll dann die Eingabe/Ausgabe etwas präzisiert werden, also Länge 
der Ausgabezeit usw.
Mir geht es aber jetzt nur darum zu wissen, wie ich das vom Eingang auf 
den Ausgang bekomme.
Die Tasten gegen Masse und Optokoppler gegen +5V habe ich darum gewählt, 
um es auf dem STk nachvollziehen zu können.

Ich dank Euch schon mal im Voraus, für Hilfe und Ratschläge

Gerhard

Edit 1: Morgen oder übermorgen werde ich mal schreiben wie ich mit dem 
Programm überhaupt was weiter gekommen bin, habe nicht immer so Zeit 
dafür.

von Gerhard H. (oderlachs)


Lesenswert?

Also zumindestens habe ich den Schritt geschafft mit den Eingangspegeln 
die Ausgangspegel zu schalten, allerdings mit anderen Port.
ich habe bei RN-Wissen.de dazu folgenes in einem Assembler-Tutorial 
gefunden

Hier das Zitat:
Beispiel

An PORTC haben wir (mit Vorwiderständen) ein paar LEDs angeschlossen. 
Und die sollen einfach nur zeigen, welche 0-er und 1-er am PORTB 
anliegen.

 ; Eigene Initialisierungen
  LDI R24, 0            ; der wert "0" ins allgemeine Register R24
  OUT DDRB, R24         ; das kommt ins Controll-register f. PortB
                        ; dadurch sind diese PINs als INPUT festgelegt
  LDI R24, 255          ; der wert "255" = FF ins allgemeine Register 
R24
  OUT DDRC, R24         ; das kommt ins Controll-register f. PortC
                        ; dadurch ist das Port auf OUTPUT gestellt

 ; Eigene Befehle (in der Hauptschleife)
  IN  R24, PINB         ; die Bits vom PortB ins allgemeine Register R24
  OUT PORTC, r24        ; schreiben wir nach PortC
                        ; wo ein 1-er ist, leuchtet nun die LED

Wenn wir diese Befehle in das Programm-Schema oben einfügen, haben wir 
also das erste Assemblerprogramm schon geschrieben.
.........

Zitatende

Nur eines begreife ich dabei nicht wie es zu der "Hauptschleife" kommt, 
ich habe nur folgenden Code daraus gemacht, d.h. die erste Zeile 
hinzugefügt :

.include "m8515def.inc"

  LDI R24, 0            ; der wert "0" ins allgemeine Register R24
  OUT DDRB, R24         ; das kommt ins Controll-register f. PortB
                        ; dadurch sind diese PINs als INPUT festgelegt
  LDI R24, 255          ; der wert "255" = FF ins allgemeine Register 
R24
  OUT DDRC, R24         ; das kommt ins Controll-register f. PortC
                        ; dadurch ist das Port auf OUTPUT gestellt

 ; Eigene Befehle (in der Hauptschleife)
  IN  R24, PINB         ; die Bits vom PortB ins allgemeine Register R24
  OUT PORTC, r24        ; schreiben wir nach PortC


und schon geht es...

von spess53 (Gast)


Lesenswert?

Hi

>Nur eines begreife ich dabei nicht wie es zu der "Hauptschleife" kommt,
>ich habe nur folgenden Code daraus gemacht, d.h. die erste Zeile
>hinzugefügt :

Meinst du die:  .include "m8515def.inc" ?

Wenn ja: Dadurch weiss der Assembler erst, welche Adresse Portx, ... 
haben.
Die sind bei unterschiedlichen AVRs durchaus verschieden.

> LDI R24, 255

benutze bitte LDI R24,0b11111111 oder LDI R24,$FF (0xFF). Dezimalzahlen 
sind an der Stell irreführend bzw. total unverständlich.

MfG Spess

von Gerhard H. (oderlachs)


Lesenswert?

Hallo Spess !
Ja ich verstehe das schon mit der Dezimalzahlangabe, das mit binärem 
Wert sieht mann auch gleich das Bitmuster, ist mir auch klar.
Ich habe auch das nur so org. aus dem Tuto übernommen, das mit der 
m8515def.inc ist mir auch verständlich , dort werden dem Compiler die 
Adressen für die Worte wie PortA,DDRB usw.. übergeben. Man müsste wohl 
sonst den Code in kopfzermarternden Adressangaben schreiben, aus C64er 
Zeit mir noch gut bekannt...

Was ich nicht verstehe ist hier :
IN  R24, PINB         ; die Bits vom PortB ins allgemeine Register R24
OUT PORTC, r24        ; schreiben wir nach PortC

Wie kommt der Progcounter nach der Abarbeitung der out ... Anweisung 
wieder zurück in die In... Anweisung, um PortB neu abzufragen, ob sich 
da was geändert hat ??

Aber je mehr Probleme ich habe um so mehr muss ich lernen und das ist 
gut !!

Euch Allen, auch natürlich besten Dank für alle Hilfe !!!

Gerhard

von spess53 (Gast)


Lesenswert?

Hi

>Was ich nicht verstehe ist hier :
>IN  R24, PINB         ; die Bits vom PortB ins allgemeine Register R24
>OUT PORTC, r24        ; schreiben wir nach PortC

>Wie kommt der Progcounter nach der Abarbeitung der out ... Anweisung
>wieder zurück in die In... Anweisung, um PortB neu abzufragen, ob sich
>da was geändert hat ??

Eigentlich gar nicht. Wenn allerdings der Rest des Programmspeichers 
durch Löschen mit $FF gefüllt ist, wird er wohl bis zum Speicherende 
durchlaufen und dann von vorn wieder anfangen.
Um eine Programmschleife zu erhalten, musst du folgendes machen:

label:
  IN  R24, PINB         ; die Bits vom PortB ins allgemeine Register R24
  OUT PORTC, r24        ; schreiben wir nach PortC
  rjmp label            ; Sprung nach label

Wobei 'label' ein Bezeichner deiner Wahl ist.

MfG Spess

von Paul B. (paul_baumann)


Lesenswert?

Wenn Du mit PIN statt PORT drangehst, müßte es funktionieren:

config PortD = input
config PortB = output
dim P as bit

do
P = PIND.0  'Hier ist die Stelle
PortB.0 =P
....
....
P= PIND.7
PortB.7 = P
loop

end

Print "MfG Paul"

von Gerhard H. (oderlachs)


Lesenswert?

Danke Spess,  habe selbiges eben gemacht "rjmp schleife"...geht

Danke Paul, ja das mit dem PinD  o.ä.  ja das weiss ich noch nicht alles 
so genau aus dem Kopf, meine ersten IO-Schritte dieser Art, die ich 
mache... Danke für den Hinweis.

Ich freue mich ja so ,daß ich hier nachfragen darf, wenn ich mich auch 
manchmal böd anstelle, aber so im "Selbststudium" erkennt man seine 
eigenen Fehler schlecht selber.. ;)

Ich habe vor 15 Jahre mal Assembler 8085 gemacht, davor noch  mit dem 
C64er. da ist ein wenig hängen geblieben, aber sind die Mnemonik und die 
Bezeichner doch oft anders, gerade in ASSR bei verschiedenen Chips...

Gruss Gerhard

von spess53 (Gast)


Lesenswert?

Hi

>Ich habe vor 15 Jahre mal Assembler 8085 gemacht, davor noch  mit dem
>C64er. da ist ein wenig hängen geblieben, aber sind die Mnemonik und die
>Bezeichner doch oft anders, gerade in ASSR bei verschiedenen Chips...

Ich habe in den 80-ern mit dem U880(Z80) angefangen. Mit dem 
Hintergrundwissen fand ich den Einstieg bei den AVRs nicht sehr 
kompliziert.

Sie dir mal in Ruhe das Instruction Set an:

http://www.atmel.com/dyn/resources/prod_documents/doc0856.pdf

MfG Spess

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.