Autor Tema: Medir tiempo desde el inicio del programa  (Leído 8912 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Estorki

  • PIC10
  • *
  • Mensajes: 10
Medir tiempo desde el inicio del programa
« en: 18 de Febrero de 2012, 14:23:03 »
Buenas, estoy haciendo una conversión de código desde Arduino al CCS para PIC 18f452

Llevo ya alrededor de 1500 lineas de código pero ahora me he encontrado con un problema.
Resulta que Arduino tiene una función millis () que directamente te entrega el tiempo en milisegundos desde que comenzo el programa.
http://arduino.cc/en/Reference/millis

Ahora necesito alguna función/código que me proporcione esto mismo en C para CCS. La verdad, no soy ningun experto en programación de PICs, he tratado de buscar información al respecto y solo he encontrado gente hablando sobre pequeñas mediciones entre pulsaciones y tal usando timers, que sea dicho de paso aun no he echo nada con ellos. Por si sirve de algo pretendo ponerle un oscilador de 20Mhz


Ya sé que es mucho pedir, pero algún alma caritativa podría pasarme alguna función que haga lo mismo que la función millis() de Arduino ?


Realmente me salvaría el culo ((:-)) Gracias
« Última modificación: 18 de Febrero de 2012, 16:19:28 por Estorki »

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: Medir tiempo desde el inicio del programa
« Respuesta #1 en: 18 de Febrero de 2012, 14:40:41 »
lo tendras que hacer tu, el arduino es eso un pic con funciones programadas, como un pic con librerias muy sencillo.

Lo ideal es que actives un timer y cada interrupcion del timer aumentas una variable, luego haces los calculos segun el timer y oscilador y obtienes el tiempo transcurrido.

Desconectado Estorki

  • PIC10
  • *
  • Mensajes: 10
Re: Medir tiempo desde el inicio del programa
« Respuesta #2 en: 19 de Febrero de 2012, 01:14:16 »
Muchas gracias Merlinz por la orientación.

Me he puesto manos a la obra leyendo el datasheet del 18f452 y ya tengo bastante clara su configuración

T0CON = 10000111
20Mhz, 16bits, 1:256, cada incremento son 51.2us, si pongo una precarga de 6942 el contador se desborda cada 3000.012ms (es lo más cercano a 3 segundos que se puede conseguir con esta configuración).

Pero tengo un par de problemas:
1- Si pongo en mi programa T0CON=0b10000111 me dice que T0CON no existe :S
Si intento escribir cada uno por separador en plan; TMR0ON=1; ...etc. tampoco me deja
En definitiva, que no puedo configurar el byte T0CON del timer 0.

2- Para cargar la precarga debería usar el siguiente comando? set_timer0(6942);
Como haría para que se carge esa precarga automáticamente tras cada desborde?

3- Qué interrupciones debo activar para que funcione?


Muchisimas gracias!

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: Medir tiempo desde el inicio del programa
« Respuesta #3 en: 19 de Febrero de 2012, 11:47:27 »
el CCS para poder usar los registros individualmente tienes que poner algo de use_fast_io o algo asi recuerdo, si no se configura con el setup_timer o una funcion asi, mirate el menu derecho de la libreria ahi te viene todo explicado.

Desconectado jhozate

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1698
Re: Medir tiempo desde el inicio del programa
« Respuesta #4 en: 19 de Febrero de 2012, 12:30:35 »
el use_fast_io corresponde a la configuracion de los puertos.  El ccs tiene funciones para la configuracion de timers entre otros. Puedes buscar tanto en la ayuda de ccs y/o mirar el archivo 18F452.h.
Si deseas configurar tu mismo el registro entonces debes hacer
Código: CSS
  1. #byte T0CON= direccion del registro

Pienso, si deseas medir el tiempo que dura la ejecucion de una iteración del programa, enciende un led al inicio y apagalo al final de la iteración, y mides con osciloscopio cuanto tardó..no?? serviría?
« Última modificación: 19 de Febrero de 2012, 12:37:54 por jhozate »
Ser Colombiano es un Premio, Saludos desde CALI-COLOMBIA

Desconectado Estorki

  • PIC10
  • *
  • Mensajes: 10
Re: Medir tiempo desde el inicio del programa
« Respuesta #5 en: 19 de Febrero de 2012, 14:22:35 »
El problema es que no es algo tan sencillo como encender y apagar un led.
Estoy traduciendo desde Arduino a PIC el proyecto de Photoduino (aunque tambien quiero añadirle recepción infraroja y control sobre dos motores paso a paso paro algunas funciones que necesito):

http://www.photoduino.com/es/

Entre otras cosas se utilizan muchas variables de retardos de tiempo de levantamiento de espejo de la cámara, tiempos muertos, se usan barreras para fotografía en alta velocidad, también hay que configurar intervalometros para sacar fotos espaciadas un tiempo constante que pueden ser segundos, minutos, horas... y necesitan una base de tiempos.

Como referencia para todas estas necesidades de tiempo, en arduino usa la función milis(). Si la llamas en diferentes peridos de tiempo y lo restas, te queda el tiempo que ha transcurrido, por ejemplo.


Entonces bueno, ahí ando peleandome con el timer 0, porque conozco el lenguaje C, pero llevo poco tiempo estudiando CCS. Ahora me estoy enterando que tengo que coner algo parecido a la siguiente estructura para hacer una rutina cuando desborde (aunque tampoc estoy seguro de que sea correcta):

#int_rtcc
void handle_rtcc_int()
   {
   }
« Última modificación: 19 de Febrero de 2012, 14:26:35 por Estorki »

Desconectado Estorki

  • PIC10
  • *
  • Mensajes: 10
Re: Medir tiempo desde el inicio del programa
« Respuesta #6 en: 22 de Febrero de 2012, 17:51:11 »
Como la finalidad del foro es compartir, os escribo como he dejado el programa de prueba para el timer0 + algo de info que me es util en mis primeras pruebas rogramando pics


Código: [Seleccionar]
////////////////////////////////////////////////////////////////////////////////////
//
// Fuses
//
////////////////////////////////////////////////////////////////////////////////////
/*
#FUSES NOWDT           //No Watch Dog Timer
#FUSES WDT128          //Watch Dog Timer uses 1:128 Postscale
#FUSES HS              //High speed Osc (> 4mhz)
#FUSES NOPROTECT       //Code not protected from reading
#FUSES BROWNOUT_NOSL   //Brownout enabled during operation, disabled during SLEEP
#FUSES BROWNOUT        //Reset when brownout detected
#FUSES BORV20          //Brownout reset at 2.0V
#FUSES PUT             //Power Up Timer
#FUSES NOCPD           //No EE protection
#FUSES STVREN          //Stack full/underflow will cause reset
#FUSES NODEBUG         //No Debug mode for ICD
#FUSES NOLVP           //No low voltage prgming, B3(PIC16) or B5(PIC18)used for I/O
#FUSES NOWRT           //Program memory not write protected
#FUSES NOWRTD          //Data EEPROM not write protected
#FUSES IESO            //Internal External Switch Over mode enabled
#FUSES FCMEN           //Fail-safe clock monitor enabled
//#FUSES PBADEN          //PORTB pins are configured as analog input channels on RESET
#FUSES NOWRTC          //configuration not registers write protected
#FUSES NOWRTB          //Boot block not write protected
#FUSES NOEBTR          //Memory not protected from table reads
#FUSES NOEBTRB         //Boot block not protected from table reads
#FUSES NOCPB           //No Boot Block code protection
#FUSES MCLR            //Master Clear pin enabled
#FUSES LPT1OSC         //Timer1 configured for low-power operation
#FUSES NOXINST         //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
//#FUSES LP                       //Low power osc < 200 khz
 */////////////////////////    FIN FUSES    //////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////
//
// INICIALIZACIONES GENERALES
//
////////////////////////////////////////////////////////////////////////////////////
/*
  delay_ms(333);                  // Espero a que todo se estabilice e ...
  disable_interrupts(global);     // Inicializo el Micro y ...
  disable_interrupts(int_timer1); // deshabilitando todo lo no necesario ...
  disable_interrupts(int_rda);
  disable_interrupts(int_ext);
  disable_interrupts(int_ext1);
  disable_interrupts(int_ext2);
  setup_adc_ports(NO_ANALOGS);
  setup_adc(ADC_OFF);
  setup_spi(FALSE);
  setup_psp(PSP_DISABLED);
  setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
  setup_timer_0(RTCC_OFF);
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
  setup_timer_2(T2_DISABLED,0,1);
  setup_timer_3(T3_DISABLED);
  setup_comparator(NC_NC_NC_NC);
  setup_vref(FALSE);
  port_b_pullups(FALSE);
  delay_ms(333);
  //setup_oscillator(OSC_8MHZ|OSC_TIMER1|OSC_31250|OSC_PLL_OFF);      //Creo que no existe en 18f4520
  */

////////////////////////////////////////////////////////////////////////////////////
//
// Funciones básicas
//
////////////////////////////////////////////////////////////////////////////////////
/*
 #include <lib_int_eeprom.c>        //Manejar eeprom con mas de 8 bits, librería larga, no funciona bien
 #include <lib_int_eeprom_basica.c> //Manejar eeprom con mas de 8 bits, librería corta, hay que pegarla el el main.c
 write_eeprom_16bits(0x04, valor);
 read_eeprom_16bits(0x04)
 write_eeprom(0x00, valor);         //Librería estandar para manejar 4bits en la eeprom
 read_eeprom(0x00);
 printf("%f",read_eeprom_16bits(0x04));
 
 set_tris_A(0xFF);                  //Puerto A como entrada
 setup_adc_ports(all_analog);       //Configurar los pines RA0, RA1, RA3 como entradas analógicas
 setup_adc(ADC_CLOCK_DIV_32);       // Configurar el tiempo de lectura para cada dato analógico. Hay que configurarlo en función de los Mhz del micro.
 portB = 0;                         // Limpiamos puertos
 LATB=0;                            // Limpiamos puertos, mejor usar LATx para las salidas ¿?
 
 output_high(PIN_B0);
 output_bit(PIN_B2,1);
 output_low(PIN_B0);        
 output_bit(PIN_B2,0);
 input(PIN_A0)             //Pin a 1
 !input(PIN_A0)            //Pin a 0
 Output_Toggle(PIN_E0);    //cambiar estado
  
 lcd_init();
 set_adc_channel(0);
 delay_ms(2);
 valor1 = read_adc();
 delay_ms(2);
 lcd_putc("Bienvenido");
 lcd_gotoxy(1,1);  
 printf(lcd_putc,"\V RA0: %lu", valor1);
 setup_ccp1(CCP_PWM);    //ccp1 modo PWM
 read_eeprom(address);
 write_eeprom(address, byte);
 */////////////////////////    FIN FUNCIONES BÁSICAS    //////////////////////////////////////////




#include <18F452.h>
#device adc=16
#include <STDIO.h>

#FUSES NOWDT           //No Watch Dog Timer
#FUSES NOBROWNOUT      //No brownout reset
#FUSES NOLVP           //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(clock=20000000)
#include "flex_lcd.c"

#byte PORTA=0xF80
#byte PORTB=0xF81
#byte PORTC=0xF82
#byte PORTD=0xF83
#byte PORTE=0xF84
#byte LATA=0xF89
#byte LATB=0xF8A
#byte LATC=0xF8B
#byte LATD=0xF8C
#byte LATE=0xF8D

void write_eeprom_16bits(int address, long* val){
  int pLow, pHigh;
  pLow = val;
  pHigh = val>>8;
  write_eeprom(address,pHigh);
  delay_ms(12);
  ++address;
  write_eeprom(address,plow);
  delay_ms(12);
}
long read_eeprom_16bits(int address){
  int pLow, pHigh;
  long result;
  pHigh = read_eeprom(address);
  ++address;
  pLow = read_eeprom(address);
  result=(pHigh<<8);
  result+=pLow;
  return result;
}



  
////////////////////////////////////////////////////////////////////////////////////
//
// Interrupción por Externa por Cambio de Flanco en RB0
//
////////////////////////////////////////////////////////////////////////////////////

int16 cont_desbordes_t0 = 0;


#int_rtcc
void handle_rtcc_int()
   {cont_desbordes_t0 ++;
   Set_timer0(6942);
   }     //   milisegundos = cont_desbordes_t0*3000 + (GET_TIMER0()-6942)*0.0512;
 



////////////////////////////////////////////////////////////////////////////////////
//
// Main
//
////////////////////////////////////////////////////////////////////////////////////
void main()
{
  ////////////////////////////////////////// INICIALIZACIONES GENERALES
  delay_ms(333);                  // Espero a que todo se estabilice e ...
  disable_interrupts(global);     // Inicializo el Micro y ...
  disable_interrupts(int_timer1); // deshabilitando todo lo no necesario ...
  disable_interrupts(int_rda);
  disable_interrupts(int_ext);
  disable_interrupts(int_ext1);
  disable_interrupts(int_ext2);
  setup_adc_ports(NO_ANALOGS);
  setup_adc(ADC_OFF);
  setup_wdt(WDT_OFF);
  setup_spi(FALSE);
  setup_psp(PSP_DISABLED);
  setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
  setup_timer_0(RTCC_OFF);
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
  setup_timer_2(T2_DISABLED,0,1);
  setup_timer_3(T3_DISABLED);
  
  

  
    /////////////////////////////////////////// INICIALIZACIONES PERTINENTES A LA APLICACION

 setup_timer_0(RTCC_DIV_256); // Ajusto divisor de TMR0 con una divisor de 256
 enable_interrupts(int_rtcc);
 enable_interrupts(global);               // Habilito las interrupciones necesarias

 set_tris_C(0x00);
 set_tris_B(0x00);
 set_tris_E(0x00);
 LATC=0;
 LATB=0;
 LATE=0;

 int16 segundos = 0;
 int16 milisegundos = 0;


 lcd_init();
 lcd_gotoxy(1,1);  

 
 SET_RTCC(0);
 while (1)
 {lcd_gotoxy(1,1);
 printf(lcd_putc,"Num desbor.: %lu", cont_desbordes_t0);
 lcd_gotoxy(1,2);
 segundos = cont_desbordes_t0*3 + (GET_TIMER0()-6942)*0.0000512;
 milisegundos = cont_desbordes_t0*3000 + (GET_TIMER0()-6942)*0.0512;
 printf(lcd_putc,"Segundos: %lu", milisegundos);
 }


}
« Última modificación: 22 de Febrero de 2012, 17:56:21 por Estorki »

Desconectado edgar_soliz

  • PIC10
  • *
  • Mensajes: 2
Re: Medir tiempo desde el inicio del programa
« Respuesta #7 en: 28 de Julio de 2013, 12:19:49 »
veo que el tema ya es muy antiguo pero pongo un codio en CCS que tiene las mismas características de la función millis en Arduino espero que les sirva:
Código: CSS
  1. #include <16f877A.h>
  2. #fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT,NOCPD,NOWRT
  3. #use delay (clock=4000000)
  4. //#use fast_IO(B)
  5. #BYTE PORTB=0x06   // puerto B
  6. #BYTE TRISB=0x86
  7. #include "lcd.c"
  8.  
  9.  
  10. long millis;
  11. long tiempo;
  12. long cont;
  13.  
  14. #INT_TIMER0
  15. void TIMER0_isr()
  16. {
  17.    millis=millis+1;
  18.    set_timer0(6);
  19. }
  20.  
  21. void main()
  22. {
  23.  
  24.    TRISB=0x00;
  25.    PORTB=0;
  26.    output_high(PIN_B0);
  27.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
  28.    set_timer0(6);
  29.    enable_interrupts(INT_TIMER0);
  30.    enable_interrupts(GLOBAL);
  31.    lcd_init();
  32.    tiempo=millis;
  33.    while(TRUE)
  34.    {
  35.       if(millis-tiempo>=1000)
  36.       {
  37.          lcd_gotoxy(5,2);
  38.          printf(lcd_putc,"\Conv=%lu ",millis-tiempo);
  39.          lcd_gotoxy(1,1);
  40.          printf(lcd_putc,"\Cont=%lu ",cont++);    
  41.          PORTB=PORTB|0b00000001;
  42.          PORTB=PORTB|0b00000100;
  43.          tiempo=millis;
  44.       }  
  45.    }
  46.  
  47.  
  48. }
« Última modificación: 28 de Julio de 2013, 12:30:31 por edgar_soliz »


 

anything