Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
E estado intentando hacer un codigo el cual funcione como un cronometro real, el cual al presionar un boton comience la cuenta del tiempo y al presionar de nuevo ese boton lo detenga mostrando el ultimo tiempo registrado, e intentado de distintas formas pero no e logrado que el tiempo se detenga
aqui el codigo del cronometro:
#include <16f887.h>
#fuses INTRC,NOPROTECT,NOLVP,NOWDT
#use delay (clock=8000000)
#include <stdlib.h>
#use rs232(baud=9600, xmit=PIN_c6, rcv=PIN_c7)
void main()
{
int16 minutos=0 ;
int16 segundos=0;
int16 milisegundos=0;
int1 boton;
while(true)
{
boton=input_state(pin_b7);
milisegundos=milisegundos+1;
delay_ms(1);
if(milisegundos>=999)
{
milisegundos=0;
segundos=segundos+1;
}
if(segundos==59)
{
segundos=0;
minutos=minutos+1;
}
if(boton==1)
{
printf("%li : %li : %linr",minutos,segundos,milisegundos);
}
}
}
Wow! 😮
En definitiva, después de leer todo el párrafo anterior verás que la precisión y la complejidad estan reñidas. Simplemente planteate estas preguntas:
- ¿cuál es el tiempo más largo que voy a medir?
- ¿cuál es la precisión que necesito en ese tiempo?
No es lo mismo 1 min de medida con una precisión de 1ms que 1 año de medida con una precisión de 1ms.
S2
Ranganok Schahzaman
PD: en la wiki, en la sección de tutoriales hay dos que te podrían servir para comprender el funcionamiento del micro y los timers:
- http://wiki.webdearde.com/index.php?title=Tutorial:Los_PIC_de_la_gama_media " onclick="window.open(this.href);return false;
- http://wiki.webdearde.com/index.php?title=Tutorial:_Programaci%C3%B3n_de_PICs_en_Ensamblador " onclick="window.open(this.href);return false;
Quizá te sirva esto.
Cuentavueltas y cronómetro para robots velocistas hecho con un PIC16F628A:
http://webdelcire.com/wordpress/archives/2709 " onclick="window.open(this.href);return false;
mruQG03mtCc
Poco más que añadir, pero por si sirve de algo, te pongo esto:
* Calculadora online de timers:
http://eng-serve.com/pic/pic_timer.html
* Calculadora completa pero para unos pocos modelos de pic:
http://www.mediafire.com/download/z2o1jym5zzm/ConfigPIC.rar
(Tampoco hay mucha diferencia de un 16F648 a un 16F887, muchas cosas las puedes usar)
Recomendación:
Lo primero bajarte el datasheet del 16F887 y mirar sus características, sobretodo los Timers. La página oficial es esta:
http://ww1.microchip.com/downloads/en/DeviceDoc/41291G.pdf
Fíjate que tiene tres timers:
* Timer 0 (8 bits)
* Timer 1 (16 bits)
* Timer 2 (8 bits)
A más bits, más precisión tendrás en ajustar el tiempo exacto. Si solo usarás los timers para hacer un reloj, no tendrás problemas, pero si quisieras hacer una aplicación más complicada, usando otros periféricos del microcontrolador, tienes que fijarte en que los timers són compartidos y no puedes usarlos para hacer dos temporizaciones diferentes a la vez.
Después decidir si usas el reloj interno o uno externo. El interno es de 8 MHz pero lo puedes dividir con el pre-escaler para obtener frecuencias más bajas.
Entonces con la calculadora de timers o con una tabla de excel (es lo que suelo hacer yo) pruebas diferentes valores del registro TMRx de cada timer y los pre-escalers para intentar conseguir el tiempo lo más exacto posible. Por ejemplo, para conseguir un tiempo de 1 ms, con un reloj de 8MHz, debes configurar los timers con los siguientes valores:
* Timer 0: pre-escaler 1:8, TMR0 = 6
* Timer 1: pre-escaler 1:1, TMR1 = 63536 (TMR1H = 248, TMR1L = 48)
* Timer 2: post-escaler 1: TMR2 = 200
Para trabajar con cualquier micro hay que conocer sus registros y como funcionan. Así que te toca estudiar. De todos modos, si no recuerdo mal, el ide/compilador CCS lleva varios "wizards" para configurar los timers, lo puedes hacer desde allí.
Este hilo me parece otro buen ejemplo de que en el foro se crea un contenido muy valioso que debería ser reorganizado, clasificado y editado como un: tutorial? , simple entrada en nuestro próximo nuevo blog?.... lo que sea, cuando tengamos los "cajones" hechos, lo ubicamos bien... pero valioso es.
Espero que a lorenzorenzzo le haya ayudado. Si tienes más dudas no las guardes...
Slds a todos,
Sphinx.
muchas gracias a todos por responder
intento cambiar el código del programa que sistemasorp aporto con el link, e intentado cambiar el programa para adaptarlo al pic que estoy utilizando pero al momento de simularlo no realiza la cuenta del cronometro ¿me podrian ayudar?
aquí el código que adapte #include <16F887.h>
#include <string.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#use delay(clock=20000000)
#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use fast_io(A)
#use fast_io(B)
#rom 0x2100={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define MAXIMO_VUELTAS 10
#define TEMPORIZADOR0 217
#define TEMPORIZADOR1 59286
#define TIEMPO_ENTRE_VUELTAS 200
#define LUZ PIN_B3
#define SONIDO PIN_A3
enum ESTADOS{CALIBRADO, INICIO, PREPARADO, ESPERANDO, CORRIENDO, PARADA, RESULTADO};
void activa_interrupcion_timer();
void datos(int8 finalizado);
#include "lcd.c"
#include <string.h>
volatile int16 mediciones[MAXIMO_VUELTAS];
volatile int8 indice;
volatile ESTADOS estado;
volatile int16 ms;
#INT_RB
void pulsado()
{
int8 valor;
valor = input_b();
if((valor & 0x10) == 0)
{
switch(estado)
{
case CALIBRADO:
estado = PARADA;
break;
case PREPARADO:
clear_interrupt(INT_EXT);
enable_interrupts(INT_EXT);
output_high(LUZ);
mediciones[0] = 0;
indice = 0;
estado = ESPERANDO;
break;
case CORRIENDO:
estado = PARADA;
break;
}
}
}
#INT_EXT
void marcaje()
{
if(estado == ESPERANDO)
{
set_timer1(TEMPORIZADOR1);
enable_interrupts(INT_TIMER1);
putchar(0);
putchar(0);
output_low(LUZ);
activa_interrupcion_timer();
estado = CORRIENDO;
}
else if((estado == CORRIENDO) && (mediciones[indice] > TIEMPO_ENTRE_VUELTAS))
{
if(indice < (MAXIMO_VUELTAS - 1))
{
putchar(mediciones[indice] >> 8);
putchar(mediciones[indice] & 0xFF);
indice++;
mediciones[indice] = 0;
activa_interrupcion_timer();
}
else
{
estado = PARADA;
}
}
}
#INT_TIMER0
void tick0()
{
set_timer0(TEMPORIZADOR0);
ms++;
if(ms >= 200)
{
disable_interrupts(INT_TIMER0);
ms = 0;
output_low(SONIDO);
}
}
#INT_TIMER1
void tick1()
{
set_timer1(TEMPORIZADOR1);
mediciones[indice]++;
}
void activa_interrupcion_timer()
{
ms = 0;
set_timer0(TEMPORIZADOR0);
output_high(SONIDO);
enable_interrupts(INT_TIMER0);
}
void activa_interrupcion_rb()
{
input_b();
clear_interrupt(INT_RB);
enable_interrupts(INT_RB);
}
void pinta(int16 valor, char *cadena)
{
int16 minutos;
int16 segundos;
int16 decimas;
char tiempo[10];
decimas = valor % 100;
segundos = (valor - decimas) / 100;
minutos = segundos / 60;
segundos -= minutos * 60;
sprintf(tiempo,"%ld:%02ld:%02ld ", minutos, segundos, decimas);
strcat(cadena, tiempo);
}
void datos(int8 finalizado)
{
int16 total;
int16 actual;
int8 contador;
char vueltas[11];
char cadena[42] = "";
actual = mediciones[indice]; // si no uso actual el timer puede sumar uno mas entre el pintar el actual y el pintar el total
if(finalizado == FALSE)
{
pinta(actual, cadena);
}
else
{
pinta(0, cadena);
}
if(indice > 0)
{
pinta(mediciones[indice - 1], cadena);
}
else
{
pinta(0, cadena);
}
sprintf(vueltas, "n%d ", indice);
strcat(cadena, vueltas);
total = 0;
for(contador = 0; contador < indice; contador++)
{
total += mediciones[contador];
}
if(finalizado == FALSE)
{
total += actual;
}
pinta(total, cadena);
//disable_interrupts(INT_RB);
set_tris_b(3); // 00000011
lcd_gotoxy(1, 1);
printf(lcd_putc, "%s", cadena);
set_tris_b(0x13); // 00010011
//activa_interrupcion_rb();
}
void lee_mediciones()
{
int8 contador;
int16 valor;
indice = 0;
for(contador = 0; contador < MAXIMO_VUELTAS; contador++)
{
valor = 0;
valor = read_eeprom(contador * 2) << 8;
valor += read_eeprom(contador * 2 + 1);
if(valor > 0)
{
indice++;
}
mediciones[contador] = valor;
}
}
void guarda_mediciones()
{
int8 contador;
for(contador = 0; contador < indice; contador++)
{
write_eeprom(contador * 2, mediciones[contador] >> 8);
write_eeprom(contador * 2 + 1, mediciones[contador] & 0xFF);
}
for(contador = indice; contador < MAXIMO_VUELTAS; contador++)
{
write_eeprom(contador * 2, 0);
write_eeprom(contador * 2 + 1, 0);
}
}
void main()
{
int8 buzzer;
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_128);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
set_tris_a(0);
set_tris_b(3); // 00000011
port_b_pullups(true);
ext_int_edge(L_TO_H);
activa_interrupcion_rb();
enable_interrupts(GLOBAL);
buzzer = 0;
lcd_init();
lee_mediciones();
printf(lcd_putc, "Apunte el lasernhacia el LDR");
set_tris_b(0x13); // 00000011
estado = CALIBRADO;
for(;;)
{
switch(estado)
{
case CALIBRADO:
if(input(PIN_B0) == 0)
{
output_high(LUZ);
if(buzzer == 0)
{
activa_interrupcion_timer();
buzzer = 1;
}
}
else
{
output_low(LUZ);
buzzer = 0;
}
break;
case INICIO:
output_low(LUZ);
datos(TRUE);
estado = PREPARADO;
break;
case ESPERANDO:
case CORRIENDO:
datos(FALSE);
delay_ms(9);
break;
case PARADA:
disable_interrupts(INT_TIMER1);
disable_interrupts(INT_EXT);
putchar(0xFF);
putchar(0xFF);
guarda_mediciones();
delay_ms(500);
estado = INICIO;
break;
}
}
}