Fråga ang C kod

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
exos
Inlägg: 194
Blev medlem: 24 november 2005, 21:04:25

Inlägg av exos »

använde detta schemat...
http://web.telia.com/~u52113724/Bilder/LED-blink.png

och gjorde denna koden:

Kod: Markera allt

.org 0x0000
rjmp main

.include "c:\Program\Atmel\AVR Tools\AvrAssembler2\Appnotes\tn261def.inc"

main:
ldi r16,RAMEND    ;Stackpointer initialisieren 
out SPL,r16

ldi r16, 0xFF
out DDRB, r16

LOOP: 
 
sbi PortB, 3 
cbi PortB, 3 
sbis PinB, 5 

rjmp LOOP 

Det som händer nu är att led´n lyser och när jag håller ner knappen så slocknar den...MEN inte helt den lyser jätte svagt... och när ja släpper upp knappen igen så tänds den...

tanken va ju att vid ett kanpptryck så är den tänd, trycker man en gång igen så släcks den....

nån som vet vad som är fel? :?:
Användarvisningsbild
MicaelKarlsson
Inlägg: 4669
Blev medlem: 18 juni 2004, 09:16:07
Ort: Aneby
Kontakt:

Inlägg av MicaelKarlsson »

Skall du inte initiera så här istället?

ldi r16, 0x02
out DDRB, r16

Nu har du ju hela port B som utgångar, om jag inte tar fel :?
Senast redigerad av MicaelKarlsson 7 januari 2006, 13:50:29, redigerad totalt 1 gång.
Användarvisningsbild
Xyzzy
Inlägg: 1260
Blev medlem: 30 januari 2004, 22:31:07
Ort: Uppsala, Sweden

Inlägg av Xyzzy »

Ja kan aldrig tänka mig att du kopplat som i schemat om du använder koden du skrev.
Enl. asmkoden kopplar du knappen till PORTB.5 men LED till PORTB.4 men enl. schemat är de kopplade till PORTD.0 resp. PORTD.1, VAD gäller?
Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Inlägg av Kaggen »

exos:
Tycker fortfarande du inte verkar ha riktig förståelse vad kommandona gör som du skriver. Verkar som om du slänger in lite kommandon där du tror dom skall vara och hoppas på det bästa.

Om du följer din kod uppifrån och ner, vad händer i koden?

Om jag plockar ut LOOP från ditt exempel:

Kod: Markera allt

  
LOOP: 

sbi PortB, 3 ; Sätter bit 3 på PortB, Diod lyser
cbi PortB, 3  ; Nollar bit 3 på PortB, Diod släcks
sbis PinB, 5  ; Kollar om bit 5 på PinB är satt, skippar isåfall efterföljande
           kommando som i detta fall är "rjmp LOOP".

rjmp LOOP ; Hoppar tillbaka till "LOOP"
Vad händer efter rjmp LOOP? Om bit 5 på PinB är satt så hoppar ju programmet över "rjmp LOOP" och där hittar det... ...ingenting?...

Vad är PinB förresten? Menar du PortB? Att kolla bit 5 på PinB låter lite konstigt.

Det du gör är ju att tända och släcka dioden hela tiden. Den är tänd den tid det tar att exekvera "sbi PortB,3" kommandot, vilket kanske är 1 us, och sedan är den släckt under "cbi PortB,3 och sbis och rjmp" kommandona vilket kanske är 5-6 us, för att sedan hoppa tillbaka till LOOP igen och vara tänd 1 us, osv. osv. osv

Du måste ha en förståelse hur processorn utför ovanstående kommandon, annars är det som att ta massa ryska ord och slumpa ihop dom och hoppas att det skall bli en förståelig mening.

Mats
exos
Inlägg: 194
Blev medlem: 24 november 2005, 21:04:25

Inlägg av exos »

ang koden...
Detta är vad jag har uppfattat det som...

Kod: Markera allt

LOOP: 
  
sbi PortB, 3 : skickar ett värde till PortB pin 3
cbi PortB, 3 : rensar värdert på PortB pin 3
sbis PinB, 5 : läser av Port B, 5

rjmp LOOP 
men undertiden nu så ser jag ju att så som jag trodde att det va verkar ju iunte rätt, eftersom PortB, 3 måste ju vara att den sätter 3 bit på PortB ...

Jag vill som sagt inte heller sätta hela PortB utan just en viss pin typ PB3
och läsa från PB5.

Men då skall det vara såhär mer...

Kod: Markera allt

LOOP: 
  
sbi PortB, 3 : skickar ett värde till PortB pin 3
cbi PortB, 3 : rensar värdert på PortB pin 3
sbis PinB, 5 : läser av Port B, 5

rjmp LOOP 

så här körs koden om PinB är satt till 5 bit... ?

Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Inlägg av Kaggen »

> Detta är vad jag har uppfattat det som...

Kod: Markera allt

 
LOOP: 
  
sbi PortB, 3 : skickar ett värde till PortB pin 3 
cbi PortB, 3 : rensar värdert på PortB pin 3 
sbis PinB, 5 : läser av Port B, 5 

rjmp LOOP 
> men undertiden nu så ser jag ju att så som jag trodde att det va verkar
> ju iunte rätt, eftersom PortB, 3 måste ju vara att den sätter 3 bit på PortB ...

Ah, du har inte läst på tillräckligt. Kolla i manualen för AVR-instruktioner:
http://www.atmel.com/dyn/resources/prod ... oc0856.pdf

Sida 117

Kommandot sbi PortB,3 Sätter bit nummer 3 och enbart bit nummer 3 till "1" på PortB. Den sätter inte 3 bitar på PortB. Inga andra bitar på PortB berörs.

För att göra det ännu tydligare:

Kod: Markera allt

PortB bitar och värde:
Bit nummer  7 6 5 4 3 2 1 0
Värde       0 0 0 0 1 0 0 0

Se? Bit nummer 3 är "1"
När du sätter bit nummer 3 på PortB, lägger processorn ut +5V på den pinne som motsvarar bit 3 på PortB, i fallet ATiny26 är det ben 4.

Har du dioden kopplad där lyser den, eftersom den får +5V spänning.

Sedan (enligt ditt program) sätter du bit nummer 3 på PortB till noll med kommandot cbi PortB,3. Detta gör att processorn tar bort spänningen på den pinne som motsvarar bit nummer 3 på PortB (fortfarande ben 4). Det betyder att dioden inte får spänning/ström och följaktligen inte lyser.

Efter det du tänt och släckt dioden i din kod med ovanstående kommandon (sbi, cbi) så kollar du vad du har på ingången PinB bit nummer 5. Om man så tittar i databladet, ser man att PinB bit 5 motsvarar ATiny26 ben 8.

Om du har en spänning (+5V) på ben 8 kommer bit 5 på PinB vara "1", om du inte har någon spänning på ben 8 (0V) kommer bit 5 på PinB att vara "0".

Om du nu har brytaren kopplad till ben 8 på ATiny26 och sluter den, kommer det att ligga en spänning på +5V på det benet. När du då läser av med sbis PinB,5 kommer den att känna av en "1" på PinB bit 5 och följaktligen skippa nästa kommando (i ditt fall rjmp LOOP). Detta vet du antagligen redan eftersom du läst hur sbis kommandot funkar på sidan 119 i ovan nämnda datablad.

Det enda din knapptryckning gör är att hoppa över rjmp-kommandot ifall du sluter brytaren. Ifall du inte sluter den så läser den rjmp LOOP och hoppar till labeln LOOP och fortsätter därifrån.

För att summera:

Det du gör i ditt program (stegen nummrerade):

1. Sätter bit 3 PortB (tänder dioden)
2. Nollar bit 3 PortB (släcker dioden)
3. Kollar om brytaren är nedtryckt (bit 5 PinB), hoppar isåfall över nästa kommando (steg 4).
4. Hoppar tillbaka till steg 1


Som du ser har vi inget steg 5. Det har du inte heller i ditt program, så när brytaren är "till" hoppar processorn ur ditt program och exekverar vad som nu kan tänkas ligga efter steg 4. Antagligen resettar den sig eller lyckas så småningom hoppa till startvektorn och börjar om ditt program igen efter några mikrosekunder, men det är likväl fel.


Det du vill göra (stegen nummrerade):

1. Kolla om brytaren är nedtryckt (bit 5 PinB), hoppa isåfall över nästa steg (steg 2)
2. Nolla bit 3 PortB (släck dioden)
3. Kolla om brytaren inte är nedtryckt (bit 5 PinB), hoppa isåfall över nästa steg (steg 4)
4. Sätt bit 3 PortB (tänd dioden)
5. Hoppa tillbaka till steg 1


Nu kommer det mest spännande. Kan du göra om "Det du vill göra" i vacker AVR-kod? Sätt de små grå i gungning.

EDIT: Tips! Du behöver ett till kommando förutom de du redan använt: sbic. Nu så, jag har redan sagt mer än nog.

Mats
exos
Inlägg: 194
Blev medlem: 24 november 2005, 21:04:25

Inlägg av exos »

Tack för ett jätte bra svar... fatta allt utom det med att PinB,5 skulle vara ben 8,

exemplet med PortB haja jag...

Kod: Markera allt

PortB bitar och värde: 
Bit nummer  7 6 5 4 3 2 1 0 
Värde       0 0 0 0 1 0 0 0 

Se? Bit nummer 3 är "1" 
om man säger enligt den koden så skulle ben 8 vara PortB, 7 ? right?

det ända jag hitta ang PinB va på sida 105 i databladet för Tiny26 och där ser det ut om om det e samma som portB alltså att ben "8" är Bit "5".... eller?


edit:

Såhär tror jag då det skall se ut,

Kod: Markera allt

LOOP: 

sbis PinB, 5
cbi PortB, 3
sbic PinB, 5
sbi PortB, 3

rjmp LOOP
inte sant ;)
Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Inlägg av Kaggen »

Vet inte om vi kollar samma datablad. Jag kollar detta för Atiny26(L):
http://www.atmel.com/dyn/resources/prod ... oc1477.pdf

> om man säger enligt den koden så skulle ben 8 vara PortB, 7 ? right?

Nope! Du får inte anta att bit nummret på en port är det samma som vilket fysiskt ben den hör ihop med! PortB bit 7 skulle kunna lika gärna vara ben 100 på någon processor. Tabellen jag visade ovan är hur bitarna är organiserade i det programregister som motsvarar PortB. Har inget med det fysiska nummret på benet att göra.

Kolla databladet igen, det jag länka till ovan. Sida 2

Där ser du ju utmärkt PB5 (PortB bit 5). Se? Ben 8?

Har du ingen sådan översikt i ditt datablad?

Jag säger igen. Blanda inte ihop portar, bitar och de fysiska ben de motsvarar. Du skal alltid kolla i databladet vad som gäller. Fuskläsa med datablad är aj aj! :)

Mats

Edit:

> Såhär tror jag då det skall se ut... (kod borttagen)

Med beröm godkänt! :)

Skall tillägga att det finns många sätt att skriva kod för ovanstående exempel. Det du skrivit är ett sätt, sedan är det en smak och designsak hur man lägger upp koden.

Angående PortB och PinB, verkar det som om Atmel har olika beteckning på samma port beroende om man läser från eller skriver till den. PortB verkar användas för att sätta värden på de bitar som är satta som utgångar, medans PinB används för att läsa värdet på de bitar som är satta som ingångar. Någon mer AVR-kunnig programmerare kanske kan utveckla varför det är så.

Mats
Senast redigerad av Kaggen 8 januari 2006, 14:56:00, redigerad totalt 1 gång.
Användarvisningsbild
karlstedt
EF Sponsor
Inlägg: 966
Blev medlem: 14 oktober 2003, 16:55:23
Ort: Lund
Kontakt:

Inlägg av karlstedt »

Kapselns bennummer behöver aldrig nämnas i denna diskussion.
Använd istället deras funktion/namn så kommer missförstånden att minska avsevärt.
exos
Inlägg: 194
Blev medlem: 24 november 2005, 21:04:25

Inlägg av exos »

sorry man, bladade ihop det som du sa ja inte fick blanda ihop ;)

körde den koden på AVR´n det blev så fin så... släckt hela tiden till ja "håller inne" knappen då tänds den, när ja släpper då slocknar den,

skall försöka fixa så att vid en knapp tryck tänds den och vid nästa så släcks den....
Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Inlägg av Kaggen »

karlstedt:

Du har helt rätt. Jag antar att man kan skriva sbi PortB,PB3 istället för sbi PortB,3(har inte hunnit testa AVR-assembler än, men jag antar att PBx bitarna är definierade i nån include fil).

Detta är betydligt bättre programmeringssed, bl.a. eftersom man enklare kan hitta t.ex. beteckningen PB4 i databladet än PortB bit 4 eller ifall Atmel, föga troligt, beslutar att PB4 skall vara PortB bit 3.

Mats
exos
Inlägg: 194
Blev medlem: 24 november 2005, 21:04:25

Inlägg av exos »

YES!! fick ihop det och det fungera "ok"... denna koden

Kod: Markera allt

ledoff:
sbic PinB, 5  ;kollar om knappen inte är nertryckt isf hoppa över nästa
rjmp ledon   ;hoppar till ledon:
cbi PortB, 3  ;släcker LED´n
rjmp ledoff  ; börjar om från ledoff:

ledon:
sbic PinB, 5  ;kollar om knappen inte är nertryckt, isf hoppa över nästa
rjmp ledoff   ; hoppar till ledoff:
sbi PortB, 3  ; tänder LED´n
rjmp ledon   ;börjar om från ledon:
Detta fungerade fint, men jag märkte att det inte riktigt kännde av alla knapptryckningar jag gjorde, man typ fick trycka ett par gånger.. för att den skulle tända / släcka, man kanske skall ha nån form av delay så att den hinner känna efter typ...? känns som att det är nåt sånt..
Användarvisningsbild
karlstedt
EF Sponsor
Inlägg: 966
Blev medlem: 14 oktober 2003, 16:55:23
Ort: Lund
Kontakt:

Inlägg av karlstedt »

Ditt problem just nu är kontaktstuds. Vill du lösa det mjukvarumässigt så är en delay en bra idé. Känn av knappen, vid etta, kör delay, känn av knappen igen. Har den samma värde igen är det mycket sannolikt att det är en knapptryckning.
5ms brukar räcka för en vanlig tangentbordsströmställare av typen:
Bild
exos
Inlägg: 194
Blev medlem: 24 november 2005, 21:04:25

Inlägg av exos »

aha...ok det är sånna jag använder, skall testa detta. tackar
exos
Inlägg: 194
Blev medlem: 24 november 2005, 21:04:25

Inlägg av exos »

gjort en kod nu som typ strobbar 2st leds,
den ena LED´n blinkar 2gånger snabbt och sen lite delay sen den andra LED´n 2 gånger snabbt så håller det på så några gånger, men för att få detta att hända en massa gånger så har jag kopierat koden o lagt efter varanda vilket känns rätt onödigt, så jag skulle behöva en loop som typ kör koden säg 5 gånger ist för att ha massa kod.... men hittar inget direkt om loopar, samma gäller delay hittade dock en trevligt program som genererar delay, men nackdelen är ju den att man inte lär sig hur man får fram själva delayen...

här är koden

Kod: Markera allt


.org 0x0000
rjmp main

.include "c:\Program\Atmel\AVR Tools\AvrAssembler2\Appnotes\tn261def.inc"

main:
ldi r16,RAMEND    ;Stackpointer initialisieren 
out SPL,r16

ldi r16, 0xFF
out DDRB, r16

strobeoff:
sbic PinB, 2
rjmp strobeon
cbi PortB, 0
cbi PortB, 1
rjmp strobeoff

strobeon:
sbic PinB, 2
rjmp strobeoff
rcall blinksub
rjmp strobeon

blinksub:
sbi PortB, 0
rcall delayfast
cbi PortB, 0
rcall delayfast
sbi PortB, 0
rcall delayfast
cbi PortB, 0

rcall delayslow

sbi PortB, 1
rcall delayfast
cbi PortB, 1
rcall delayfast
sbi PortB, 1
rcall delayfast
cbi PortB, 1

rcall delayslow


; HÄR HADE JAG KOPIERAT KODEN EN MASSA GÅNGER
; för att få det att blinka flera gånger, men ist vill jag ha en loop...
; var hittar jag info om loopar ? 

rjmp strobeoff
ret

delayfast:

; ============================= 
;    delay loop generator 
;     60000 cycles:
; ----------------------------- 
; delaying 59994 cycles:
          ldi  R17, $63
WGLOOP0:  ldi  R18, $C9
WGLOOP1:  dec  R18
          brne WGLOOP1
          dec  R17
          brne WGLOOP0
; ----------------------------- 
; delaying 6 cycles:
          ldi  R17, $02
WGLOOP2:  dec  R17
          brne WGLOOP2
; ============================= 




ret

delayslow:

; ============================= 
;    delay loop generator 
;     200000 cycles:
; ----------------------------- 
; delaying 199998 cycles:
          ldi  R17, $06
WGLOOPP0:  ldi  R18, $37
WGLOOPP1:  ldi  R19, $C9
WGLOOPP2:  dec  R19
          brne WGLOOPP2
          dec  R18
          brne WGLOOPP1
          dec  R17
          brne WGLOOPP0
; ----------------------------- 
; delaying 2 cycles:
          nop
          nop
; ============================= 


ret

delayveryslow:

; ============================= 
;    delay loop generator 
;     800000 cycles:
; ----------------------------- 
; delaying 799995 cycles:
          ldi  R17, $5F
WGLOOP0s:  ldi  R18, $17
WGLOOP1s:  ldi  R19, $79
WGLOOP2s:  dec  R19
          brne WGLOOP2s
          dec  R18
          brne WGLOOP1s
          dec  R17
          brne WGLOOP0s
; ----------------------------- 
; delaying 3 cycles:
          ldi  R17, $01
WGLOOP3s:  dec  R17
          brne WGLOOP3s
; ----------------------------- 
; delaying 2 cycles:
          nop
          nop
; ============================= 

ret
Skriv svar