Forum » Elektrotehnika in elektronika » PIC 16f84A - utripanje
PIC 16f84A - utripanje
upirna ::
Sem začetnik v programiranju PICov. Za nalogo sem si postavil utripanje ledice, ampak mi preprosto ne rata. Ne vem, kje je napaka zato prilagam kodo.
list p=16f84a
#include p16f84a.inc
__CONFIG _WDT_OFF & _CP_OFF & _PWRTE_ON & _XT_OSC
;set I/O ports
bsf STATUS,RP0
movlw b'00000000'
movwf TRISB
bcf STATUS,RP0
;set values
PROGRAM
movlw b'00000000'
movwf PORTB
call PAVZA
call PAVZA
movlw b'00000001'
movwf PORTB
call PAVZA
call PAVZA
goto PROGRAM
;podprogram
PAVZA
STEVEC EQU 0x0C
movlw 255
movwf STEVEC
ZANKA
decfsz STEVEC,1
goto ZANKA
return
END
list p=16f84a
#include p16f84a.inc
__CONFIG _WDT_OFF & _CP_OFF & _PWRTE_ON & _XT_OSC
;set I/O ports
bsf STATUS,RP0
movlw b'00000000'
movwf TRISB
bcf STATUS,RP0
;set values
PROGRAM
movlw b'00000000'
movwf PORTB
call PAVZA
call PAVZA
movlw b'00000001'
movwf PORTB
call PAVZA
call PAVZA
goto PROGRAM
;podprogram
PAVZA
STEVEC EQU 0x0C
movlw 255
movwf STEVEC
ZANKA
decfsz STEVEC,1
goto ZANKA
return
END
[to sporočilo bo spremenil upirna, kadar bo to njemu pasalo]
snow ::
call ZANKA traja nekje 1 ms na 4MHz oscilatorju.
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins
upirna ::
snow, kaj hočeš povedat... call ZANKA namreč ni nikjer v kodi
[to sporočilo bo spremenil upirna, kadar bo to njemu pasalo]
Highlag ::
Pozkusi takole:
Koda:
PROCESSOR 16f84A
#include "p16f84A.inc"
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
Cblock 0X0C ; Začetek RAM-a
HIcnt ; višji bajt argumenta makrota
LOcnt ; nižji bajt argumenta makrota
LOOPcnt ; spremenljivka makrota
Temp
endc ; konec spemenljivk
ORG 0x00 ; reset vektor
goto Main ; skok na Main
ORG 0x04 ; interupt vektor
goto Main ; skok na Main
include "pause.inc" ; Asembler ob pretvarjanju doda kodo makrota pause.inc
Main
banksel TRISA ; izbira banke kjer se nahaja register TRISA
clrf TRISA ; register TRISA je napolnjen z 00000000 -> A=output
banksel PORTA ; izbira banke, kjer se nahaja register PORTA
Loop
movlw b'00001000' ; 00001000->W
Loop1
movwf PORTA ; W ->PORTA
movwf Temp ; W -> temp
rrf Temp, 1 ; Rotate right through carry
; prižge in počaka 0.5s
pausems .1000 ; klic makrota z parametrom -> hočemo 0.5s zamika
movlw 0x00 ; 0 -> W
movwf PORTA ; W -> PORTA
pausems .1000 ; klic makrota z parametrom -> hočemo 0.5s zamika
movf Temp, 0 ; Temp -> W
goto Loop1 ; skok nazaj na Loop
End
konec kode.
Rabiš še pause.inc datoteko v isti mapi:
Koda:
; Za 1 minuto (59,904sekund) mora biti argument arg1 = .59904 (to je decimalno)
;
;
pausems macro arg1
local Loop1
local dechi
local Delay1ms
local Loop2
local Konec
movlw high arg1 ; Move literal to W register Višji bajt argumenta arg1 gre v HIcnt
movwf HIcnt ; Move W register to HIcnt
movlw low arg1 ; Move literal to W register Nižji bajt argumenta arg1 gre v LOcnt
movwf LOcnt ; Move W register to LOcnt
Loop1
;Zmanjšuje HIcnt in LOcnt za določeno število
;in nato pokliči podprogram Delay1ms
movf LOcnt, f ; Move conents of Locnt
btfsc STATUS, Z ; Bittest skip if clear testira bit Z status registra Z = 1 če je rezultat računske operacije 0
goto dechi ; če rezultat operacije ni 0 skoči sem kar pomeni, da še ni prišel na 0 (v tem primeru)
call Delay1ms ; Call ->kliče podprogram Delay1ms ko podprogram zaključi se izvrši naslednja vrstica
decf LOcnt, f ; Decrement LOcnt register rezultat shrani v LOcnt
goto Loop1 ; skok nazaj
dechi
movf HIcnt, f
btfsc STATUS, Z
goto Konec
call Delay1ms
decf HIcnt, f
decf LOcnt, f
goto Loop1
Delay1ms:
movlw .100 ; Move literal to W 100->W (0xFA)
movwf LOOPcnt ; Move W to LOOPcnt
Loop2:
nop ; nooperation
nop ; nooperation
nop ; nooperation
nop ; nooperation
nop ; nooperation
nop ; nooperation
nop ; nooperation
decfsz LOOPcnt, f ; Decrement LOOPcnt skip if zero LOOPcnt=LOOPcnt-1 odšteje 1 od vrednosti registra LOOPcnt
goto Loop2 ; Če je LOOPcnt=0 potem ta stavek spusti saj je 1ms minila
return ; skok nazaj na vrstico 18
Konec
endm
Konec kode.
Koda:
PROCESSOR 16f84A
#include "p16f84A.inc"
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
Cblock 0X0C ; Začetek RAM-a
HIcnt ; višji bajt argumenta makrota
LOcnt ; nižji bajt argumenta makrota
LOOPcnt ; spremenljivka makrota
Temp
endc ; konec spemenljivk
ORG 0x00 ; reset vektor
goto Main ; skok na Main
ORG 0x04 ; interupt vektor
goto Main ; skok na Main
include "pause.inc" ; Asembler ob pretvarjanju doda kodo makrota pause.inc
Main
banksel TRISA ; izbira banke kjer se nahaja register TRISA
clrf TRISA ; register TRISA je napolnjen z 00000000 -> A=output
banksel PORTA ; izbira banke, kjer se nahaja register PORTA
Loop
movlw b'00001000' ; 00001000->W
Loop1
movwf PORTA ; W ->PORTA
movwf Temp ; W -> temp
rrf Temp, 1 ; Rotate right through carry
; prižge in počaka 0.5s
pausems .1000 ; klic makrota z parametrom -> hočemo 0.5s zamika
movlw 0x00 ; 0 -> W
movwf PORTA ; W -> PORTA
pausems .1000 ; klic makrota z parametrom -> hočemo 0.5s zamika
movf Temp, 0 ; Temp -> W
goto Loop1 ; skok nazaj na Loop
End
konec kode.
Rabiš še pause.inc datoteko v isti mapi:
Koda:
; Za 1 minuto (59,904sekund) mora biti argument arg1 = .59904 (to je decimalno)
;
;
pausems macro arg1
local Loop1
local dechi
local Delay1ms
local Loop2
local Konec
movlw high arg1 ; Move literal to W register Višji bajt argumenta arg1 gre v HIcnt
movwf HIcnt ; Move W register to HIcnt
movlw low arg1 ; Move literal to W register Nižji bajt argumenta arg1 gre v LOcnt
movwf LOcnt ; Move W register to LOcnt
Loop1
;Zmanjšuje HIcnt in LOcnt za določeno število
;in nato pokliči podprogram Delay1ms
movf LOcnt, f ; Move conents of Locnt
btfsc STATUS, Z ; Bittest skip if clear testira bit Z status registra Z = 1 če je rezultat računske operacije 0
goto dechi ; če rezultat operacije ni 0 skoči sem kar pomeni, da še ni prišel na 0 (v tem primeru)
call Delay1ms ; Call ->kliče podprogram Delay1ms ko podprogram zaključi se izvrši naslednja vrstica
decf LOcnt, f ; Decrement LOcnt register rezultat shrani v LOcnt
goto Loop1 ; skok nazaj
dechi
movf HIcnt, f
btfsc STATUS, Z
goto Konec
call Delay1ms
decf HIcnt, f
decf LOcnt, f
goto Loop1
Delay1ms:
movlw .100 ; Move literal to W 100->W (0xFA)
movwf LOOPcnt ; Move W to LOOPcnt
Loop2:
nop ; nooperation
nop ; nooperation
nop ; nooperation
nop ; nooperation
nop ; nooperation
nop ; nooperation
nop ; nooperation
decfsz LOOPcnt, f ; Decrement LOOPcnt skip if zero LOOPcnt=LOOPcnt-1 odšteje 1 od vrednosti registra LOOPcnt
goto Loop2 ; Če je LOOPcnt=0 potem ta stavek spusti saj je 1ms minila
return ; skok nazaj na vrstico 18
Konec
endm
Konec kode.
Never trust a computer you can't throw out a window
zcetrt ::
Ali bi ga rad že sedaj odvrnil od programiranja? Kakšne komplikacije...
Že nekaj časa sem sicer izven assemblerja, ampak poišči funkcijo stopwatch v MPlabu in poštopaj, koliko časa ti traja en utrip. Kajti meni se zdi, da ti vse skupaj traja odločno premalo, da bi kaj opazil. (od oka sem na hitro računal precej manj kot 1ms, da bi kaj videl pa rabiš kakih 100ms recimo).
Kakšen oscilator imaš?
Že nekaj časa sem sicer izven assemblerja, ampak poišči funkcijo stopwatch v MPlabu in poštopaj, koliko časa ti traja en utrip. Kajti meni se zdi, da ti vse skupaj traja odločno premalo, da bi kaj opazil. (od oka sem na hitro računal precej manj kot 1ms, da bi kaj videl pa rabiš kakih 100ms recimo).
Kakšen oscilator imaš?
4.
TESKAn ::
Highlag, ti pa znaš zakomplicirat.
Je pa že snow lepo povedal, prehitro ti preklaplja, tam z ene 2kHz, če imaš 4 MHz oscilator, torej ledika bi že utripala, samo vidiš tega ne:).
Da bi delalo, kot more, moreš podaljšat pavzo - recimo narediš še podprogram, npr. PAVZA1, ki ti 255 - krat požene PAVZA, potem pa še tretji podprogram, PAVZA2, ki ti bo tam ene 16 - krat poklical PAVZA1 in ti bo naredilo ~1sec zakasnitve. V glavnem programu potem pokličeš PAVZA2.
Je pa že snow lepo povedal, prehitro ti preklaplja, tam z ene 2kHz, če imaš 4 MHz oscilator, torej ledika bi že utripala, samo vidiš tega ne:).
Da bi delalo, kot more, moreš podaljšat pavzo - recimo narediš še podprogram, npr. PAVZA1, ki ti 255 - krat požene PAVZA, potem pa še tretji podprogram, PAVZA2, ki ti bo tam ene 16 - krat poklical PAVZA1 in ti bo naredilo ~1sec zakasnitve. V glavnem programu potem pokličeš PAVZA2.
Uf! Uf! Je rekel Vinetou in se skril za skalo,
ki jo je prav v ta namen nosil s seboj.
ki jo je prav v ta namen nosil s seboj.
upirna ::
hm, sam zdej pa dobim error ker nimam pause.inc. A bi mi lahko lepo prosm poslal na mail
uros.pirnat{afna}gmail.com
uros.pirnat{afna}gmail.com
[to sporočilo bo spremenil upirna, kadar bo to njemu pasalo]
TESKAn ::
Lej, pusti ti že napisane programčke nekje. Lepo malo pomodificiraj svojo PAVZA podrutino, pa bo lepo utripalo. Sej lahko si sam zračunaš, koliko časa bo zakasnitev:
- za strojni cikel deliš frekv. oscilatorja z 4 (recimo 4 MHz osc ti da 1 us za en strojni cikel)
- koliko ciklov porabi kak ukaz, ti pa v datasheetu piše - večina jih traja en cikel, vejitveni ukazi dva.
Drugače pa evo tle ena koda, ki mi dela cirka 1s pavzo
spremenljivke so
longdelayc1
longdelayc2
longdelayc3
ti samo skopiraj to kodo v svoj program, definiraj te tri spremenljivke in namesto call PAVZA dej call longdelay enkrat.
longdelay
movlw 0x08
movwf longdelayc1
ldelay1
movlw 0xFF
movwf longdelayc2
ldelay2
movlw 0xFF
movwf longdelayc3
ldelay3
decfsz longdelayc3,f
goto ldelay3
decfsz longdelayc2,f
goto ldelay2
decfsz longdelayc1,f
goto ldelay1
return
p.s.:pa pazi, kje deklariraš spremenljivke...se mi je zgodilo, da sem deklariral spremenljivko in jo potem počistil...problem je bil, ker je imela naslov programskega števca, jaz pa potem gledam, zakaj za vraga se mi PIC resetira.
- za strojni cikel deliš frekv. oscilatorja z 4 (recimo 4 MHz osc ti da 1 us za en strojni cikel)
- koliko ciklov porabi kak ukaz, ti pa v datasheetu piše - večina jih traja en cikel, vejitveni ukazi dva.
Drugače pa evo tle ena koda, ki mi dela cirka 1s pavzo
spremenljivke so
longdelayc1
longdelayc2
longdelayc3
ti samo skopiraj to kodo v svoj program, definiraj te tri spremenljivke in namesto call PAVZA dej call longdelay enkrat.
longdelay
movlw 0x08
movwf longdelayc1
ldelay1
movlw 0xFF
movwf longdelayc2
ldelay2
movlw 0xFF
movwf longdelayc3
ldelay3
decfsz longdelayc3,f
goto ldelay3
decfsz longdelayc2,f
goto ldelay2
decfsz longdelayc1,f
goto ldelay1
return
p.s.:pa pazi, kje deklariraš spremenljivke...se mi je zgodilo, da sem deklariral spremenljivko in jo potem počistil...problem je bil, ker je imela naslov programskega števca, jaz pa potem gledam, zakaj za vraga se mi PIC resetira.
Uf! Uf! Je rekel Vinetou in se skril za skalo,
ki jo je prav v ta namen nosil s seboj.
ki jo je prav v ta namen nosil s seboj.
Zgodovina sprememb…
- spremenil: TESKAn ()
upirna ::
Tokrat hvala kolikor je mikrosekund potrebnik za tole :D
[to sporočilo bo spremenil upirna, kadar bo to njemu pasalo]
snow ::
Drugače si lahko pa tudi z MPLABom pomagaš, da ugotoviš koliko časa traja kakšen del tvoje kode.
Dobro si je tudi pogledati (mislim da v simulator listing) koliko ciklov porabi določena koda (kar lahko preračunaš v čas).
Kako pa peš oceniš:
Vsak cikel se izvede v 4ih taktih, se pravi če imaš 4MHz kvarc, traja en cikel 1 mikrosekundo.
Vsi ukazi trajajo 1 cikel, razen kakšnih skokov (call, goto, return).
Tvoja delay koda pa naredi 255x goto in decfsz (2 + 1) ~ 755 mikrosekund.
Ker kličeš zadevo 2x je to nekje 1,5 milisekunde.
Če pa imaš dvojno zanko pa ta porabi nekje 255x255x3 mikrosekund (groba ocena!).
Dobro si je tudi pogledati (mislim da v simulator listing) koliko ciklov porabi določena koda (kar lahko preračunaš v čas).
Kako pa peš oceniš:
Vsak cikel se izvede v 4ih taktih, se pravi če imaš 4MHz kvarc, traja en cikel 1 mikrosekundo.
Vsi ukazi trajajo 1 cikel, razen kakšnih skokov (call, goto, return).
Tvoja delay koda pa naredi 255x goto in decfsz (2 + 1) ~ 755 mikrosekund.
Ker kličeš zadevo 2x je to nekje 1,5 milisekunde.
Če pa imaš dvojno zanko pa ta porabi nekje 255x255x3 mikrosekund (groba ocena!).
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins
Highlag ::
Ne vem kaj je tako kompleksnega v moji kodi.
Pausems dobi argument, ga razdeli in odšteje tiste cikle. Ko konča zaključi.
Ker sprejme zakasnitev dolgo tudi 1s izgleda malo bolj kompleksno samo ko kodo preštudiraš ni noben bav-bav.
Pausems dobi argument, ga razdeli in odšteje tiste cikle. Ko konča zaključi.
Ker sprejme zakasnitev dolgo tudi 1s izgleda malo bolj kompleksno samo ko kodo preštudiraš ni noben bav-bav.
Never trust a computer you can't throw out a window
snow ::
Za začetek s PICi in asm programiranja je mal dolga... sploh če se še učiš ukazov.
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins
Tutankhamun ::
Kok velik kode :). Zakaj pa ne napises zakasnitvene rutine s pomocjo Timer0. Pa se kej lahko umes delas. Pa koda bo veliiiiiik krajša.
AMD Phenom QUAD 9950 Black Edition, 8GB
snow ::
Ni slaba ideja, ampak moraš prvo vedet kaj so interrupti. In ti niso ravno lekcija 1.
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins
zcetrt ::
V MPlabu je funkcija stopwatch. V kodo postaviš z mišakom breakpoints in poženeš simulator. Na prvem breakpointu se ti ustavi, daš štoparico na nič in poženeš simulator naprej, pride do druge (ali prve. če je narejen loop) in odčitaš čas trajanje. Zelo uporabna reč.
Bi pa rad opozoril, da ti oscilatorji niso primerni za uro, saj so kar pošteno netočni...
Bi pa rad opozoril, da ti oscilatorji niso primerni za uro, saj so kar pošteno netočni...
4.
Tutankhamun ::
evo za približn 1 sekundo.
Sam ne me sprasvt zakaj so umes prazne vrstice pol pa zgleda tko velik
#include <p16f84a.inc> Delay equ 0x0C ;//Memory Location ;//Reset Vector org 0 goto InitPrg ;//Interrupt Vector org 4 bcf INTCON, T0IF decf Delay, F btfss STATUS, Z ;//if Delay is 0 retfie ;//No, return from Interrupt movlw d'16' ;//Yes, set Delay movwf Delay movlw 1 xorwf PORTB, F ;//toggle bit 0 on portB retfie ;//return from Interrupt InitPrg movlw d'16' ;//set Delay movwf Delay clrf PORTB ;//clear PortB bsf STATUS, RP0 ;//Bank 1 (TRISB REGISTER, OPTION REGISTER) clrf TRISB ;//output pins ;//Enable Timer0 Interrupt bsf INTCON, T0IE ;//timer0 bsf INTCON, GIE ;//global interrupt ;//enable Timer0, prescaler is 1:256 bcf OPTION_REG, T0CS ;//Fosc bcf OPTION_REG, PSA ;//prescaler bcf STATUS, RP0 ;//Bank 0 (PORTB REGISTER) Loop goto Loop ;//endless loop end
Sam ne me sprasvt zakaj so umes prazne vrstice pol pa zgleda tko velik
AMD Phenom QUAD 9950 Black Edition, 8GB
ql000 ::
C-jevska varianta (CCS PIC C Compiler):
Samo v razmislek!
#include <pic16f84> #use delay(clock=4000000) void main() { { output_low(RB0); // ce je ledika na B0 delay_ms(500); output_high(RB0); } while(TRUE); }
Samo v razmislek!
Zgodovina sprememb…
- spremenil: ql000 ()
Tutankhamun ::
ql000 tole pa ne bo lih delal :). Še en delay ti manjka ko nastavš RB0 na high. Edin če bi namest output_high in output_low, samo spremenu v
RB0 ^= 1. Mislm da je ^ v Cju XOR, da samo spreminjaš zadnji bit.
RB0 ^= 1. Mislm da je ^ v Cju XOR, da samo spreminjaš zadnji bit.
AMD Phenom QUAD 9950 Black Edition, 8GB
ql000 ::
@Tutankhamun: a si spregledal
?
Drugače se pa strinjam z XOR, samo zakaj komplicirat že pri lediki?
delay_ms(500);
?
Drugače se pa strinjam z XOR, samo zakaj komplicirat že pri lediki?
Tutankhamun ::
ql000 nism spregledu, ampak ti edn še manka. Tvoj program se tkole izvaja.
output_low(RB0);
delay_ms(500);
output_high(RB0);
output_low(RB0);
delay_ms(500);
output_high(RB0);
output_low(RB0);
delay_ms(500);
output_high(RB0);
Med Output High pa output low ni nobene pauze. Ce bo upirna gledu LEDico, ne bo nič utripala, ker bo na izhodu samo en kratek impulzek.
XOR ni kompliciranje. Kompliciranje je tole, koje use podvojen.
;set values
PROGRAM
movlw b'00000000'
movwf PORTB
call PAVZA
call PAVZA
movlw b'00000001'
movwf PORTB
call PAVZA
call PAVZA
goto PROGRAM
Tko se pa znebiš polovico kode
;set values
PROGRAM
movlw 1
xorwf PORTB, F ;//toggle bit 0 on portB
call PAVZA
call PAVZA
goto PROGRAM
output_low(RB0);
delay_ms(500);
output_high(RB0);
output_low(RB0);
delay_ms(500);
output_high(RB0);
output_low(RB0);
delay_ms(500);
output_high(RB0);
Med Output High pa output low ni nobene pauze. Ce bo upirna gledu LEDico, ne bo nič utripala, ker bo na izhodu samo en kratek impulzek.
XOR ni kompliciranje. Kompliciranje je tole, koje use podvojen.
;set values
PROGRAM
movlw b'00000000'
movwf PORTB
call PAVZA
call PAVZA
movlw b'00000001'
movwf PORTB
call PAVZA
call PAVZA
goto PROGRAM
Tko se pa znebiš polovico kode
;set values
PROGRAM
movlw 1
xorwf PORTB, F ;//toggle bit 0 on portB
call PAVZA
call PAVZA
goto PROGRAM
AMD Phenom QUAD 9950 Black Edition, 8GB
Zgodovina sprememb…
- spremenil: Tutankhamun ()
snow ::
utripanje ledice je super primer za pokazat delovanje xor.
in ja... tam zgoraj manjka en delay.
in ja... tam zgoraj manjka en delay.
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | Pic- zamik za 24hOddelek: Elektrotehnika in elektronika | 998 (910) | MeGreat |
» | PIC18F4550 in ds18s20Oddelek: Elektrotehnika in elektronika | 2002 (1681) | snow |
» | programiranje PIC..c++ ali zbirnik?Oddelek: Programiranje | 1737 (1629) | Highlag |
» | programiranje procesorja (strani: 1 2 3 4 … 8 9 10 11 )Oddelek: Elektrotehnika in elektronika | 36830 (26231) | icek |
» | ideja: koda za razne mikrokontrolerje na enem mestuOddelek: Elektrotehnika in elektronika | 3703 (3180) | neoto |