Sida 1 av 2
Delayrutinen stämmer inte i verkligheten..
Postat: 13 februari 2007, 17:43:32
av JimmyAndersson
PIC-kretsen är en PIC18F1320.
Har gjort en delayrutin som enligt MPLAB SIM tar 49,999ms att utföra på en PIC som kör i 8MHz.
Denna rutin körs mellan varje kommando som matar ut ett tecken på en LCD-display.
Problemet är att det dröjer nästan en sekund mellan varje tecken när jag kör koden i verkligheten.
Koden som ger en oscillator-frekvens på 8MHz:
Kod: Markera allt
; OSCILLATOR FREQ 8MHz
bcf OSCCON, IDLEN
bsf OSCCON, IRCF2
bsf OSCCON, IRCF1
bsf OSCCON, IRCF0
bsf OSCCON, SCS1
Config-delen för oscillatorn ser ut såhär:
Delay-rutinen:
Kod: Markera allt
;************************************************************
; Delay50ms -- 50ms = 100'000 cycles @ 8MHz
dly50ms_vars udata_acs
CNT4 res 1
CNT5 res 1
CNT6 res 1
dly50ms_code CODE
delay_50ms
movlw 0x04
movwf CNT4
movlw 0x06
movwf CNT5
movlw 0x10
movwf CNT6
dly50ms_loop
decfsz CNT5
goto dly50ms_loop
movlw 0x07
movwf CNT5
decfsz CNT4
goto dly50ms_loop
decfsz CNT6
goto dly50ms_loop
nop
return
;************************************************************
Ser det rätt ut så långt?
Kan man lita på att tiden som MPLAB SIM ger stämmer i verkligheten?
Postat: 13 februari 2007, 18:51:26
av RasmusB
Jag tycker det ser ut att stämma. Ögnade igenom databladet lite snabbt och det ser ut som att oscillatorn är rätt konfigurerad också.
Säger simulatorn att det tar så lång tid så borde det stämma. Jag skulle gissa att oscillatorn går i fel hastighet. Gör du något mer med de inställningarna än du klistrat in här?
Postat: 13 februari 2007, 21:57:57
av JimmyAndersson
"Gör du något mer med de inställningarna än du klistrat in här?"
Inget som har med några inställningar av själva oscillatorn att göra.
Postat: 13 februari 2007, 22:04:09
av bengt-re
Lite OT, men sitter med ungefär samma problem jag också fast på en 16f628A. Mina timerinterupt kommer 2,7 gånger mer sällan än vad jag räknat ut...... 2,7 !!! Hur f-n.......
Postat: 13 februari 2007, 22:30:54
av sodjan
Det är inte så att delay_50ms avbryts av t.ex en ISR regelbundet ?
Postat: 13 februari 2007, 23:53:24
av JimmyAndersson
Provade att disabla alla interruptmöjligheter, men det är tyvärr likadant ändå.
Postat: 14 februari 2007, 00:35:57
av RasmusB
Riktigt skumt.
Får hela koden plats här?
Postat: 14 februari 2007, 00:39:15
av Kaggen
Är du säker på att du talat om för MPSIM att simulera 8MHz och inget annat?
Har du disableat watchdog?
Är du säker på att det inte är på något annat ställe i koden felet ligger (ibland visar det sig att felet inte ligger i den del av koden man tror).
Postat: 14 februari 2007, 00:51:59
av JimmyAndersson
RasmusB: Hela koden är 416 rader, men jag kan förminska den och lägga upp den.
Kaggen: Japp, watchdog är disablat.
Hela config-historien ser ut såhär:
Kod: Markera allt
CONFIG OSC = INTIO2
CONFIG PWRT = ON, BOR = OFF, WDT = OFF, MCLRE = ON
CONFIG STVR = OFF, LVP = OFF, DEBUG = OFF, CP0 = OFF
CONFIG CP1 = OFF, CPB = OFF, CPD = OFF, WRT0 = OFF
CONFIG WRT1 = OFF, WRTB = OFF, WRTC = OFF, WRTD = OFF
CONFIG EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF
I MPSIM står det mycket riktigt 8MHz.
"ibland visar det sig att felet inte ligger i den del av koden man tror"
Sååå sant.
edit: Glömde en rad:
Så även den har jag tänkt på.

Postat: 14 februari 2007, 00:59:42
av JimmyAndersson
Nu har jag bantat koden lite. Det finns kanske massor med saker som kan göras snyggare, men för att vara mitt första asm-projekt till en µC så tycker jag det är ok, än så länge.
Är ni beredda?
Ok:
Kod: Markera allt
;************************************************************
processor 18f1320
#include <p18f1320.inc>
;************************************************************
; TFTUVbox
;
; Använder interna oscillatorn (8MHz.)
;
;************************************************************
; CONFIG SETTINGS - Note: DEBUG, CPx, WRTx, osv.
CONFIG OSC = INTIO2
CONFIG PWRT = ON, BOR = OFF, WDT = OFF, MCLRE = ON
CONFIG STVR = OFF, LVP = OFF, DEBUG = OFF, CP0 = OFF
CONFIG CP1 = OFF, CPB = OFF, CPD = OFF, WRT0 = OFF
CONFIG WRT1 = OFF, WRTB = OFF, WRTC = OFF, WRTD = OFF
CONFIG EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF
;************************************************************
; Defines och EUQ
; DISPLAY 12x2
#define D4 LATA, 0
#define D5 LATA, 1
#define D6 LATA, 2
#define D7 LATA, 3
#define RS LATA, 4
#define E LATA, 6
;************************************************************
knapp_vars udata_acs
ad_varde res 1 ;Innehållet från AD-avläsningen (LOW)
knapp res 1 ;Vilen knapp som tryckts ner
del res 1 ;Delen (nibble) av byten till LCD'n
;************************************************************
; MACRO
lcd_skriv_text_pos macro vad, var
; Skicka första halvan av 'var' till LATA
bcf RS ;instruktionsläge
movlw var ;var --> W
movwf del ;W --> del-registret
call lcd_dela_hi ;hi --> del (Skiftat och förkortat)
bcf del, 4 ;Ingen RS-bit
bsf del, 3 ;För att skicka position
movff del, WREG ;del --> W
call lcd_skriv ;Skicka W till LATA
; Skicka andra halvan av 'var' till LATA
bcf RS ;instruktionsläge
movlw var ;var --> W
movwf del ;W --> del-registret
call lcd_dela_lo ;lo --> del (Förkortat)
bcf del, 4 ;Ingen RS-bit
bcf del, 3 ;För att skicka position
movff del, WREG ;del --> W
call lcd_skriv ;Skicka W till LATA
;
; Skicka första halvan av 'vad' till LATA
bsf RS ;teckenläge
movlw vad ;vad --> W. T.ex 0101'0110
movwf del ;W --> del-registret
call lcd_dela_hi ;hi --> del (Skiftat och förkortat; 0000'0101)
bsf del, 4 ;Lägg till en RS-bit
movff del, WREG ;del --> W
call lcd_skriv ;Skicka W till LATA. T.ex 0001'0101
; Skicka andra halvan av 'vad' till LATA
bsf RS ;teckenläge
movlw vad ;vad --> W. T.ex 0101'0110
movwf del ;W --> del-registret
call lcd_dela_lo ;lo --> del (Förkortat till 0000'0110)
bsf del, 4 ;Lägg till en RS-bit
movff del, WREG ;del --> W
call lcd_skriv ;Skicka W till LATA. T.ex 0001'0110
endm
lcd_skriv_lata macro kommando
; Används för att skriva direkt till LATA utan att dela upp byten.
bcf RS
movlw kommando ;kommando --> W
call lcd_skriv
endm
;************************************************************
Boot CODE h'0000'
goto Start
;************************************************************
Int_vect CODE h'0008'
goto isr_rutin
;************************************************************
Main CODE
Start
; OSCILLATOR FREQ 8MHz
bcf OSCCON, IDLEN
bsf OSCCON, IRCF2
bsf OSCCON, IRCF1
bsf OSCCON, IRCF0
bsf OSCCON, SCS1
; WATCHDOG TIMER
bcf WDTCON, SWDTEN
; IN/UTGÅNGAR
movlw b'10000000'
movwf TRISA
movlw b'10100111'
movwf TRISB
; NOLLSTÄLL PORTARNA...
clrf PORTA
clrf PORTB
; INITIERAR LITE SMÅGREJJER
bcf E
bcf RS
; INTERRUPT
bcf T1CON, TMR1ON ; <---- TIMER1 DISABLED
bcf PIE1, TMR1IE ; <---- TMR1 OVERFLOW INTERRUPT DISABLED
bcf INTCON, GIE ; GLOBAL INTERRUPT DISABLED
bcf INTCON, PEIE ; PERIPHERAL INTERRUPT DISABLED
;************************************************************
; INITIERA DISPLAYEN - 4 bitar.
lcd_skriv_lata b'00000011'
lcd_skriv_lata b'00000011'
lcd_skriv_lata b'00000011'
lcd_skriv_lata b'00000010'
lcd_skriv_lata b'00000010'
lcd_skriv_lata b'00001000'
lcd_skriv_lata b'00000000'
lcd_skriv_lata b'00000001'
lcd_skriv_lata b'00000000'
lcd_skriv_lata b'00000110'
lcd_skriv_lata b'00000000'
lcd_skriv_lata b'00001100'
;************************************************************
; Kör igång presentationen!
call lcd_presentation
;************************************************************
;
;************************************************************
;************************************************************
loop
goto loop ;Igen!
;************************************************************
;************************************************************
;
;************************************************************
; Skriv till LATA. Datan finns i W.
lcd_skriv CODE
lcd_skriv ;Det som ska skrivas finns i W
bcf E
movwf LATA
call delay_50ms
bsf E
call delay_50ms
bcf E
call delay_50ms
return
;************************************************************
; Dela upp en byte och returnera den höga delen (hi nibble).
lcd_dela_hi CODE
lcd_dela_hi ;Det som ska delas upp finns i registret 'del'.
swapf del, 1 ;Byt plats
bcf del, 4 ;Rensa bit
bcf del, 5
bcf del, 6
bcf del, 7
return
;************************************************************
; Dela upp en byte och returnera den låga delen (lo nibble).
lcd_dela_lo CODE
lcd_dela_lo ;Det som ska delas upp finns i registret 'del'.
bcf del, 4 ;Rensa bit
bcf del, 5
bcf del, 6
bcf del, 7
return
;************************************************************
lcd_presentation CODE
lcd_presentation
;Presentationen som syns när man startar projektet
; vad var
;Steg 1
lcd_skriv_text_pos d'85', b'00000100' ;U
lcd_skriv_text_pos d'86', b'00000110' ;V
;Steg 2
lcd_skriv_text_pos d'84', b'00000011' ;T
lcd_skriv_text_pos d'70', b'00000101' ;F
lcd_skriv_text_pos d'84', b'00000111' ;T
return
;************************************************************
;
;************************************************************
;************************************************************
isr_rutin CODE
isr_rutin
; movlw ADRESL ;Läs av ADC's låga byte.
; movwf ad_varde
nop
bcf PIR1, TMR1IF ;Cleara AD-interrupt.
retfie fast
;************************************************************
; Delay500us -- 500us = 1000 cycles @ 8MHz
dly500us_vars udata_acs
CNT1 res 1
CNT2 res 1
dly500us_code CODE
delay_500us
movlw 0x0B
movwf CNT1
movlw 0x13
movwf CNT2
dly500us_loop
decfsz CNT1
goto dly500us_loop
movlw 0x10
movwf CNT1
decfsz CNT2
goto dly500us_loop
return
;************************************************************
; Delay50ms -- 50ms = 100'000 cycles @ 8MHz
dly50ms_vars udata_acs
CNT4 res 1
CNT5 res 1
CNT6 res 1
dly50ms_code CODE
delay_50ms
movlw 0x04
movwf CNT4
movlw 0x06
movwf CNT5
movlw 0x10
movwf CNT6
dly50ms_loop
decfsz CNT5
goto dly50ms_loop
movlw 0x07
movwf CNT5
decfsz CNT4
goto dly50ms_loop
decfsz CNT6
goto dly50ms_loop
nop
return
;************************************************************
end
Pust!

Postat: 14 februari 2007, 10:52:41
av sodjan
OK, då ska vi se.
Låt oss först *anta* att delay_50ms fungerar precis som den ska.
Sen, om jag förstår rätt, så är det i "lcd_presentation" som varje tecken
skrivs ut, eller hur ?
Notera att varje gång som macrot "lcd_skriv_text_pos" används så
anropas delay_50ms 3x4 = 12 gånger. 12 x 50ms = 600 ms.
Så det bör ta ca 600 ms (600,046 ms enligt MPSIM) mellan varje tecken.
Vilken tid var det du såg i verkligheten ?
Postat: 14 februari 2007, 11:02:20
av RasmusB
Ser ut som att jag bara kan hålla med sodjan...

Postat: 14 februari 2007, 11:47:56
av JimmyAndersson
"Sen, om jag förstår rätt, så är det i "lcd_presentation" som varje tecken
skrivs ut, eller hur ?"
Japp.
"Så det bör ta ca 600 ms (600,046 ms enligt MPSIM) mellan varje tecken.
Vilken tid var det du såg i verkligheten ?"
Nu är mitt oscilloskop ute och åker buss, men när jag jämförde med en vanlig klocka så uppskattade jag tiden till lite mer än en halv sekund. Så då stämmer det alltså. Skönt att det inte berodde på något fel.
Så då är det alltså bara att minska delaytiden. (Att flytta markören tar egentligen bara 39µs.)
Postat: 14 februari 2007, 12:18:44
av sodjan
Nu är jag inte riktigt med här...
Problemet var alltså att du inte riktigt förstog din egen kod !?
Om du sätter två breakpoints på två anrop till "lcd_skriv_text_pos"
så ser du direkt i tidtagaruret att det blir drygt 600 ms mellan varje tecken.
Postat: 14 februari 2007, 13:27:44
av JimmyAndersson
Jodå, koden förstår jag.
Däremot hade jag inte riktigt kommit på hur man sätter breakpoints och därför snöade jag in på enbart en delayrutin.
Men man lär sig av sina misstag, så nu vet jag hur man ska göra.
