tid på blinkande diod
tid på blinkande diod
Hej! Sitter o försöker förstå mig på det här med programering av pic. Jag sitter med en pic 16f690 som jag har skrivit av ett program jag hittat på nätet. Det är en diod som ska blinka. Jag är totalt nybörjare så ha förståelse!! Jag har fått det att blinka men jag skulle vilja ändra hur snabt det blinkar. Jag förstår inte hur jag ändrar den.
STATUS equ 0x03
portc equ 0x07
var1 equ 0x20
var2 equ 0x30
trisc equ 0x87
RPO equ 0x05
org 0x00
goto init
Wait movlw 0xff
movwf var2
loop2 movlw 0xff
movwf var1
loop1 decfsz var1,1
goto loop1
decfsz var2,1
goto loop2
return
init clrw
movwf portc
bsf STATUS,RPO
movwf trisc
bcf STATUS,RPO
main bsf portc,0
call Wait
bcf portc,0
call Wait
goto main
end
Någon som kan tipsa mig hur jag kan ändra tiden på den här koden eller är det så att det inte går??
STATUS equ 0x03
portc equ 0x07
var1 equ 0x20
var2 equ 0x30
trisc equ 0x87
RPO equ 0x05
org 0x00
goto init
Wait movlw 0xff
movwf var2
loop2 movlw 0xff
movwf var1
loop1 decfsz var1,1
goto loop1
decfsz var2,1
goto loop2
return
init clrw
movwf portc
bsf STATUS,RPO
movwf trisc
bcf STATUS,RPO
main bsf portc,0
call Wait
bcf portc,0
call Wait
goto main
end
Någon som kan tipsa mig hur jag kan ändra tiden på den här koden eller är det så att det inte går??
Du kan kalla på väntloopen två gånger mellan lysdiod av/på
Vill du ha kortare tid kan du ändra på värdena i funktionen "wait" till något lägre värde.
Kod: Markera allt
main bsf portc,0 ;här slås lysdioden på.
call Wait
;Här kan du lägga till fler "call Wait"
bcf portc,0 ;här slås lysdioden av.
call Wait
;Här kan du lägga till fler "call Wait"
goto main
Vill du ha kortare tid kan du ändra på värdena i funktionen "wait" till något lägre värde.
Kod: Markera allt
; Följande radet är BIG NO NO och MYCKET dålig programmeringsstil!
; Man använder en include-fil med alla dessa definitioner i! Finns med i MPLAB!
STATUS equ 0x03
portc equ 0x07
var1 equ 0x20
var2 equ 0x30
trisc equ 0x87
RPO equ 0x05
; Slut på kassa raderna
org 0x00 ; OK, absolut mode, inte bästa vägen att gå men det får vara just nu
goto init ; Ganska logisk
Wait ; Detta är en 'label', i detta fall är det namnet på en rutin. Gissa vad den gör... (tips: läs namnet)
movlw 0xff ; Laddar 0xFF in i W, ändar värdet = ändra hur lång tid Wait tar
movwf var2 ; Kopierar W till var2 (var2 = 0xFF alltså)
loop2 ; En label
movlw 0xff ; Ytterligare ett värde som bestämmer tiden
movwf var1
loop1 ; Också en label
decfsz var1,1 ; Räkna ner var1
goto loop1 ; Om var1 = 0 hoppas denna över
decfsz var2,1 ; Räkna ner var2
goto loop2 ; Om var2 = 0 hoppas denna över
return ; OK, klart här, hoppa tillbaka till vem som nu än kallade på detta
init ; Ännu en label
clrw
movwf portc
bsf STATUS,RPO
movwf trisc
bcf STATUS,RPO
main ; Och en label mer
bsf portc,0 ; Slå på PORTC,0
call Wait ; Vänta en viss tid
bcf portc,0 ; Slå av PORTC,0
call Wait Vänta en viss tid
goto main ; Hoppla, börja om på main... igen och igen och igen
Har försedd med kommentarer som borde ge lite ledtrådar.
Här är en alternativ kod för 16F690.
Den är portad från 16F628A reakt av, testad i MPSIM
men inte kört på riktig hårdvara, men jag tror att det fungerar.
Den är portad från 16F628A reakt av, testad i MPSIM
men inte kört på riktig hårdvara, men jag tror att det fungerar.
Kod: Markera allt
;**********************************************************************
; Enkelt blink-a-led, 16F690. *
;**********************************************************************
; Filer : P16F690.INC
; 16F690.LNK (läggs till som "linker Script" i projketet
;**********************************************************************
list p=16f690
#include <p16f690.inc>
__CONFIG _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _HS_OSC
Boot CODE 0x000 ; processor reset vector
goto start ; go to beginning of program
INT_VECTOR CODE 0x004 ; interrupt vector location
goto isr_routine ; goto main interrupt service routine.
;***************************************************************
MAIN CODE
start
banksel ansel
clrf ansel ; Stäng av alla analoga funktioner.
banksel trisa
clrf trisa
clrf trisb
clrf trisc ; Alla pinnar = utgångar.
banksel t1con
movlw b'00110001'
movwf t1con ; Se datablad, kap om TMR1...
; Ändra pre-scaler för olika blinkhastighet.
; T.ex b'00100001' ovan.
; -- = pre-scaler biterna. Se databladet !
banksel pie1
movlw b'00000001'
movwf pie1 ; Enable avbrott från TMR1.
banksel intcon
bsf intcon, peie
bsf intcon, gie ; Enable avbrott generellt...
banksel porta
clrf porta ; Starta med ett känt värde i PORTA...
loop
goto loop ; Vänta på avbrott...
;***************************************************************
ISR_ROUTINE CODE
isr_routine
; OK, Timer1 har "snurrat runt" !
banksel porta
comf porta ; Blinka med hela PORTA!
; Notera att detta blinkar med alla pinnar i PORTA
; som är vanliga digitala I/O. Så t.ex inte RA3, den är MCLR.
banksel pir1
bcf pir1, tmr1if ; återställ avbrotts flagga.
; Klart, returnera och vänta på nästa avbrott från Timer1...
retfie
end
Hej!
Jag har nu läst era svar och jag har provat att ändra lite som Swech skriver.
Jag provade att ändra Var2 equ 0x30 till 0x60 men jag såg ingen skillnad. Jag provade också att skriva ett tal som han skrev 0-255 men ingen skilnad. Därimot så ändrade jag den till 0x0c och då gick den fortare och 0x0f gick den saktare. Varför fungerade inte den han skrev?? vad är det jag ändrade?? Jag har ju fåt funktionen som jag eftersökte men jag vill ju veta vad jag har gjort för framtida projekt.
Jag har nu läst era svar och jag har provat att ändra lite som Swech skriver.
Jag provade att ändra Var2 equ 0x30 till 0x60 men jag såg ingen skillnad. Jag provade också att skriva ett tal som han skrev 0-255 men ingen skilnad. Därimot så ändrade jag den till 0x0c och då gick den fortare och 0x0f gick den saktare. Varför fungerade inte den han skrev?? vad är det jag ändrade?? Jag har ju fåt funktionen som jag eftersökte men jag vill ju veta vad jag har gjort för framtida projekt.
- Swech
- EF Sponsor
- Inlägg: 4750
- Blev medlem: 6 november 2006, 21:43:35
- Ort: Munkedal, Sverige (Sweden)
- Kontakt:
ops.. ja där ser man..
läser man för fort och är rostig på pic så kan det bli så.
I AVR världen använder man EQU för konstanter och mycket sällan
för adresser.. därav mitt misstag
Du kan alltså justera hastigheten genom att ändra 0xff till ett tal mellan
0 och 255.
Det är dock som övriga säger inget vidare bra sätt att programmera på.
läser man för fort och är rostig på pic så kan det bli så.
I AVR världen använder man EQU för konstanter och mycket sällan
för adresser.. därav mitt misstag
Kod: Markera allt
Wait movlw 0xff - ändrar du här istället till 0.255 så blinkar det snabbare
movwf var2
loop2 movlw 0xff
movwf var1
loop1 decfsz var1,1
goto loop1
decfsz var2,1
goto loop2
return
0 och 255.
Det är dock som övriga säger inget vidare bra sätt att programmera på.
Ingen som helst skillnad på AVR och PIC i det avseendet. Normalt sett så använder man EQU för fasta adresser och konstanter. Sedan kan man i vissa sammanhang använda EQU även för den konstanta adressen till en variabel, men det finns andra sätt att göra det på.Swech skrev:I AVR världen använder man EQU för konstanter och mycket sällan
för adresser.. därav mitt misstag
> läser man för fort och är rostig på pic så kan det bli så.
> I AVR världen använder man EQU för konstanter och mycket sällan
> för adresser..
För PIC så används EQU *enbart* för att definiera symboliska konstanter !
(Sen att dessa konstanter ibland/ofta används som minnesadresser är en helt annan sak...)
> ok då vad det som jag trode att equ vad en adress.
Det är det alltså inte. EQU definier en konstant (som du sen använder som
en adress, men det vet inte EQU ett smack om...)
Tron att EQU definierar/reserverar en minnesadress är ett av de vanligaste
missförstånden bland nybörjare, så ta det inte personligt...
Kommandot som däremot verkligen reserverar minne heter RES.
> Om man tittar på den koden jag skrev, vad är det som bestämer tiden på blinkningen där.
Värdena som laddas till Var2 och Var1 med MOVLW/MOVWF i Wait rutinen.
Ett enklare sätt att skriva Wait är :
> Den koden som sodjan skrev, var bestäms tiden där?
Främst inställningen av Timer1 prescaler. Sedan så låter jag Timer1
bara snurra runt (alltså 2**16) steg, så där finns det inte mycket att göra,
men det var inte avsikten heller. Det var därför jag skrev:
> I AVR världen använder man EQU för konstanter och mycket sällan
> för adresser..
För PIC så används EQU *enbart* för att definiera symboliska konstanter !
(Sen att dessa konstanter ibland/ofta används som minnesadresser är en helt annan sak...)
> ok då vad det som jag trode att equ vad en adress.
Det är det alltså inte. EQU definier en konstant (som du sen använder som
en adress, men det vet inte EQU ett smack om...)
Tron att EQU definierar/reserverar en minnesadress är ett av de vanligaste
missförstånden bland nybörjare, så ta det inte personligt...

Kommandot som däremot verkligen reserverar minne heter RES.
> Om man tittar på den koden jag skrev, vad är det som bestämer tiden på blinkningen där.
Värdena som laddas till Var2 och Var1 med MOVLW/MOVWF i Wait rutinen.
Ett enklare sätt att skriva Wait är :
Kod: Markera allt
Wait movlw 0xff ; Ladda startvärde till Var2
movwf var2
loop decfsz var1,1 ; Räkna ner Var1 (alltid 256 varv !)
goto loop
decfsz var2,1 ; Räkna ner Var2...
goto loop ; Ej 0, kör ett varv till.
return ; Klart...
Främst inställningen av Timer1 prescaler. Sedan så låter jag Timer1
bara snurra runt (alltså 2**16) steg, så där finns det inte mycket att göra,
men det var inte avsikten heller. Det var därför jag skrev:
Kod: Markera allt
...
; Ändra pre-scaler för olika blinkhastighet.
; T.ex b'00100001' ovan.
; -- = pre-scaler biterna. Se databladet !
...
Här är en version av din kod som är uppsnyggad, rättad och kommenterad.
Kod: Markera allt
;**********************************************************************
; Enkelt blink-a-led, 16F690. *
;**********************************************************************
; Filer : P16F690.INC
; 16F690.LNK (läggs till som "linker Script" i projektet
;**********************************************************************
list p=16f690
#include <p16f690.inc>
__CONFIG _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _HS_OSC
;**********************************************************************
; Definition av konstanter och reservera variabler
delay EQU h'8F' ; Startvärde för wait loopen.
variabler UDATA_SHR ; Lägg variabler i "shared memory"...
var1 RES 1 ; Reservera 2 variabler för Wait loopen.
var2 RES 2 ; - " -
;**********************************************************************
; Här börjar själva koden.
Boot CODE h'0000' ; Starta allt på adress h'0000'
clrw ; Nolla W
movwf portc ; Nolla PORTC
banksel trisc ; Byt bank
movwf trisc ; Nolla TRISC
banksel ansel ; Byt bank igen...
clrf ansel ; Sätt alla pinnar som digitala I/O pinnar.
banksel portc ; Byt tillbaka till bank0 igen...
main_loop
bsf portc,0 ; Sätt RC0 = "1"
call Wait
bcf portc,0 ; Sätt RC0 = "0"
call Wait
goto main_loop ; Å så kör vi en sväng till...
Wait
movlw delay ; Ladda startvärde till Var2
movwf var2
wait_loop
nop ; Bara för att få ett bra "blink"...
nop ; - " -
nop ; - " -
decfsz var1, f ; Räkna ner Var1 (alltid 256 varv !)
goto wait_loop ; En gång till tills var1 = 0
decfsz var2, f ; Räkna ner Var2...
goto wait_loop ; Ej 0, kör ett varv till.
return ; Klart...
end