Programación Específica > Microcontroladores
Retardos...
eliza_marti:
Hola Chicos.. :hola: ..Sé que no me debo concentrar en esto..y que con la práctica usaré el programa de retardos.. :) ..pero siempre es bueno saber!..estaba viendo una rutina de 1seg..y me quedaron ciertas dudas..se que el valor del cristal a utilizar siempre se divide para 4 entiendo porqué perfectamente..pero ? :unsure: ..porqué el divisor de frecuencia es 256??..a que se debe?.. :huh:
Aqui está la rutina...
--- Código: Text ---;---------------------------------------------;Subrutina de temporizar 1 segundo.;---------------------------------------------;Frecuencia del cristal es 4Mhz.;La señal de entrada al TMR0 es fosc./4, o sea, 1Mhz (T= 1 useg.).;El divisor de frecuencia divide por 256, con lo que la señal de 1 Mhz se;transforma en una de 3906,25 Hz (T= 0,256 mseg.);1seg= 1000 mseg.;0,256 mseg x 3900= 998,4 mseg;El TMR0 va a contar desde 216 a 255 que son 39 impulsos de 0,256 mseg.;y esto lo va hacer 100 veces, o sea, las 3900 veces que necesito. cuenta1 bsf INTCON,T0IE; activo int. timer0. bcf INTCON,T0IF; poner a cero el flag del; timer0. movlw 0d8h; d8h= 216 decimal movwf TMR0; 255 - 216 = 39.cuentaetc................
Gracias por leer este post... :hola: ..y si alguien me puede decir el porqué se lo agredecería muchio..bye.. :comp: :ph34r:
eliza_marti:
Yo entiendo así.. :) Corríjanme si estoy mal…sé que cada instrucción puede tardar en ejecutarse uno o dos ciclos de reloj..(dependiendo).. :) .pero la duración de cada ciclo de reloj puede variar dependiendo que cristal utilices u otros…por ejemplo si utilizo un cristal de 4Mhz…Quiere decir que puedo procesar 4’000000 de ciclos por segundo..que dividido para 4 me dará el valor en si del temporizador o sea 1Mhz…entonces cada ciclo de reloj me durará 1/1’000000 = 0,000001 seg. = 1useg.. o sea que para simular un retardo de 1 seg. Debo de ejecutar a lo mucho 1’000000 de ciclos (1’000000 useg)..es válida mi conclusión?... :huh: entonces porqué en algunos ejemplos se pasan de los 1’000000 useg?...no son exactos?.. :o .hay unos que son exactos y otros no?... :o
Gracias a Todos por leer… :hola: ….todas sus opiniones son bienvenidas…. ;) :hola: :comp:
Huguen_aus_Tirol:
Hola! Hay muchísimas formas de hacer retardos en los microcontroladores; yo personalmente uso el timer0 y obtengo bases de tiempo de, p.e., 10 mseg, 1 seg, 1 min, etc. Todo depende de que es lo que se quiera hacer.
Hacer que sea exacto quizá no debería preocuparte tanto, si tienes un error de algunos µseg cada segundo no es tan trágico. P.e., un error de 20 µseg por cada segundo (20 instrucciones, y es mucho) te da un segundo de error por cada, aprox., 14 horas!
Si solo se quiere hacer parpadear un led para indicar un estado, o algo, tal vez sea lo mismo que parpadee a 1.2 seg, 1 seg, ó a 0.95 seg :)
En este foro existen ya rutinas de tiempos hechas, si no me equivoco Jonathan ya te pasó el link. Eso te facilita el trabajo de hacerlas, pero fijate como funcionan; puedes sacar muchas cosas en claro, y que despues seguro te serviran para solucionar otros problemas ;)
Bueno, a seguir practicando, hasta que salga humo de nuestras cabezas, o del micro :D . Lo importante es aprender!
PD Jonathan, gracias por aclarar el tema del warning! Siempre había tenido la duda...
Saludos
eliza_marti:
Hola Chicos!.. :hola: ...Huguen_aus_Tirol... :o ..es verdad lo que dijiste en este foro ya hay una explicación sobre tiempos utilizando el temporizador interno:
Retardo En 16f84
y... :D ..no estaba equivocada en lo del manejo del tiempo...
aunque todavia no entiendo muy bien el ejemplo que puse al principio.. :huh: ..
Bueno..Muchas Gracias por tu ayuda!.. ;) ..Bye!.. :hola: :comp: :ph34r:
Huguen_aus_Tirol:
Hola! Aca les paso un pequeño programa de ejemplo, en el que está como utilizo el timer0 para generar retardos; me funciona muy bien, tal vez no tan exacto, pero me sirve a la perfección para lo que necesito. Además me parece fácil de adaptar a cualquier necesidad de tiempos...
Usé el mismo concepto con los ST de Thompson, despues con los 16Fxx, y ahora me da excelentes resultados con los 18F.
Bueno, espero no se mareen, pero me pareció mejor darlo asi como está...
Ah, y si alguien lo entiende, le agradecería me explique como funciona!! :D (es chiste)
Saludos y suerte
--- Código: Text --- TITLE "Temporizador general programable";; Autor: Hugo Erhard, <hugoerhard@yahoo.de>; Inicio: 23-08-2002 ; Terminado: 25-08-2002;; Revisiones: 1.00 23-08-2002 Initial release; 1.01 25-08-2002 Se define constante para Xtal 3.57 MHz; ;===============================================================================;;===============================================================================; errorlevel -215, -302, -301 list p=pic16f84 include "p16f84.h" __CONFIG 0x3FF1;;-------------------------------------------------------------------------------; DEFINICION DE VARIABLES; CBLOCK 0x0E; T0_ADJ; para correccion de error en timer T0_SEG; post scaler para 1 segundo MIL50; contador de 50 milisegundos CNT_SEG; contador de segundos CNT ; contador general; ENDC;; DEFINICION DE PINES;#DEFINE SELECT PORTA,0; selector base de tiempo#DEFINE START_SW PORTA,1; pulso de inicio#DEFINE OUT PORTA,2; salida, 1 mientras temporiza#DEFINE BUZZER PORTA,3; zumbador#DEFINE LED PORTA,4; led;; DEFINICION DE CONSTANTES;XTAL EQU .10 ; si usas xtal de 4 MHz declaralo aqui; if XTAL == .4;COUNTS EQU .61 ; 61 -> Xtal = 4 MHz // 81 -> Xtal = 3.57 MHzK_1seg EQU .20 ; 20 cuentas de 50 µseg = 1 seg; else;COUNTS EQU .159; 159 -> Xtal = 10 MHzK_1seg EQU .100; 100 cuentas de 10 µseg = 1 seg; endif;;-------------------------------------------------------------------------------; ORG 0POR GOTO MAIN ; reset, salto al programa principal; ORG 4ISR MOVWF SAVE_W ; salvo W SWAPF STATUS,W; cargo STATUS MOVWF SAVE_S ; y salvo CLRF STATUS ; para asegurar que este en banco 0 BTFSC T0IF ; interrupcion de timer ? GOTO T0ISR ; si, atiendo...INTEND SWAPF SAVE_S,W; recupero STATUS invirtiendo nibbles MOVWF STATUS ; SWAPF SAVE_W,F; recupero W de esta manera para no afectar SWAPF SAVE_W,W; los bits de STATUS RETFIE ; y salgo de interrupcion habilitandolas;-------------------------------------------------------------------------------;; T0 INTERRUPT SERVICE ROUTINE;; Cristal = 4 MHz; Ciclo = 1 µseg, prescaler = 256; TMR0 se incrementa cada 1 µseg * 256 = 256 µseg; Para llegar a 50 mseg -> 50000 µseg / 256 µseg = 195.31 -> 195 cuentas; Cargando TMR0 con 256 - 195 = 61, se genera una interrupcion cada 195; cuentas, es decir cada 195 * 256 µseg = 49.92 mseg.; Esto genera un error de 50000 µseg - 49920 µseg = 80 µseg.;; NOTA: si se utiliza un cristal de 3.579545 MHz, se tiene:; temporizador MINUTOS cuenta cada 1.11746 minutos; temporizador HORAS cuenta cada 1h 7' 2"; Si se utiliza este cristal, para conservar los tiempos de temporizacion,; cargar TMR0 con 81 (175 cuentas) en lugar de 61 (195 cuentas). ; Se agrega un error de 3 mseg por segundo de temporizacion.; *** VER EN DECLARACION CONSTANTES ***;; CONSTANTES PARA CRISTAL DE 10 MHz;; Cristal = 10 MHz; Ciclo = 0.4 µseg, prescaler = 256; TMR0 se incrementa cada 0.4 µseg * 256 = 102.4 µseg; Para llegar a 50 mseg -> 50000 µseg / 102.4 µseg = 488.28 -> 488 cuentas;; Me pase, puedo tener maximo 256 cuentas!!!!!!!; Probamos con temporizacion de 10 mseg = 10000 µseg:;; Para llegar a 10 mseg -> 10000 µseg / 102.4 µseg = 97.65 -> 97 cuentas;; Cargando TMR0 con 256 - 97 = 159, se genera una interrupcion cada 97; cuentas, es decir cada 97 * 102.4 µseg = 9.9328 mseg.; Esto genera un error de 10000 µseg - 9932.8 µseg = 67.2 µseg.; Este error corresponde a 67.2 µseg / 0.4 µseg = 168 instrucciones; T0ISR if XTAL == .4;; Se compila si se usa XTAL de 4 MHz; NOP ; este lazo genera una demora de 80 µseg MOVLW .15 ; para compenzar el error del timer MOVWF T0_ADJ ; GOTO $+1 ; para gastar 2 ciclos ahorrando memoria DECFSZ T0_ADJ,1; GOTO $-2 ; ; else;; Se compila si se usa XTAL de 10 MHz (o distinto de 4 MHz OJO!!!); GOTO $+1 ; para compenzar error GOTO $+1 ; MOVLW .30 ; para compenzar el error del timer MOVWF T0_ADJ ; GOTO $+1 ; para gastar 2 ciclos ahorrando memoria DECFSZ T0_ADJ,1; GOTO $-2 ; ; endif; MOVLW COUNTS ; cargo TMR0 para N cuentas MOVWF TMR0 ; DECF MIL50,1 ; DECFSZ T0_SEG,1; decremento post-scaler de 1 segundo GOTO T0END ; si falta salgo; MOVLW K_1seg ; valor de recarga de post-scaler de 1 segundo MOVWF T0_SEG ; DECF CNT_SEG,1; decremento contador de segundosT0END BCF T0IF ; rehabilito interrupcion de timer GOTO INTEND ; y salgo;-------------------------------------------------------------------------------;; Aqui salta despues de un reset, se inicializan todos los registros;MAIN CLRF STATUS ; borro STATUS para saber como inicializo BSF RP0 ; banco 1 MOVLW b'00000011'; PORTA -> xxxOOOII MOVWF TRISA ; MOVLW b'11111111'; PORTB -> IIIIIIII MOVWF TRISB ; MOVLW b'00000111'; RB pull up enabled, x, TMR0 ck internal, MOVWF OPTION_REG; x, prescaler to TMR0, prescaler = 256 BCF RP0 ; banco 0 CLRF PORTA ; borro puerto A MOVLW K_1seg ; inicializo base de tiempos de segundos MOVWF T0_SEG ; MOVLW COUNTS ; inicializo timer 0 MOVWF TMR0 ; MOVLW b'10100000'; habilito interrupciones, solo timer 0 MOVWF INTCON ; ;-------------------------------------------------------------------------------;; Lazo principal, salida permanece baja por 58 seg y alta por 2 seg; La salida se refleja en el led;MAIN_LOOP BCF OUT ; salida en 0 BSF LED ; led apagado MOVLW .58 ; preparo demora de 58 seg MOVWF CNT_SEG ; WAIT_LOW TSTF CNT_SEG ; BNZ WAIT_LOW; espero a que pasen los 58 seg BSF OUT ; salida en 1 BCF LED ; led encendido MOVLW .2 ; preparo demora de 2 seg MOVWF CNT_SEG ; WAIT_HIGH TSTF CNT_SEG ; BNZ WAIT_HIGH; espero a que pasen los 2 seg GOTO MAIN_LOOP; y repito for ever...; END
Navegación
[#] Página Siguiente
Ir a la versión completa