# Problema simulación - proteus + PSI



## Manunet (Abr 7, 2011)

Hola a todos, a ver si me podeis hechar una mano en un problemita que me ha surgido haciendo unas simulaciones.

Resulta que en la 1º simulacion ( llamada '1seg' ) utilizo el tmr1 del 16f877a para encender y apagar un led cada segundo.
El tema es fácil, configuro el  tmr1, le  doy a TMR1H = 0xFC ( 252 ) TMR1L = 0x46 ( 70 ), activo las interrupciones y el tmr1 desborda cada milisegundo, con lo cual pongo un contador desde 0 hasta 999, cuando contador=999 entoces enciendo el led.
He comprobado que si a TMR1H y TMR1L los pongo a 0 ( cero ) el tmr1 desborda cada 1 minuto y 5 segundos más o menos.
Todo esto según la simulación y el pic a 4Mhz.

Bien, ahora lo curioso viene en la segunda simulación ( llamada 'captura'), ésta no hace más que calcular los hertzios durante 1 segundo con lo cual utilizo las mismas rutinas que en la simulacion anterior... configuro el tmr1 para que desborde cada segundo ( valores 0Xfc y =0x46 ). Configuro el capturador en flanco de subida y cuando detecte el 1º impulso activa el tmr1, mientras, en cada impulso cont=cont+1, lo siguiente que hace es que cuando desborda el tmr1 apaga el capturador, para el tmr1 y muestra el valor de cont por el lcd... vamos, mas sencillo imposible...

El problema está en que en la 1º simulación el tmr1 desborda cada milisegundo, por eso le pongo un contador de 0 a 999, ( 1000 mS = 1S ), bien, pues en la segunda simulación, he tenido que hacer lo siguiente:
TMR1H y TMR1L  a 0 ( cero ) y le he tenido que poner un contador de 0 a 15 para que cuante casi exacto un segundo.

La duda es porque tengo que variar el TMR1H y TMR1L en las simulaciones si simplemente cambio el led por un osciloscopio...

Aquí el código de la simulación '1Seg'

Define CONF_WORD = 0x3f71

'Prueba contador 1 segundo

Define LCD_LINES = 4  'LCD de 4 líneas/filas
Define LCD_CHARS = 16  'LCD de 16 caracteres/columnas
Define LCD_BITS = 8  'Comunicacion con LCD a 8 bits
Define LCD_DREG = PORTB  'La comunicación se raliza por el PortB
'Define LCD_DBIT = 0 'A 4 bits, 0 Se utilizan pines del 0 al 3 y el 4 del 4 al 7
Define LCD_RSREG = PORTC  'El bit RS en el PortC
Define LCD_RSBIT = 6  'El bit RS en el pin 0
Define LCD_EREG = PORTC  'El bit E en el PortC
Define LCD_EBIT = 7  'El bit E en el pin 1
'Define LCD_RWREG = PORTC  'El bit RW en el PortC
'Define LCD_RWBIT = 2  'El bit RW en el pin 2
Define LCD_COMMANDUS = 100  'Pausa en microsegundos despues de enviar un comando al LCD
Define LCD_DATAUS = 50  'Pausa en microsegundos despues de enviar datos al LCD
Define LCD_INITMS = 2  'Pausa para esperar la inicialización del LCD

'Define SIMULATION_WAITMS_VALUE = 1  'Convierte todos los WaitMS a WaitMs=1

Lcdinit
WaitMs 100
'Break
CMCON = 0  'comparador a off
Symbol ro = RD0
Symbol am = RD1
Dim a As Bit
Dim cont As Long
Dim th As Byte
Dim tl As Byte

'Un segundo corresponde cada 1.000, aunque en ésta simulación corresponde a 1.004
'1 segundo = 64.582
'th = 252
'tl = 70

'2 segundos = 63.582
'th = 248
'tl = 90

'3 segundos = 62.574
'th = 244
'tl = 110

a = 1
'tmr1
'preescaler:
'11=1:8 10=1:4 01=1:2 00=1:1
T1CON.T1CKPS1 = 0
T1CON.T1CKPS0 = 0
'oscilador
'1=enabled 0=disabled
T1CON.T1OSCEN = 0
'sincronicacion
'1=No external clock
'0=External clock
T1CON.T1SYNC = 0
'clock source
'1=reloj externo (RC0) ( contador )
'0=interno ( Fosc/4 ) ( Timer )
T1CON.TMR1CS = 0

TMR1H = th  'preparo TMR1H para que desborde
TMR1L = tl  'preparo TMR1L para que desborde
INTCON.PEIE = 1  'activo las int de perifericos
PIE1.TMR1IE = 1  'activo int del tmr1

'estado del tmr1
'0=apagado
'1=encendido
T1CON.TMR1ON = 1  'activo el tmr1

Enable  'activo las int globales ( unmasked )

'el preescaler se pierde al escribir en TMR1H y TMR1L

While a = 1
	Lcdcmdout LcdLine1Home
	Lcdout #TMR1H, "    "
	Lcdcmdout LcdLine2Home
	Lcdout #TMR1L, "    "
Wend

End                                               

On Interrupt
Save System

If PIR1.TMR1IF Then
	PIR1.TMR1IF = 0
	Toggle ro
	TMR1H = th
	TMR1L = tl
	cont = cont + 1
	If cont = 999 Then
		cont = 0
		Toggle am
	Endif
Endif
Resume

-----------------------------------

Aqui el código de 'capturador'


'Define SIMULATION_WAITMS_VALUE = 1

Define LCD_LINES = 4  'LCD de 4 líneas/filas
Define LCD_CHARS = 16  'LCD de 16 caracteres/columnas
Define LCD_BITS = 8  'Comunicacion con LCD a 8 bits
Define LCD_DREG = PORTD  'La comunicación se raliza por el PortB
'Define LCD_DBIT = 0 'A 4 bits, 0 Se utilizan pines del 0 al 3 y el 4 del 4 al 7
Define LCD_RSREG = PORTB  'El bit RS en el PortC
Define LCD_RSBIT = 0  'El bit RS en el pin 0
Define LCD_EREG = PORTB  'El bit E en el PortC
Define LCD_EBIT = 1  'El bit E en el pin 1
'Define LCD_RWREG = PORTB  'El bit RW en el PortC
'Define LCD_RWBIT = 1  'El bit RW en el pin 2
Define LCD_COMMANDUS = 100  'Pausa en microsegundos despues de enviar un comando al LCD
Define LCD_DATAUS = 100  'Pausa en microsegundos despues de enviar datos al LCD
Define LCD_INITMS = 50  'Pausa para esperar la inicialización del LCD

Dim datos As Word
Dim cont As Long
Dim timer As Long
Dim tiempo As Bit
Dim th As Byte
Dim tl As Byte

Lcdinit 0

WaitMs 500

'config del timer1
T1CON = 0
'T1CON.T1CKPS0 = 0  'modo del preescaler
'T1CON.T1CKPS1 = 0
'T1CON.T1OSCEN = 0  'activar oscilador
'T1CON.T1SYNC = 0  'sincronizacion con timer1 externo
'T1CON.TMR1CS = 0  'Origen de reloj - 1:Externo, 0:Interno(Fosc/4)
'T1CON.TMR1ON = 0  'Activar Timer1

'config modulo captura
CCP1CON.CCP1M0 = 1  'captura por flanco
CCP1CON.CCP1M1 = 0  '0100 descendente, 0101 ascendente, 0110 captura el 4º ascendente, 0111 cap el 16º ascen
CCP1CON.CCP1M2 = 1
CCP1CON.CCP1M3 = 0

INTCON.PEIE = 1  'activo la int de perifericos
PIE1.CCP1IE = 1  'activo la int de ccp cuando ocurra una captura
PIE1.TMR1IE = 1  'activo la int de desbordamiento del tmr1

'configuro el tmr1 para que desborde cada segundo
th = 0
tl = 0
TMR1H = th  '252
TMR1L = tl  '70

T1CON.TMR1ON = 0  'activo el tmr1
RC6 = 0  'activo rc6 para que coincida con rc7 en la primera captura ( estetica )
Enable  'activo los perifericos

loop:
Goto loop

End                                               

On Interrupt

Save System  'guardo el estado del sistema

If PIR1.TMR1IF = 1 Then  'interrupcion de desbordamiento del tmr1, desbordado
	timer = timer + 1
	PIR1.TMR1IF = 0
	If timer = 15 Then
		timer = 0
		T1CON.TMR1ON = 0  'paro el tmr1
		PIE1.CCP1IE = 0  'desactivo el capturador
		Lcdcmdout LcdLine1Home
		Lcdout "Hz-> ", #cont, "    "  'muestro el valor de cont
		cont = 0  'reinicio el contador
		TMR1H = th
		TMR1L = tl
		Toggle RC7  'cambio el estado de RC7
		PIE1.CCP1IE = 1  'activo el capturador
	Endif
Endif

If PIR1.CCP1IF = 1 Then  'Interrupcion del registro de captura, captura realizada
	PIR1.CCP1IF = 0  'limpio el flag
	Toggle RC6  'cambio el estado de RC6
	T1CON.TMR1ON = 1  'activo el tmr1
	cont = cont + 1  'contador de Hertzios por segundo
Endif

Resume

----------------------------------------


Muchas gracias y saludos.


----------



## RSelectronic (Abr 7, 2011)

Podrías poner el log que salta en el ISIS ?


----------



## Manunet (Abr 7, 2011)

Hola Silvesters, no sé a que log te refieres, de todas maneras mando 2 capturas de pantalla.

La 1º pantalla es de la simulación '1seg', como se puede ver en el osciloscopio el led cambia de estado cada segundo con los valores de tmr1h y tmr1l = 0xfc y 0x70 respectivamente y un contador desde 0 hasta 999.

La 2º pantalla es de la simulación 'captura', ahí los registros de tmr1h y tmr1l = 0, además he tenido que poner un contador hasta 15 para que la transición ocurra cada segundo.

Se supone que cada instrucción tarda 1uS, entonces he sacado las siguientes cuentas:
1.000 uS = 1 mS
1.000  mS = 1 Segundo

Sabiendo que el tmr1 es de 16 bits éste desbordaría cuando llegue a 65.535, con lo cual:
65.535 uS - 1.000 uS = 64.535 uS. (  )
Debería contar 1.000 uS para desbordar y activar la interrupción pero como tengo un contador desde 0 hasta 999 deberá desbordar 1.000 veces antes de efectuar el cambio de estado del led que sería cada segundo.

Todo esto se cumple en la primera simulación pero no en la segunda 

Se me olvidaba comentar que en la 2º imagen, en el osciloscopio, la línea amarilla corresponde al generador de señales, la línea roja es cuando el pic entra en la interrupción del capturador ( ccp1 ) y la azul corresponde a la interrupción del tmr1.

Saludos


----------



## R-Mario (Abr 7, 2011)

Mi recomendacion despues de haber intentado simular micros AVR PIC y 8051 es: Proteus es una mugre no sirve, comenten muchos errores como invertir señales, no funcionar como se le indica etc etc, mi segunda recomendacion es: mejor armalo y prueba


----------



## RSelectronic (Abr 7, 2011)

> 65.535 uS - 1.000 uS = 55.535 uS.



No será 64.535?


----------



## Manunet (Abr 8, 2011)

Ouch!!! tienes razón, són 64.535... si esque no puedo... llego de trabajar y el frigorifico no funciona... cada vez que llego a casa del laburo son disgustos.... la secadora, la lavadora... un litro gasolina y verás que pronto lo reparo todo de golpe 

Benito, ya sé que los simuladores tienen muchos fallos y lo mejor para probar algo es montarlo en una proto o una plaquita, el problema es que yo hago la casa por el tejado.. jeje,  tengo un proyecto en mente ( un pequeño ordenador de abordo para el auto ), y lo que hago es montar todo por módulos y luego lo pongo en el proyecto principal; todo en simulación.

Ahora le ha tocado el turno al modulo ccp para las rpm o activación de los inyectores, entonces empecé haciendo un programa en el PSI para que simplemente encendiera un led cada segundo y así conocer el funcionamiento del tmr1, esa misma rutina la aplique a otro proyecto para calcular los Hz cada segundo y resulta que el trm1 funciona de otra manera con los mismos valores.

El tema es que la duda que tengo es porqué entre dos proyectos simulados el tmr1 funciona de distinta manera independientemente de como funcione en la realidad que lo mismo en la simulación me sale 1 segundo exacto y en el real son 3 y pico....

Saludos!


----------

