Programmering i asm i ATMega128
Programmering i asm i ATMega128
Programmering i asm i ATMega128
Ville kolla bit 1 i PORTG. Försöket med BST och BLD men fick det inte att funka. Körde till slut ”idioten” och det funkar… Hur kollar man bit 1 på ett enklare sätt? Jag vill alltså veta om bit 1 är 1 eller 0.
/Harald
lds Temp,PORTG ;Ladda direkt från SRAM
lsr Temp ;skifta in 0 från vänster så att bit 0 knuffas ut
;värdet från bit 1 nu i pos bit 0
lsl Temp ;skifta in 0 från höger nu i pos bit 1
lsl Temp ;skifta in 0 från höger nu i pos bit 2
lsl Temp ;skifta in 0 från höger nu i pos bit 3
lsl Temp ;skifta in 0 från höger nu i pos bit 4
lsl Temp ;skifta in 0 från höger nu i pos bit 5
lsl Temp ;skifta in 0 från höger nu i pos bit 6
lsl Temp ;skifta in 0 från höger nu i pos bit 7
lsr Temp ;skifta in 0 från vänster nu i pos bit 6
lsr Temp ;skifta in 0 från vänster nu i pos bit 5
lsr Temp ;skifta in 0 från vänster nu i pos bit 4
lsr Temp ;skifta in 0 från vänster nu i pos bit 3
lsr Temp ;skifta in 0 från vänster nu i pos bit 2
lsr Temp ;skifta in 0 från vänster nu i pos bit 1
lsr Temp ;skifta in 0 från vänster nu i pos bit 0
;nu finns alltså värdet som fanns i bit 1 i bit 0 och alla andra bitar är 0
tst Temp ;testa om 0
breq SLUT_Down_r19B ;Hoppa om Temp = 0 dvs Relä 1 är frånslaget
Ville kolla bit 1 i PORTG. Försöket med BST och BLD men fick det inte att funka. Körde till slut ”idioten” och det funkar… Hur kollar man bit 1 på ett enklare sätt? Jag vill alltså veta om bit 1 är 1 eller 0.
/Harald
lds Temp,PORTG ;Ladda direkt från SRAM
lsr Temp ;skifta in 0 från vänster så att bit 0 knuffas ut
;värdet från bit 1 nu i pos bit 0
lsl Temp ;skifta in 0 från höger nu i pos bit 1
lsl Temp ;skifta in 0 från höger nu i pos bit 2
lsl Temp ;skifta in 0 från höger nu i pos bit 3
lsl Temp ;skifta in 0 från höger nu i pos bit 4
lsl Temp ;skifta in 0 från höger nu i pos bit 5
lsl Temp ;skifta in 0 från höger nu i pos bit 6
lsl Temp ;skifta in 0 från höger nu i pos bit 7
lsr Temp ;skifta in 0 från vänster nu i pos bit 6
lsr Temp ;skifta in 0 från vänster nu i pos bit 5
lsr Temp ;skifta in 0 från vänster nu i pos bit 4
lsr Temp ;skifta in 0 från vänster nu i pos bit 3
lsr Temp ;skifta in 0 från vänster nu i pos bit 2
lsr Temp ;skifta in 0 från vänster nu i pos bit 1
lsr Temp ;skifta in 0 från vänster nu i pos bit 0
;nu finns alltså värdet som fanns i bit 1 i bit 0 och alla andra bitar är 0
tst Temp ;testa om 0
breq SLUT_Down_r19B ;Hoppa om Temp = 0 dvs Relä 1 är frånslaget
Tja....
Det finns många sätt att lösa problemt på här ett sätt, som desutom är ganska enkelt
http://www.atmel.com/dyn/resources/prod ... oc2550.pdf
http://www.atmel.com/dyn/resources/prod ... macros.inc
hoppas att det hjälpte
Det finns många sätt att lösa problemt på här ett sätt, som desutom är ganska enkelt
http://www.atmel.com/dyn/resources/prod ... oc2550.pdf
http://www.atmel.com/dyn/resources/prod ... macros.inc
hoppas att det hjälpte

Det funkade bra att ersätta mina ”skiftningar” med direkt koll av biten med sbrc. Exemplet här http://www.atmel.com/dyn/resources/prod ... oc2550.pdf gör mej dock konfunderad. Vad är det för språk? Min AVR500 har version 4.06 och den typen av kod kan tydligen köras i V4.08 som kan laddas ner och är free. Finns t ex do while eller motsvarande i det språket. Det har jag ju nu snickrat själv t ex så här:
Process_1:
Upprepa_Process_1:
Mov…
Cls…
Rcall…
Tst r17
Breq Slut_Process_1 ;Hoppa ur om r17 = 0
Rjmp Upprepa_Process_1
Slut_Process_1:
Ret
/Harald
Process_1:
Upprepa_Process_1:
Mov…
Cls…
Rcall…
Tst r17
Breq Slut_Process_1 ;Hoppa ur om r17 = 0
Rjmp Upprepa_Process_1
Slut_Process_1:
Ret
/Harald
Tja det är inge språk utan ett sätt att säga vad prekompilatorn ska göra...
du har redan använt prekompilatorn genom att använda exempel
.def temp =r16
men man kan få prekompilatorn att välja kod beronde på vilket vilkor de får eller man kan göra makron som gör flera rader code med en rad. Det kan vara väldigt praktisk i bland då man gör sama sak på flera ställen och funktionen är så liten att det inte är någon mening att ha den i ett funktions anrop eller om det är tids kritiskt..
do while får du snickra ihop själv
men du kan använda exempel brne för att göra den lite mindre
Process_1:
Upprepa_Process_1:
Mov
Cls
Rcall
Tst r17
BRNE Upprepa_Process_1 ;Hoppa ur om r17 = 0
Ret
du har redan använt prekompilatorn genom att använda exempel
.def temp =r16
men man kan få prekompilatorn att välja kod beronde på vilket vilkor de får eller man kan göra makron som gör flera rader code med en rad. Det kan vara väldigt praktisk i bland då man gör sama sak på flera ställen och funktionen är så liten att det inte är någon mening att ha den i ett funktions anrop eller om det är tids kritiskt..
do while får du snickra ihop själv
men du kan använda exempel brne för att göra den lite mindre

Process_1:
Upprepa_Process_1:
Mov
Cls
Rcall
Tst r17
BRNE Upprepa_Process_1 ;Hoppa ur om r17 = 0
Ret
Erixon,
Smart lösning… Jag har ändrat till din lösning på alla ställen där det endast sker ETT test. När det är flera tester verkar det som om man måste ha något att hoppa till i slutet liksom…
Din lösning skulle även kunna användas i nedanstående kodexempel. Jag använder hexadecimala omkopplare direkt på portarna. Varje omkopplare har 4 bit och kan alltså beskriva 0-F. Två omkopplare kan alltså beskriva 0-FF eller 0-255. En användare kan lätt ställa in ”entalsomkopplaren” som är graderad från 0-F. Det är värre att ställa in 16-talsomkopplaren. Då måste man räkna… Därför gjorde jag om 16-talen till 10-tal. Dvs jag skiftade in nollor så att 16-talet blev entaligt och så skulle jag multiplicera med 10. Fick inte mul att fungera. Tog då och adderade 10 gånger… Gör man så här kan man beskriva tal mellan 0 och 225 (15 x 15) Om man kör med en decimal omkopplare för 10-talen blir omfånget 0 – 150… Det kanske blev obegripligt det här…?
Jag förmodar att detta att konvertera 16-tal till 10-tal är en känd grej för assemblerprogrammerare. Finns det ingen som samlat ihop den här typen av programmeringstips? Det här kan säkert också göras mycket smartare!
/Harald
r7_16_tal_10_tal: ;talet finns i r7. Bit 0-3 är värd 0-15,
;bit 4-7 0-15 x 16. Ändras till 0-15 x 10 för att få bättre
;användarvänlighet. Metod. Kopierara värdet i r7 till r24 (Temp)
;Skifta in 4 nollor från höger och därefter 4 nollor från vänster
;så finns endast talet entalstalet i variablen. Lägg denna i r23.
;(SF-variabeln lånas...)
;Kopiera värdet i r7 till r24. Skifta in 4 nollor från vänster
;så finns det tidigare värdet från bit 4-7 nu i bit 0-3.
;Multiplicera detta värde med hjälp av variabel r25 (används i
;delay20ms)
;Testvärde r7
;ldi Temp,130
;mov r7,Temp
clr r23
clr r24
clr r25
mov Temp,r7
lsl Temp ;skifta in nollor från höger
lsl Temp
lsl Temp
lsl Temp
lsr Temp ;skifta in nollor från vänster
lsr Temp
lsr Temp
lsr Temp
mov r23,Temp ;ental läggs i r23
mov Temp,r7
lsr Temp ;skifta in nollor från vänster
lsr Temp
lsr Temp
lsr Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r23,r25 ;addera r23 och r25.
mov r7,r23 ;nu finns det konverterade värdet i r7...
ret
Smart lösning… Jag har ändrat till din lösning på alla ställen där det endast sker ETT test. När det är flera tester verkar det som om man måste ha något att hoppa till i slutet liksom…
Din lösning skulle även kunna användas i nedanstående kodexempel. Jag använder hexadecimala omkopplare direkt på portarna. Varje omkopplare har 4 bit och kan alltså beskriva 0-F. Två omkopplare kan alltså beskriva 0-FF eller 0-255. En användare kan lätt ställa in ”entalsomkopplaren” som är graderad från 0-F. Det är värre att ställa in 16-talsomkopplaren. Då måste man räkna… Därför gjorde jag om 16-talen till 10-tal. Dvs jag skiftade in nollor så att 16-talet blev entaligt och så skulle jag multiplicera med 10. Fick inte mul att fungera. Tog då och adderade 10 gånger… Gör man så här kan man beskriva tal mellan 0 och 225 (15 x 15) Om man kör med en decimal omkopplare för 10-talen blir omfånget 0 – 150… Det kanske blev obegripligt det här…?
Jag förmodar att detta att konvertera 16-tal till 10-tal är en känd grej för assemblerprogrammerare. Finns det ingen som samlat ihop den här typen av programmeringstips? Det här kan säkert också göras mycket smartare!
/Harald
r7_16_tal_10_tal: ;talet finns i r7. Bit 0-3 är värd 0-15,
;bit 4-7 0-15 x 16. Ändras till 0-15 x 10 för att få bättre
;användarvänlighet. Metod. Kopierara värdet i r7 till r24 (Temp)
;Skifta in 4 nollor från höger och därefter 4 nollor från vänster
;så finns endast talet entalstalet i variablen. Lägg denna i r23.
;(SF-variabeln lånas...)
;Kopiera värdet i r7 till r24. Skifta in 4 nollor från vänster
;så finns det tidigare värdet från bit 4-7 nu i bit 0-3.
;Multiplicera detta värde med hjälp av variabel r25 (används i
;delay20ms)
;Testvärde r7
;ldi Temp,130
;mov r7,Temp
clr r23
clr r24
clr r25
mov Temp,r7
lsl Temp ;skifta in nollor från höger
lsl Temp
lsl Temp
lsl Temp
lsr Temp ;skifta in nollor från vänster
lsr Temp
lsr Temp
lsr Temp
mov r23,Temp ;ental läggs i r23
mov Temp,r7
lsr Temp ;skifta in nollor från vänster
lsr Temp
lsr Temp
lsr Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r25,Temp
add r23,r25 ;addera r23 och r25.
mov r7,r23 ;nu finns det konverterade värdet i r7...
ret
Tja... hur man omvandlar dec till bin finns i exempel i app204
http://www.atmel.com/dyn/resources/prod ... oc0938.pdf
exempel på hur man kan göra finns många sätt
Tyvär kan jag inte rekomdera något ställe där det finns lätt förståd asambler code 
http://www.atmel.com/dyn/resources/prod ... oc0938.pdf
exempel på hur man kan göra finns många sätt
Kod: Markera allt
.def ansl = r0
.def ansh = r1
.def temp1 = r16
.def temp2 = r17
.def argument = r18
exempel:
ldi temp1, 0xF0
and temp1, argument
ldi temp2, 160
mul temp1, temp2
andi argument, 0x0F
add argument, ansh
ret
