Autor Tema: equivalencia millis de arduino en ccs?  (Leído 4399 veces)

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

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 276
equivalencia millis de arduino en ccs?
« en: 05 de Junio de 2020, 15:58:20 »
cordial saludo,
quisiera preguntar  si en "CCS" hay una funcion similar al "millis" de arduino para manejar temporizadores sin que el pic se quede esperando salir de este.
Gracias de antemano.
Si algo parece complicado... es por que esta mal explicado.

Desconectado remi04

  • PIC24F
  • *****
  • Mensajes: 657
Re:equivalencia millis de arduino en ccs?
« Respuesta #1 en: 05 de Junio de 2020, 20:13:31 »
Sin recurrir a un RTOS , a la función millis(); se le puede hacer un port de una forma muy sencilla mediante el uso de un timer del pic conectado al oscilador y una interrupción Para ese timer cuyo handler calcule e incremente la variable de 32 bits ms y ya de paso, otra variable también de 32 bits para los us en el mismo handler y así aprovechas y haces port también de la función micros();

 

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 276
Re:equivalencia millis de arduino en ccs?
« Respuesta #2 en: 06 de Junio de 2020, 12:25:05 »
Sin recurrir a un RTOS , a la función millis(); se le puede hacer un port de una forma muy sencilla mediante el uso de un timer del pic conectado al oscilador y una interrupción Para ese timer cuyo handler calcule e incremente la variable de 32 bits ms y ya de paso, otra variable también de 32 bits para los us en el mismo handler y así aprovechas y haces port también de la función micros();

 
gracias por tu respuesta, lo de los timer lo comprendo, me perdi cuando dices hacer un port, que quieres decir con esto?.
gracias...
Si algo parece complicado... es por que esta mal explicado.

Desconectado remi04

  • PIC24F
  • *****
  • Mensajes: 657
Re:equivalencia millis de arduino en ccs?
« Respuesta #3 en: 06 de Junio de 2020, 13:03:22 »
Sin recurrir a un RTOS , a la función millis(); se le puede hacer un port de una forma muy sencilla mediante el uso de un timer del pic conectado al oscilador y una interrupción Para ese timer cuyo handler calcule e incremente la variable de 32 bits ms y ya de paso, otra variable también de 32 bits para los us en el mismo handler y así aprovechas y haces port también de la función micros();

 
gracias por tu respuesta, lo de los timer lo comprendo, me perdi cuando dices hacer un port, que quieres decir con esto?.
gracias...

   Es una forma de decir que implementas una función propia de un compilador/sistema/dispositivo adaptándola o reescribiéndola para que funcione y se pueda usar en otros que no lo implementaban. 


Desconectado Eduardo2

  • PIC24H
  • ******
  • Mensajes: 1004
Re:equivalencia millis de arduino en ccs?
« Respuesta #4 en: 06 de Junio de 2020, 14:15:00 »
... me perdi cuando dices hacer un port, que quieres decir con esto?.

Anglicismo de "portar"     ;-)

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 276
Re:equivalencia millis de arduino en ccs?
« Respuesta #5 en: 10 de Junio de 2020, 10:10:25 »
 :? no estoy relacionado con el termino, seria posible por favor y me comparten un pequeño ejemplo..
Si algo parece complicado... es por que esta mal explicado.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:equivalencia millis de arduino en ccs?
« Respuesta #6 en: 10 de Junio de 2020, 12:37:52 »
Codigo de Arduino:

Código: C
  1. unsigned long millis()
  2. {
  3.         unsigned long m;
  4.         uint8_t oldSREG = SREG;
  5.  
  6.         // disable interrupts while we read timer0_millis or we might get an
  7.         // inconsistent value (e.g. in the middle of a write to timer0_millis)
  8.         cli();
  9.         m = timer0_millis;
  10.         SREG = oldSREG;
  11.  
  12.         return m;
  13. }
  14.  
  15.  
  16. unsigned long micros() {
  17.         unsigned long m;
  18.         uint8_t oldSREG = SREG, t;
  19.        
  20.         cli();
  21.         m = timer0_overflow_count;
  22. #if defined(TCNT0)
  23.         t = TCNT0;
  24. #elif defined(TCNT0L)
  25.         t = TCNT0L;
  26. #else
  27.         #error TIMER 0 not defined
  28. #endif
  29.  
  30. #ifdef TIFR0
  31.         if ((TIFR0 & _BV(TOV0)) && (t < 255))
  32.                 m++;
  33. #else
  34.         if ((TIFR & _BV(TOV0)) && (t < 255))
  35.                 m++;
  36. #endif
  37.  
  38.         SREG = oldSREG;
  39.        
  40.         return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
  41. }

Como ves usa el Timer0 de los AVR, y este es el setup de esos timers:

Código: C
  1. void init()
  2. {
  3.         // this needs to be called before setup() or some functions won't
  4.         // work there
  5.         sei();
  6.        
  7.         // on the ATmega168, timer 0 is also used for fast hardware pwm
  8.         // (using phase-correct PWM would mean that timer 0 overflowed half as often
  9.         // resulting in different millis() behavior on the ATmega8 and ATmega168)
  10. #if defined(TCCR0A) && defined(WGM01)
  11.         sbi(TCCR0A, WGM01);
  12.         sbi(TCCR0A, WGM00);
  13. #endif
  14.  
  15.         // set timer 0 prescale factor to 64
  16. #if defined(__AVR_ATmega128__)
  17.         // CPU specific: different values for the ATmega128
  18.         sbi(TCCR0, CS02);
  19. #elif defined(TCCR0) && defined(CS01) && defined(CS00)
  20.         // this combination is for the standard atmega8
  21.         sbi(TCCR0, CS01);
  22.         sbi(TCCR0, CS00);
  23. #elif defined(TCCR0B) && defined(CS01) && defined(CS00)
  24.         // this combination is for the standard 168/328/1280/2560
  25.         sbi(TCCR0B, CS01);
  26.         sbi(TCCR0B, CS00);
  27. #elif defined(TCCR0A) && defined(CS01) && defined(CS00)
  28.         // this combination is for the __AVR_ATmega645__ series
  29.         sbi(TCCR0A, CS01);
  30.         sbi(TCCR0A, CS00);
  31. #else
  32.         #error Timer 0 prescale factor 64 not set correctly
  33. #endif
  34.  
  35.         // enable timer 0 overflow interrupt
  36. #if defined(TIMSK) && defined(TOIE0)
  37.         sbi(TIMSK, TOIE0);
  38. #elif defined(TIMSK0) && defined(TOIE0)
  39.         sbi(TIMSK0, TOIE0);
  40. #else
  41.         #error  Timer 0 overflow interrupt not set correctly
  42. #endif

Y este el vector de interrupcion de TIM0

Código: C
  1. #if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  2. ISR(TIM0_OVF_vect)
  3. #else
  4. ISR(TIMER0_OVF_vect)
  5. #endif
  6. {
  7.         // copy these to local variables so they can be stored in registers
  8.         // (volatile variables must be read from memory on every access)
  9.         unsigned long m = timer0_millis;
  10.         unsigned char f = timer0_fract;
  11.  
  12.         m += MILLIS_INC;
  13.         f += FRACT_INC;
  14.         if (f >= FRACT_MAX) {
  15.                 f -= FRACT_MAX;
  16.                 m += 1;
  17.         }
  18.  
  19.         timer0_fract = f;
  20.         timer0_millis = m;
  21.         timer0_overflow_count++;
  22. }

Algunas definiciones:

Código: C
  1. #define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
  2.  
  3. // the whole number of milliseconds per timer0 overflow
  4. #define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
  5.  
  6. // the fractional number of milliseconds per timer0 overflow. we shift right
  7. // by three to fit these numbers into a byte. (for the clock speeds we care
  8. // about - 8 and 16 MHz - this doesn't lose precision.)
  9. #define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
  10. #define FRACT_MAX (1000 >> 3)

Entonces necesitas portar algunas cosas:
- Las partes especificas del codigo que son de Arduino a CSS
- Las partes especificas del codigo que involucren manejos de los modulos y registros de los microcontroladores
- Correccion en caso de necesitarse sobre los tiempos debido a distintos modos de funcionamiento de los modulos.


Ejemplo... La interrupcion, lo unico a cambiar es la parte de la definicion de la interrupcion:

#int_TIMER0

Código: C
  1. void TIMER0_isr(void)
  2. {
  3.         unsigned long m = timer0_millis;
  4.         unsigned char f = timer0_fract;
  5.  
  6.         m += MILLIS_INC;
  7.         f += FRACT_INC;
  8.         if (f >= FRACT_MAX) {
  9.                 f -= FRACT_MAX;
  10.                 m += 1;
  11.         }
  12.  
  13.         timer0_fract = f;
  14.         timer0_millis = m;
  15.         timer0_overflow_count++;
  16. }

Portada la interrupcion! Veamos la funcion millis, guarda el registro status y desactiva la interrupcion del timer0, el registro status en CSS no nos importa, lo que si debemos hacer es detener la interrupcion

Código: C
  1. unsigned long millis()
  2. {
  3.         unsigned long m;
  4.         disable_interrupts(INT_TIMER0);
  5.         m = timer0_millis;
  6.         enable_interrupts(INT_TIMER0);
  7.         return m;
  8. }

Estos son algunos ejemplos, obviamente falta la parte mas "compleja".
El setup de los Timers...

Desconectado Eduardo2

  • PIC24H
  • ******
  • Mensajes: 1004
Re:equivalencia millis de arduino en ccs?
« Respuesta #7 en: 10 de Junio de 2020, 16:35:47 »
Podés usar la directiva  de CCS  #USE TIMER .

El código es muy similar con la diferencia que millis() usa una interrupción cada 1.024 ms  y hace un ajuste a la cuenta para que la lectura sea n realmente milisegundos transcurridos.

Un ejemplo:

Código: [Seleccionar]
#use timer(TIMER=0,TICK=1ms,BITS=16,NOISR)   
// En realidad no es 1ms sino 1.024ms
// overflow cada 65" . 
// Pueden usarse 8/16 o 32 bits

........

void main(void){

    signed int16 T0 ;

    set_tris_b(0) ;

    T0 = get_ticks() + 1000 ;
    while(1){
        if((get_ticks()-T0)>0 ){
            output_toggle(PIN_B0);
            T0 = get_ticks() + 1000 ;
        }
    }
}

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 276
Re:equivalencia millis de arduino en ccs?
« Respuesta #8 en: 12 de Junio de 2020, 08:11:57 »
Eduardo2, KILLERJC Gracias por los ejemplos y aclaraciones.
ya voy entendiendo,, básicamente es tomar como ejemplo las funciones de "arduino" y llevarlas o acomodarlas al lenguaje de "CCS" .
Finalmente les pregunto, si tengo declarado, "#define DELAY 800" , como podría modificar este valor mientras este corriendo el programa?
por ejemplo, tengo un led parpadeando cada 800 milisegundos y en algún momento presiono un botón y espere un dato por el puerto serie y pueda cambiar 800 por 2000?

Código: C
  1. #include <12F508.h>
  2. //#device ADC=10
  3.  
  4. #fuses PROTECT,NOWDT,NOMCLR
  5. //#FUSES NOBROWNOUT               //No brownout reset
  6. //#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
  7.  
  8. #use delay(internal=4000000)
  9. //#use rs232(baud=2400,parity=N,xmit=PIN_B0,bits=8,stream=PORT1) //rcv=PIN_B1
  10. #ORG 0X50, 0X01FF    //CODIGO A PARTIR DE LA LINEA 50, SON 512 LINEAS    
  11.  #BYTE PORTB=0X06  
  12.   //#USE FAST_io (b)
  13. // #USE STANDARD_io (b)
  14. #use FIXED_IO( B_outputs=PIN_B5,PIN_B4 )
  15.  
  16. #DEFINE MEDIAS PIN_B0
  17. #DEFINE BAJAS  PIN_B1
  18. #DEFINE ALTAS  PIN_B2
  19. #DEFINE EXP    PIN_B4
  20. #DEFINE LED    PIN_B5
  21. //#IGNORE_WARNINGS 202, 203
  22. //int contador =0;
  23.  
  24. #define DELAY 800
« Última modificación: 12 de Junio de 2020, 08:22:06 por johenrod »
Si algo parece complicado... es por que esta mal explicado.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:equivalencia millis de arduino en ccs?
« Respuesta #9 en: 12 de Junio de 2020, 09:44:41 »
Es que el define es simplemente un nombre que le estas poniendo a ese numero, es unicamente para tu ayuda (mas legible, facilidad para cambiarlo en multiples puntos, etc)

Es decir, DELAY y 800 es lo mismo, cuando el programa se compila (mucho antes del runtime), el mismo compilador reemplaza todos los DELAY que encuentre en el codigo con el numero 800. A lo que voy y si no se entiende.. No hay mas diferencia que tenerlo asi:

Código: C
  1. delay_ms(800);

Es decir una constante, si quisieras realmente variarlo, entonces ese define lo vas a tener que quitar y crear una variable para eso

Código: C
  1. int16 mydelay = 800;
  2.  
  3. delay_ms(mydelay);

Entonces ahora SI podes cambiar esa variable y modificar el delay con tu programa.

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 276
Re:equivalencia millis de arduino en ccs?
« Respuesta #10 en: 12 de Junio de 2020, 10:05:50 »
Es que el define es simplemente un nombre que le estas poniendo a ese numero, es unicamente para tu ayuda (mas legible, facilidad para cambiarlo en multiples puntos, etc)

Es decir, DELAY y 800 es lo mismo, cuando el programa se compila (mucho antes del runtime), el mismo compilador reemplaza todos los DELAY que encuentre en el codigo con el numero 800. A lo que voy y si no se entiende.. No hay mas diferencia que tenerlo asi:

Código: C
  1. delay_ms(800);

Es decir una constante, si quisieras realmente variarlo, entonces ese define lo vas a tener que quitar y crear una variable para eso

Código: C
  1. int16 mydelay = 800;
  2.  
  3. delay_ms(mydelay);

Entonces ahora SI podes cambiar esa variable y modificar el delay con tu programa.
uff, mas claro imposible..
Ya tengo como enfrentarme al programa que necesito.
Mil gracias por la ayuda que me han brindado, ustedes son muy tesos para esto de la programación.
Si algo parece complicado... es por que esta mal explicado.


 

anything