Delayrutinen stämmer inte i verkligheten..

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
JimmyAndersson
Inlägg: 26586
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Delayrutinen stämmer inte i verkligheten..

Inlägg 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:

Kod: Markera allt

CONFIG	OSC = INTIO2

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?
Användarvisningsbild
RasmusB
Inlägg: 1006
Blev medlem: 24 augusti 2006, 23:32:13
Ort: Södertälje

Inlägg 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?
Användarvisningsbild
JimmyAndersson
Inlägg: 26586
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg 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.
Användarvisningsbild
bengt-re
EF Sponsor
Inlägg: 4829
Blev medlem: 4 april 2005, 16:18:59
Skype: bengt-re
Ort: Söder om söder
Kontakt:

Inlägg 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.......
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Det är inte så att delay_50ms avbryts av t.ex en ISR regelbundet ?
Användarvisningsbild
JimmyAndersson
Inlägg: 26586
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Provade att disabla alla interruptmöjligheter, men det är tyvärr likadant ändå.
Användarvisningsbild
RasmusB
Inlägg: 1006
Blev medlem: 24 augusti 2006, 23:32:13
Ort: Södertälje

Inlägg av RasmusB »

Riktigt skumt.

Får hela koden plats här?
Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Inlägg 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).
Användarvisningsbild
JimmyAndersson
Inlägg: 26586
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg 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:

Kod: Markera allt

bcf		WDTCON,	SWDTEN
Så även den har jag tänkt på. :)
Användarvisningsbild
JimmyAndersson
Inlägg: 26586
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg 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! :D
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg 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 ?
Användarvisningsbild
RasmusB
Inlägg: 1006
Blev medlem: 24 augusti 2006, 23:32:13
Ort: Södertälje

Inlägg av RasmusB »

Ser ut som att jag bara kan hålla med sodjan... :)
Användarvisningsbild
JimmyAndersson
Inlägg: 26586
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg 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.)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg 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.
Användarvisningsbild
JimmyAndersson
Inlägg: 26586
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg 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. :)
Skriv svar