PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Anfängerfrage zu einem Programm



RevolT3c
07.04.2009, 19:59
Hi @ all,

lese mich gerade ein und hab mein erstes kleines programm in assembler
geschrieben. leider funzt es noch nicht. könnt ihr mir sagen was ich
falsch mache`? habe das myavrusb board und benutze myavrdemo plus:






main: ldi r16,lo8(RAMEND)
out SPL,r16
ldi r16,hi8(RAMEND)
out SPH,r16






ldi r16,0xFF
out DDRB,r16


ldi r17,0x00
out DDRC,r17




loop:

ldi r16,0x01
out PORTB,r16

in r17,PINC


cp r16,r17

breq mainloop

rjmp loop


;------------------------------------------------------------------------
mainloop: wdr
ldi r16,0b11101111
out PORTB,r16

rjmp mainloop



ich möchte einfach das wenn ich am portc am bit 0 eine 1 anliegt, der gesamte portb auf 1 schaltet. woran liegts?

wkrug
08.04.2009, 10:06
Was mir bei deinem Programm fehlt ist die Interrupt Vektortabelle.
Eigentlich müsste dein Programm auch ohne funktionieren, ich würd Sie aber trotzdem immer am Anfang des Programms einfügen.

Bei den zuweisungen für den SPL und SPH kenn ich das mit
ldi r16,low(ramend)
...
ldi r16,high(ramend)
...
Ob das auch mit deinen Zuweisungen geht weiß ich nicht.

Da Du aber keine Subroutinen verwendest sollte das auch kein Problem sein.
Lass doch mal das Stückchen Code im Simulator vom AVR Studio laufen und guck was das passiert.

Den WDR kannst Du Dir sparen, solange Du den Watchdog weder in der Hardware, noch in der Software aktiviert hast.

Vor das Programm hab ich auch immer Speicherdefinitionen gemacht.
.cseg
.org 0x0000
; Programm...

P.S. Prügel mich nicht, wenn die Syntax nich 100% stimmt, hab in Assembler schon länger nichts mehr gemacht.

PicNick
08.04.2009, 10:47
Aus dem "mainloop" kommt er niemals wieder raus, jedenfalls in diesem Leben.
Wie ist das mit den Pull-Up ? Oder schaltest du auf +5V ?
Meistens (oft) wird ja ein Pin mit dem Taster auf GND geschaltet, mit dem Internen Pull up wäre das


ldi r17,0x00
out DDRC,r17
ldi r17,0xFF ; alles auf "1" ----> internern Pullup
out PORTC,r17

wkrug
09.04.2009, 21:46
Ich hab dein Programm ein wenig modifiziert und im Simulator getestet.

.include "m8def.inc"
main:
ldi r16,low(RAMEND)
out SPL,r16
ldi r16,high(RAMEND)
out SPH,r16






ldi r16,0xFF
out DDRB,r16


ldi r17,0x00
out DDRC,r17




loop:

ldi r16,0x01
out PORTB,r16

in r17,PINC


cp r16,r17

breq mainloop

rjmp loop


;------------------------------------------------------------------------
mainloop: wdr
ldi r16,0b11101111
out PORTB,r16

rjmp mainloop
Zuerst wird auf Port B der Wert 0x01 ausgegeben.
Und zwar so lange bis der Pin C.0 High wird.
Dann verzweigt das Programm in den Mainloop, aus dem es nie wieder zurückkommt.
Ist noch zusätzlich ein anderer PIN des Port C aktiv bleibt das Programm in der Schleife loop:
Was soll denn nun das Progrämmchen machen ?

Nichts desto trotz solltest Du die beschriebenen Verbesserungen deines Programmcodes machen.
Du möchtest ja auch mal schwierigere Sachen in Assembler basteln.
Es sein denn es handelt sich hierbei um inline Code für einen Compiler.
Da musst Du dann aber das Handbuch deines Compilers befragen, welche Register für Assembler nutzbar sind.
Die Infromationen, die Du uns hier gibst sind leider etwas mager.

RevolT3c
10.04.2009, 09:07
erstmal danke, habe es auch zum laufen gebracht. es war auch gedacht das er im mainloop bleibt. das war einfach nur ne kleine spielerei, das programm dient keinem echten zweck. dafür meine nächstes programm.

es soll ein kettenschmierimpuls an meiner motorradkette auslösen. sprich wenn ich ca 60km fahre gibt der mikrocontroller einen schmierimpuls weiter.

gezählt wird über einen reedkontakt am rad. ich benötige 50000 signale sprich 50000 radumdrehungen. danach soll die kette kurz schmieren und das ganze geht von vorne los. hier mal mein vorschlag:




;************************************************* *********
.include "m8def.inc"
;************************************************* *********





.org INT_VECTORS_SIZE


.org 0x00
rjmp main ; Reset Handler

.org INT0addr
rjmp int0_handler ; IRQ0 Handler




.def temp = r16

main: ldi temp,low(RAMEND) ; Stackpointer initialisieren
out SPL,temp

ldi temp,high(RAMEND)
out SPH,temp

ldi r18, 0

ldi r19, 0

ldi temp,0xFF
out DDRB,temp


ldi r17,0x00
out DDRD,r17


ldi temp, 0b00001111 ; INT0 und INT1 konfigurieren
out MCUCR, temp

ldi temp, 0b11000000 ; INT0 und INT1 aktivieren
out GICR, temp

sei ; Interrupts allgemein aktivieren

loop: rjmp loop




int0_handler:


ldi r16, 200 ; zählt bis 200
inc r18
cp r16, r18

breq step

reti



reset1: ldi r19, 0x00 ; resetet r19




reset2: ldi r18, 0x00 ; resetet r18
reti




step:
ldi r16, 250 ; zählt bis 250
inc r19
cp r16, r19

breq schmieren

rjmp reset2


schmieren: ; "fehlt noch"

inc r20 ;"zählt anzahl der schmierungen"

rjmp reset1





ich zähle das r18 auf 200 danach springt es zum "step" und resetet sich selbst. im step zählt das r19 auf 250 und wenn die erreicht sind gehts zur "schmierung" anschließend wieder von vorn (250x200 = 50000). die schmierung ansich fehlt aber noch. meint ihr das wäre so realisierbar wenn ich vor dem reedschalter noch einen A/D Wandler setze?


gruss ralph