Forum: Mikrocontroller und Digitale Elektronik 10er LED Lauflicht Problem


von A. B. (developer_x)


Lesenswert?

Sehr geehrtes Forum,
ich habe eine Software in Assembler geschrieben, die ein Lauflicht mit 
10 LEDs steuern soll, doch leider geschehen seltsame Fehler.

Erstmal der Code :
-----------------------------------------------------
.include "M48PAdef.inc"

; Stackpointerinitialisierung
  LDI R16, LOW(RAMEND)   ;Stackpointer initialisieren
  OUT SPL, R16
  LDI R16, HIGH(RAMEND)   ;Stackpointer initialisieren
  OUT SPH, R16

; Portoutputinitialisierung
  LDI r20,0b11111111
  OUT DDRB,r20
  OUT DDRD,r20

; Variables Declaration
  LDI r20,0b10000000
  LDI r25,0b00000000

///////////////////////////////////////////////////
//////////////////////Hauptprogramm////////////////
///////////////////////////////////////////////////

MAIN :

  OUT PORTD, r25
  LDI r21,0b00000001
  LDI r22,10
  LDI r23,19

  ROT :
  OUT PORTB,r21
  ROL r21
  RCALL Wait100MS
  INC r22
  CPSE r22,r23
  BRNE ROT

  LDI r21,0b00000010
  OUT PORTB, r25
  OUT PORTD,r21
  ROR r21
  RCALL Wait100MS
  OUT PORTD,r21
  ROR r21
  RCALL Wait100MS

RJMP MAIN

; 
//////////////////////////////////////////////////////////////////////// 
//////////
; ///////////////////////////  WAIT FUNCTIONS 
///////////////////////////
; 
//////////////////////////////////////////////////////////////////////// 
//////////
Wait1MS :               ; r17 used
LDI r16,255
LDI r17,56
WaitXX1ms :
NOP
INC r17
CPSE r17,r16
BRNE WaitXX1ms
RET

Wait10MS :              ; r18 used [r17 used]
LDI r16,255
LDI r18,246
WaitXX10ms :
RCALL Wait1MS
INC r18
CPSE r18,r16
BRNE WaitXX10ms
LDI r18,0b00000000 ; 9075
LDI r16,255
LDI r17,23 ; 9077
WaitXX10ms2 :
INC r17
CPSE r17,r16
BRNE WaitXX10ms2
RET

Wait100MS :              ; r19 used [r18 used [r17 used]]
LDI r16,255
LDI r19,246
WaitXX100ms :
RCALL Wait10MS
INC r19
CPSE r19,r16
BRNE WaitXX100ms
LDI r16,255
LDI r19,246
WaitXX100ms2 :
RCALL Wait1MS
INC r19
CPSE r19,r16
BRNE WaitXX100ms2
LDI r16,255 ; 99121
LDI r19,34
WaitXX10ms3 :
INC r19
CPSE r19,r16
BRNE WaitXX10ms3
RET

Wait1000MS :
RCALL WAIT100MS
RCALL WAIT100MS
RCALL WAIT100MS
RCALL WAIT100MS
RCALL WAIT100MS
RCALL WAIT100MS
RCALL WAIT100MS
RCALL WAIT100MS
RCALL WAIT100MS
RCALL WAIT100MS
RET
-----------------------------------------------------

Das Problem :
1. Es leuchten beim zweiten Durchlauf mehrere LEDs gleichzeitig auf,
obwohl ja eigentlich immer nur eine an sein dürfte.
2. Beim ersten Durchlauf gibt es eine Pause von 100MS bevor eine LED
von PORTD leuchtet, aber im weiteren Verlauf gibt es diese Pause nicht.

Hat jemand ne Idee, wie das sein kann?
m.f.G. Developer_X

von Markus (Gast)


Lesenswert?

Hi,

also wenn ich es richtig verstehe, sollen die LEDs von links nach rechts 
laufen und dann wieder zurück?

Mit der vorhandenen Programmlogik funktioniert das so nicht.

Ansonsten zu Deinen Problemen:

zu 1: Du machst ein ROR ohne vorher einen definierten Zustand des 
Carry-Flags zu haben, beim ROR wird das MSB (Bit 7) mit dem aktuellen 
Wert aus dem Carry-Flag gefüttert. Evtl. ist dann LSR das was Du machen 
möchtest.

Für ROL gilt analog, das der Wert vom Carry-Flag im Bit 0 landet. 
Alternativ gibt es hier LSL welches das Bit immer auf 0 setzt.

zu 2: Du hast R25 auf 0 gesetzt, machst dann die Ausgabe und den Wait, 
bevor Du in R25 irgendwas reinschreibst.


Wenn Du ein Bit über 10 LEDs (also zwei Register) schieben möchtes, 
nimm' eine Kombination aus LSL/ROL bzw. LSR/ROR.

Angenommen Du nimmst R20 und R21 für die beiden Ports, dann machst Du

LSL R20
ROL R21

bzw.

LSR R21
ROR R20

Der Effekt ist, wenn das 1-Bit aus dem ersten Register rausgeschoben 
wird, landet es über das ROL bzw. ROR dann im anderen Register.

Allgemein solltest Du versuchen, Deinen Code etwas übersichtlicher zu 
gestalten :-)

- Einrücken von allem was kein Label ist
- Klare Beschreibung welche Register eine Funktion verwendet (IN, OUT, 
SCRATCH)
- Eine klare Taktik, welche Register eine Funktion grundsätzlich 
verändern darf (z.B. r0/r1 und r28/r29), alles andere mit push/pop 
retten falls es in der Funktion benötigt wird.

Grüße
Markus

von A. B. (developer_x)


Lesenswert?

Nein, es soll folgendes leisten :

Die Leiste soll von links (PortB 1) nach rechts (PORTD 2) durchlaufen, 
es sind 10 LEDS, deshalb müssen zwei Ports verwendet werden, danach soll 
das ganze wieder bei Port B1 beginnen.

So meinte ich das, kannst du mir im Anbetracht dessen weiterhelfen?

Danke,
m.f.G. Developer_X

von Markus M. (adrock)


Lesenswert?

Ungefähr so (Initialisierung spare ich mir mal):
1
MyLoop2:
2
  ldi  r20, 0x01     ; Startwert PORTB
3
  ldi  r21, 0x00     ; Startwert PORTD
4
5
MyLoop:
6
  OUT  PORTB, r20    ; Ausgabe PORTB
7
  OUT  PORTD, r21    ; Ausgabe PORTD
8
9
  (Hier Wait-Funktion einfuegen)
10
11
  lsl  r20           ; Bits PORTB schieben
12
  rol  r21           ; Bits PORTD schieben
13
14
  cpi  r21, 0b100    ; Überlauf erreicht?
15
  brne  MyLoop       ; Noe!
16
17
  rjmp  MyLoop2      ; Ja -> Neu anfangen

Grüße
Markus

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.