Autor Tema: Mini curso "Programación en XC8"  (Leído 588215 veces)

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

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Mini curso "Programación en XC8"
« Respuesta #255 en: 03 de Septiembre de 2014, 13:20:09 »
Es normal. El timer sigue contando pulsos, mientras que el CCP mantiene el valor capturado del timer sin cambios.

¿Cómo ves los valores de los registros? ¿Qué frecuencia tiene la señal del timer?


Saludos.

Desconectado Miquel_S

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1251
Re: Mini curso "Programación en XC8"
« Respuesta #256 en: 03 de Septiembre de 2014, 13:36:59 »
Es normal. El timer sigue contando pulsos, mientras que el CCP mantiene el valor capturado del timer sin cambios.

¿Cómo ves los valores de los registros? ¿Qué frecuencia tiene la señal del timer?


Saludos.
Hola Picuino podria ser lo que comentas, ya que el valor de la parte baja del TMR1 siempre es superior al CCPR1L. Los valores de los registros los veo a traves de la simulacion.
¿No hay manera de tener una lectura exacta del valor del TMR1?
He intentado parar el timer antes de cargarlo pero hace lo mismo.

Saludos!
« Última modificación: 03 de Septiembre de 2014, 14:41:05 por Miquel_S »
Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Mini curso "Programación en XC8"
« Respuesta #257 en: 03 de Septiembre de 2014, 18:02:22 »
La captura es la lectura exacta.

Puedes hacer una prueba:
Metes un tren de 10 pulsos
Una vez que han terminado los pulsos das un pulso de captura.
Lees los dos valores y deben ser ambos iguales a 10

Los pulsos puedes darles con el mismo pic conectando pines entre sí.

Saludos.


Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Mini curso "Programación en XC8"
« Respuesta #258 en: 03 de Septiembre de 2014, 18:07:31 »
También hay otro problema. Si el micro no tiene la lectura de ambos CCPR1 sincronizada (no he mirado el datasheet), entonces es mucho más dificil en el mundo real.

Para sincronizarles debes leer el HIGH luego el LOW y luego otra vez el HIGH. A partir de esas 3 lecturas hay que programar todos los posibles casos.
Puede que prefieras pasarte a otro micro que sincronize por hardware las dos lecturas HIGH y LOW

Saludos.

Desconectado Miquel_S

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1251
Re: Mini curso "Programación en XC8"
« Respuesta #259 en: 04 de Septiembre de 2014, 04:15:43 »
Gracias Picuino por la info, aunque estas volando muy por encima de mi  :shock: pero intento aprender, de ser como tu dices las mediciones que se puedan hacer con el sensor HC-SR04 no son reales.
Lo digo por lo del eco del sensor que al ser recibido captura los valores del timer, pero si el timer tiene unos valores y el CCP otros no es real.
¿ O me equivoco?

Gracias.
Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Mini curso "Programación en XC8"
« Respuesta #260 en: 04 de Septiembre de 2014, 09:23:47 »
No te estoy contando cosas muy complicadas. Si te parece así es que no me he explicado bien o que no me has entendido.

Vamos a empezar por el principio.
En el módulo de captura hay dos señales:
   La primera es el reloj que hace que el timer cuente y aumente su valor.
   La segunda es la señal de captura, que hace que el modulo de captura lea el valor del timer y lo almacene.

¿Cuáles son estas dos señales en tu circuito?


Saludos.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Mini curso "Programación en XC8"
« Respuesta #261 en: 04 de Septiembre de 2014, 16:48:10 »
Para medir la duración de pulso de ese sensor, lo mejor es poner como señal de reloj al propio reloj del sistema con un preescaler para reducir su frecuencia a unos 200kHz.
La captura del valor del timer puedes hacerla por soft sin el módulo de captura porque ese sensor tiene un incertidumbre grande, de +-10us.

En cuanto a tu programa, es bastante difícil de entender porque no se pueden ver los bits individuales que activas en la configuración.
Luego subo un programa Python interesante que he programado para solucionarlo.

Saludos.
« Última modificación: 04 de Septiembre de 2014, 16:55:04 por Picuino »

Desconectado Miquel_S

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1251
Re: Mini curso "Programación en XC8"
« Respuesta #262 en: 04 de Septiembre de 2014, 17:45:59 »
Para medir la duración de pulso de ese sensor, lo mejor es poner como señal de reloj al propio reloj del sistema con un preescaler para reducir su frecuencia a unos 200kHz.
La captura del valor del timer puedes hacerla por soft sin el módulo de captura porque ese sensor tiene un incertidumbre grande, de +-10us.

En cuanto a tu programa, es bastante difícil de entender porque no se pueden ver los bits individuales que activas en la configuración.
Luego subo un programa Python interesante que he programado para solucionarlo.

Saludos.
:shock: :shock: :shock: :shock: :shock: Te cuento, yo la electrónica no se si por suerte o desgracia la tengo como un hobby,  y como tengo un montón de proyectos sin terminar por quedarme estancado y no saber solucionarlo, he decidido coger un pic en este caso un 16f876A
y no dejarlo hasta saber como funciona como mínimo en un 80%.
Y ahora le toca al CCP en modo captura, y lo único que intento es poner el timer1 a contar y al recibir un pulso en RC2 me haga la captura del timer, luego ya veremos que hago con todo lo que haya aprendido  :D

Saludos y gracias por tu tiempo.
Miquel.
Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas.

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re: Mini curso "Programación en XC8"
« Respuesta #263 en: 04 de Septiembre de 2014, 21:48:09 »
Miguel, es como dice Picuino.

El timer está contando e inncrementando constantemente los registros TMR1L y TMR1H. Cuando se da la condicion de captura (y se produce la interrupcion) se almacena de forma inmediata los valores de TMR1L y TMR1H en los registros CCPR1L y CCPR1H, pero ni bien se ejecute una instruccion más, el registro TMR1 irá cambiando. Por lo que no debes preocuparte porque no coincidan, nunca (creo) vas a poder ver en pantalla que coincidan. Lo que sí tenes que estar seguro es que en CCPR1 tendras los 16 bits del timer al momento de producirse la condicion de captura.

Para ese sensor, si queres usar el CCP, lo que debería hacer configurar el CCP para que interrumpa en el RISING EDGE, luego poner en 1 el pin correspondiente a TRG, hacer un delay de unos uSeg, poner a 0 el TRG. En la interrupcion del CCP almacenas los valores de CCPR1 en una variable global, configuras para que interrumpa nuevamente el CCP en el falling edge y sales de la interrupcion. Cuando el sensor detecte el TRIGER, luego de unos mseg pondrá él solo la señal de ECO en 1 y cuando reciba el Eco de la señal de US pondrá en 0 dicha señal con lo que se disparará por segunda vez la interrupcion y ahi deberás restar el contenido de CCPR1 a la variable global.

Escrito así es complicado, pero analizalo un poco!

saludos
-
Leonardo Garberoglio

Desconectado Miquel_S

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1251
Re: Mini curso "Programación en XC8"
« Respuesta #264 en: 05 de Septiembre de 2014, 04:08:07 »
Gracias elgarbe por la excelente explicación, voy a ver si entre lo tuyo y la explicación de Picuino consigo hacer algo.

De nuevo gracias a los dos.
« Última modificación: 05 de Septiembre de 2014, 04:42:52 por Miquel_S »
Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Mini curso "Programación en XC8"
« Respuesta #265 en: 05 de Septiembre de 2014, 12:05:10 »
Hola Miquel, prueba a programar los registros con este código:

http://www.todopic.com.ar/foros/index.php?topic=43374.msg359161#msg359161

Saludos.

Desconectado Miquel_S

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1251
Re: Mini curso "Programación en XC8"
« Respuesta #266 en: 05 de Septiembre de 2014, 14:54:37 »
Gracias Picuino revisare el post que me ofreces.

Saludos!
Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas.

Desconectado illusionista_86

  • PIC10
  • *
  • Mensajes: 23
Re: Mini curso "Programación en XC8"
« Respuesta #267 en: 12 de Octubre de 2014, 22:34:31 »
a petición de un compañero voy a poner unos ejemplos que he realizado para la utilización del "timer0" para el control de servos.

en el siguiente ejemplo se controlan 6 servos, pero es fácilmente ampliable hasta unos 10 servos.

el principio de funcionamiento es, para cada servo se necesitan 20ms para que funcione, pues durante estos 20ms puedo activar tantos servos como pueda, suponiendo que como máximo cada servos en tiempo alto esta 2ms, me caben unos 10 servos en el peor de los casos. Los servos se activan sucesivamente, uno detrás de otro, dentro de estos 20 ms, al llegar al último servo, se vuelve a empezar, eso si, teniendo en cuenta que si la suma de todos los tiempos en alto no llega a los 20ms, se calcula el tiempo que queda para llegar a los 20ms y se dejan todos los servos a 0 durante ese tiempo, aquí el código:

Código: C
  1. /*
  2.  * File:   prueva_servos.c
  3.  * Author: Enrique
  4.  *
  5.  * Created on 11 de octubre de 2014, 18:54
  6.  */
  7.  
  8. #include <p18f2550.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <delays.h>
  12. #include <string.h>
  13. #include <usart.h>
  14. #include <math.h>
  15. #include <float.h>
  16.  
  17.  
  18. #pragma config FOSC=XT_XT, FCMEN=OFF,IESO=OFF,CPUDIV=OSC1_PLL2
  19. #pragma config PWRT=ON,BOR=OFF,BORV=0,WDT=OFF,WDTPS=32768
  20. #pragma config MCLRE=ON,LPT1OSC=OFF,PBADEN=OFF,CCP2MX=OFF
  21. #pragma config STVREN=OFF,LVP=OFF,XINST=OFF,DEBUG=OFF
  22. #pragma config CP0=OFF,CP1=OFF,CP2=OFF,CPB=OFF,CPD=OFF
  23. #pragma config WRT0=OFF,WRT1=OFF,WRT2=OFF
  24. #pragma config WRTB=OFF,WRTC=OFF,WRTD=OFF
  25. #pragma config EBTR0=OFF,EBTR1=OFF,EBTR2=OFF,EBTRB=OFF
  26.  
  27. #define _XTAL_FREQ 8000000
  28. #define LED PORTAbits.RA3
  29. #define SERVO0 PORTBbits.RB2
  30. #define SERVO1 PORTBbits.RB3
  31. #define SERVO2 PORTBbits.RB4
  32. #define SERVO3 PORTBbits.RB5
  33. #define SERVO4 PORTBbits.RB6
  34. #define SERVO5 PORTBbits.RB7
  35. #define _RAND_MAX 180;
  36. #define _RAND_MIN 0;
  37.  
  38. unsigned long T_ON[]={0,0,0,0,0,0},T_OFF=0;
  39. float ms_ton[]={0.0,0.0,0.0,0.0,0.0,0.0};
  40. float ms_toff=0;
  41. float m;
  42. int servo=0;
  43. int pos[]={0,0,0,0,0,0};
  44. float b=0.5;
  45. float pendiente;
  46.  
  47. void calc_tiempos(int grados[]){
  48.  
  49.     pendiente=(2.5-b)/(180.0-0.0);
  50.     for (int i=0;i<6;i++){
  51.         ms_ton[i]=pendiente*(float)grados[i]+0.5;
  52.         T_ON[i]=65536-(unsigned long)((ms_ton[i]/1000.0)*(_XTAL_FREQ)/4.0); // 62556
  53.     }
  54.     ms_toff=20.0-ms_ton[0]-ms_ton[1]-ms_ton[2]-ms_ton[3]-ms_ton[4]-ms_ton[5];
  55.     T_OFF=65536-(unsigned long)((ms_toff/1000.0)*(_XTAL_FREQ)/4.0); // 28516
  56.     printf("Grados 0: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",grados[0],T_ON[0],ms_ton[0],pendiente);
  57.     printf("Grados 1: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",grados[1],T_ON[1],ms_ton[1],pendiente);
  58.     printf("Grados 2: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",grados[2],T_ON[2],ms_ton[2],pendiente);
  59.     printf("Grados 3: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",grados[3],T_ON[3],ms_ton[3],pendiente);
  60.     printf("Grados 4: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",grados[4],T_ON[4],ms_ton[4],pendiente);
  61.     printf("Grados 5: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",grados[5],T_ON[5],ms_ton[5],pendiente);
  62.     printf("T_OFF=%lu, ms_toff=%.2f, pendiente=%.4f\n\r",T_OFF,ms_toff,pendiente);
  63. }
  64.  
  65.  
  66. void putch(unsigned char byte)
  67. {
  68.             TXSTA=0x26;
  69.             SPEN=1;
  70.             TXREG=byte;            /* transmit a character to Serial IO */
  71.             while(!TXIF)continue;
  72.             TXIF=0;
  73. }
  74.  
  75. void interrupt timer0(void){
  76.  
  77.     if(INTCONbits.TMR0IF){
  78.  
  79.         if (servo==0){
  80.             SERVO0=1;
  81.             SERVO1=0;SERVO2=0;SERVO3=0;SERVO4=0;SERVO5=0;
  82.             WriteTimer0(T_ON[0]);
  83.             servo=1;
  84.         }else if(servo==1){
  85.             SERVO1=1;
  86.             SERVO0=0;SERVO2=0;SERVO3=0;SERVO4=0;SERVO5=0;
  87.             WriteTimer0(T_ON[1]);
  88.             servo=2;
  89.         }else if(servo==2){
  90.             SERVO2=1;
  91.             SERVO1=0;SERVO0=0;SERVO3=0;SERVO4=0;SERVO5=0;
  92.             WriteTimer0(T_ON[2]);
  93.             servo=3;
  94.         }else if(servo==3){
  95.             SERVO3=1;
  96.             SERVO1=0;SERVO2=0;SERVO0=0;SERVO4=0;SERVO5=0;
  97.             WriteTimer0(T_ON[3]);
  98.             servo=4;
  99.         }else if(servo==4){
  100.             SERVO4=1;
  101.             SERVO1=0;SERVO2=0;SERVO3=0;SERVO0=0;SERVO5=0;
  102.             WriteTimer0(T_ON[4]);
  103.             servo=5;
  104.         }else if(servo==5){
  105.             SERVO5=1;
  106.             SERVO1=0;SERVO2=0;SERVO3=0;SERVO4=0;SERVO0=0;
  107.             WriteTimer0(T_ON[5]);
  108.             servo=6;
  109.         }else if(servo==6){
  110.             SERVO0=0;SERVO1=0;SERVO2=0;SERVO3=0;SERVO4=0;SERVO5=0;
  111.             WriteTimer0(T_OFF);
  112.             servo=0;
  113.         }
  114.         INTCONbits.TMR0IF=0;
  115.     }
  116.  
  117.  
  118. }
  119.  
  120. void main(void) {
  121.  
  122.     ADCON1 = 0xFF;      // Deshabilita las entradas analogas.
  123.     TRISA=0b000110000;
  124.     TRISB=0b00000011;
  125.     TRISC = 0b11110011; //Coil in RC2 (PWM) and RC3
  126.  
  127.     OpenUSART(USART_TX_INT_OFF &
  128.             USART_RX_INT_ON &       //Activar la interrupcion por la recepcion de dato del buffer de Rx del USART
  129.             USART_ASYNCH_MODE &     //Modo asincrono (fullduplex)
  130.             USART_EIGHT_BIT &       //8 bits de datos
  131.             USART_CONT_RX &         //Recepción continua
  132.             USART_BRGH_HIGH, 51);  //9600 Baudios
  133.  
  134.     OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_1);
  135.     // TiempoTMR0 = (4/Fosc)*(2^bits - ValorTMR0)*Prescaler
  136.     // TiempoTMR0 = (4/8000000)*(2^16 - ValorTMR0)*1
  137.     RCONbits.IPEN = 1;          // Enable interrupt priorities
  138.     INTCONbits.GIE = 1;         // Globally enable interrupts
  139.     INTCONbits.PEIE = 1;
  140.  
  141.     printf("Prueba servos con T0\r\n");
  142.     pos[0]=90;pos[1]=90;pos[2]=90;
  143.     pos[3]=90;pos[4]=90;pos[5]=90;
  144.     calc_tiempos(pos);
  145.     servo=6;
  146.     WriteTimer0(T_OFF);
  147. //    T_ON=62556;
  148. //    T_OFF=28516;
  149.  
  150.  
  151.     while(1){
  152.         if  (PORTAbits.RA4==0){
  153.             pos[0]=rand()%180;pos[1]=rand()%180;pos[2]=rand()%180;
  154.             pos[3]=rand()%180;pos[4]=rand()%180;pos[5]=rand()%180;
  155.             calc_tiempos(pos);
  156.  
  157.             while (PORTAbits.RA4==0){
  158.                    Delay1KTCYx(1);
  159.             }
  160.         }
  161.     }
  162. }

tambien he colgado en el foro los archivos del proyecto y el proteus:
http://www.todopic.com.ar/foros/index.php?topic=43560.0

Desconectado illusionista_86

  • PIC10
  • *
  • Mensajes: 23
Re: Mini curso "Programación en XC8"
« Respuesta #268 en: 12 de Octubre de 2014, 22:41:05 »
dejo otro ejemplo de utilización del timer0 para el control de servos,

en el ejemplo utilizao 6 servos, pero es fácil ampliarlo a tantos servos como se desee.

en este caso TODOS los servos se activan a la vez, de forma que se van desactivado conforme se termine su tiempo en alto, para ello se ordenan los servos según el tiempo en alto, de menor a mayor, y se calcula la diferencia entre el actual menos el anterior, es decir, el primer servo tiene que estar en alto durante 1ms y el segundo durante 1.2ms, con lo cual se calcula el primero para un tiempo de 1ms, el segundo para 0.2ms, y así sucesivamente... en el primer instante se escribe a WriteTimer0 con el valor de 1ms, al desbordar, apaga el servo correspondiente y se vuelve a activar con el valor de 0.2ms, al desbordar desactiva este segundo servo y carga el siguiente.... y asi hasta llegar al final....

con esto podemos poner tantos servos como salidas tengamos en nuestro pic, el código es fácil de modificar.

Código: C
  1. /*
  2.  * File:   prueva_servos.c
  3.  * Author: Enrique
  4.  *
  5.  * Created on 11 de octubre de 2014, 18:54
  6.  */
  7.  
  8. #include <p18f2550.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <delays.h>
  12. #include <string.h>
  13. #include <usart.h>
  14. #include <math.h>
  15. #include <float.h>
  16.  
  17.  
  18. #pragma config FOSC=XT_XT, FCMEN=OFF,IESO=OFF,CPUDIV=OSC1_PLL2
  19. #pragma config PWRT=ON,BOR=OFF,BORV=0,WDT=OFF,WDTPS=32768
  20. #pragma config MCLRE=ON,LPT1OSC=OFF,PBADEN=OFF,CCP2MX=OFF
  21. #pragma config STVREN=OFF,LVP=OFF,XINST=OFF,DEBUG=OFF
  22. #pragma config CP0=OFF,CP1=OFF,CP2=OFF,CPB=OFF,CPD=OFF
  23. #pragma config WRT0=OFF,WRT1=OFF,WRT2=OFF
  24. #pragma config WRTB=OFF,WRTC=OFF,WRTD=OFF
  25. #pragma config EBTR0=OFF,EBTR1=OFF,EBTR2=OFF,EBTRB=OFF
  26.  
  27. #define _XTAL_FREQ 20000000
  28. #define LED PORTAbits.RA3
  29. #define SERVO0 PORTBbits.RB2
  30. #define SERVO1 PORTBbits.RB3
  31. #define SERVO2 PORTBbits.RB4
  32. #define SERVO3 PORTBbits.RB5
  33. #define SERVO4 PORTBbits.RB6
  34. #define SERVO5 PORTBbits.RB7
  35. #define _RAND_MAX 180;
  36. #define _RAND_MIN 0;
  37.  
  38. unsigned long T_ON[]={0,0,0,0,0,0},T_OFF=0;
  39. float ms_ton[]={0.0,0.0,0.0,0.0,0.0,0.0};
  40. float ms_toff=0;
  41. int servo=0;
  42. // tenemos 6 servos más una dimensión mas para el tiempo en off, de la posición
  43. // 0 a la 5, son las posiciones de los 6 servos, la posición 7, siempre será 0, de
  44. // la posición 8 a la 13 son los índices de los servos, que se inicializarán siempre
  45. // de la misma forma como la actual. será como una matriz de 2x7
  46. int pos[2][7]={0,0,0,0,0,0,0,0,1,2,3,4,5,6};
  47. float b=0.5; // coeficiente "b" de la recta.
  48. float pendiente; // pendiente de la recta para pasar la posición a "ms".
  49. int cont=0; // variable para saber qué tiempo estamos activando.
  50.  
  51. void ordenar(){
  52.     // ordenamos la variable "pos" de menor a mayor grado, en cada columna tendremos
  53.     // la posición del motor en la primera fila, y el número del servo al que corresponde
  54.     // en la segunda fila.
  55.     int comp1,comp2,index1,index2;
  56.     for (int i=0;i<6;i++){
  57.         comp1=pos[0][i];
  58.         index1=pos[1][i];
  59.         for (int j=(i+1);j<6;j++){
  60.             comp2=pos[0][j];
  61.             index2=pos[1][j];
  62.             if (comp1>comp2){      
  63.                 pos[0][i]=comp2;
  64.                 pos[1][i]=index2;
  65.                 pos[0][j]=comp1;
  66.                 pos[1][j]=index1;
  67.                 comp1=comp2;
  68.                 index1=index2;
  69.             }
  70.         }
  71.     }
  72. }
  73.  
  74. void calc_tiempos(){
  75.  
  76.     float time_ant;
  77.  
  78.     ordenar();
  79.    
  80.     pendiente=(2.5-b)/(180.0-0.0);
  81.     time_ant=0.0;
  82.     for (int i=0;i<6;i++){
  83.         // con la variable de las posiciones ordenadas, calculamos los tiempos en
  84.         // "ms" de cada una de estas posiciones, como vamos a activar todos los servos
  85.         // a la vez, cremamos una variable "time_ant" que corresponde con el tiempo
  86.         // que esta activado anteriormente ese servo. Por ejemplo: el primer servo se activa
  87.         // durante 0.8 ms, y el segundo 1 ms, con lo cual, el segundo estará 0.2 ms
  88.         // más tiempo encendido que el primero, con lo cual, este 0.2 es el que tenemos
  89.         // que almacenar, ya que los dos servos se han activado a la vez, de igual
  90.         // forma para el resto de servos.
  91.         ms_ton[i]=(pendiente*(float)pos[0][i]+b)-time_ant;
  92.         time_ant=time_ant+ms_ton[i];
  93.         // aqui el valor del TMR0 a escrivir cada vez.
  94.         T_ON[i]=65536-(unsigned long)((ms_ton[i]/1000.0)*(_XTAL_FREQ)/8.0); // 62556
  95.     }
  96.     // el tiempo en off será de 20 ms menos el tiempo del servo que este activo mas tiempo.
  97.     ms_toff=20.0-time_ant;
  98.     T_OFF=65536-(unsigned long)((ms_toff/1000.0)*(_XTAL_FREQ)/8.0); // 28516
  99. //
  100. //    printf("Grados %d: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",pos[1][0],pos[0][0],T_ON[0],ms_ton[0],pendiente);
  101. //    printf("Grados %d: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",pos[1][1],pos[0][1],T_ON[1],ms_ton[1],pendiente);
  102. //    printf("Grados %d: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",pos[1][2],pos[0][2],T_ON[2],ms_ton[2],pendiente);
  103. //    printf("Grados %d: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",pos[1][3],pos[0][3],T_ON[3],ms_ton[3],pendiente);
  104. //    printf("Grados %d: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",pos[1][4],pos[0][4],T_ON[4],ms_ton[4],pendiente);
  105. //    printf("Grados %d: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",pos[1][5],pos[0][5],T_ON[5],ms_ton[5],pendiente);
  106. //    printf("T_OFF=%lu, ms_toff=%.2f, pendiente=%.4f\n\r",T_OFF,ms_toff,pendiente);
  107. //    printf("----------------------------------\n\r");
  108.  
  109. }
  110.  
  111.  
  112. void putch(unsigned char byte)
  113. {
  114.             TXSTA=0x26;
  115.             SPEN=1;
  116.             TXREG=byte;            /* transmit a character to Serial IO */
  117.             while(!TXIF)continue;
  118.             TXIF=0;
  119. }
  120.  
  121. void interrupt timer0(void){
  122.  
  123.     if(INTCONbits.TMR0IF){
  124.  
  125.         // inicializamos con "cont=0" para que todos los servos se activen.
  126.         // en este instante accedemos a "pos" (variable ordenada), y leemos la
  127.         // posición "cont=0" de las variables "T_ON[cont]" y "pos[1][cont], de
  128.         // esta forma accedemos a la posición del servo que menos tiempo tiene que
  129.         // estar activo, en "servo" guardamos el num del servo, y en "WriteTimer0"
  130.         // escribimos el tiempo en ON de este servo. y aumentamos la variable "cont"
  131.  
  132.         // cuando se active este primer timer, accedemos a la sección de este "servo"
  133.         // ponemos a "0" la salida de dicho servo, y escrivimos en "WriteTimer0" el valor
  134.         // del siguiente servo menos activo, y guardamos en "servo" el valor del
  135.         // siguiente servo correspondiente al tiempo activado. aumentamos la variable
  136.         // "cont".... y así hasta el final.
  137.         if (cont==0){
  138.             SERVO0=1;SERVO1=1;SERVO2=1;SERVO3=1;SERVO4=1;SERVO5=1;
  139.             WriteTimer0(T_ON[cont]);
  140.             servo=pos[1][cont];
  141.             cont++;
  142.         }else if (servo==0){
  143.             SERVO0=0;
  144.             WriteTimer0(T_ON[cont]);
  145.             //printf(" servo %d, %ul\n\r",servo,T_ON[cont]);
  146.             servo=pos[1][cont];
  147.             cont++;
  148.         }else if(servo==1){
  149.             SERVO1=0;
  150.             WriteTimer0(T_ON[cont]);
  151.             //printf(" servo %d, %ul\n\r",servo,T_ON[cont]);
  152.             servo=pos[1][cont];
  153.             cont++;
  154.         }else if(servo==2){
  155.             SERVO2=0;
  156.             WriteTimer0(T_ON[cont]);
  157.             //printf(" servo %d, %ul\n\r",servo,T_ON[cont]);
  158.             servo=pos[1][cont];
  159.             cont++;
  160.  
  161.         }else if(servo==3){
  162.             SERVO3=0;
  163.             WriteTimer0(T_ON[cont]);
  164.             //printf(" servo %d, %ul\n\r",servo,T_ON[cont]);
  165.             servo=pos[1][cont];
  166.             cont++;
  167.         }else if(servo==4){
  168.             SERVO4=0;
  169.             WriteTimer0(T_ON[cont]);
  170.             //printf(" servo %d, %ul\n\r",servo,T_ON[cont]);
  171.             servo=pos[1][cont];
  172.             cont++;
  173.         }else if(servo==5){
  174.             SERVO5=0;
  175.             WriteTimer0(T_ON[cont]);
  176.             //printf(" servo %d, %ul\n\r",servo,T_ON[cont]);
  177.             servo=pos[1][cont];
  178.             cont++;
  179.         }else if(servo==6){
  180.             SERVO0=0;SERVO1=0;SERVO2=0;SERVO3=0;SERVO4=0;SERVO5=0;
  181.             //printf("todos servos a 0 ------------------\n\r");
  182.             WriteTimer0(T_OFF);
  183.             cont=0;
  184.         }
  185.         INTCONbits.TMR0IF=0;
  186.     }
  187. }
  188.  
  189. void print_servos(void){
  190.     // imprimimos las posiciones de los servos, antes de ser ordenados.
  191.     printf("Servo 0: %d grados.\r\n",pos[0][0]);
  192.     printf("Servo 1: %d grados.\r\n",pos[0][1]);
  193.     printf("Servo 2: %d grados.\r\n",pos[0][2]);
  194.     printf("Servo 3: %d grados.\r\n",pos[0][3]);
  195.     printf("Servo 4: %d grados.\r\n",pos[0][4]);
  196.     printf("Servo 5: %d grados.\r\n",pos[0][5]);
  197.     printf("-------------------\r\n");
  198. }
  199. void main(void) {
  200.  
  201.     ADCON1 = 0xFF;      // Deshabilita las entradas analogas.
  202.     TRISA=0b000110000;
  203.     TRISB=0b00000011;
  204.     TRISC = 0b11110011; //Coil in RC2 (PWM) and RC3
  205.  
  206.     // inicializamos la USART
  207.     OpenUSART(USART_TX_INT_OFF &
  208.             USART_RX_INT_ON &       //Activar la interrupcion por la recepcion de dato del buffer de Rx del USART
  209.             USART_ASYNCH_MODE &     //Modo asincrono (fullduplex)
  210.             USART_EIGHT_BIT &       //8 bits de datos
  211.             USART_CONT_RX &         //Recepción continua
  212.             USART_BRGH_HIGH, 129);  //9600 Baudios
  213.             // 12-77,20-129,
  214.  
  215.     // inizializamos el TIMER0;
  216.     OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_2);
  217.     // TiempoTMR0 = (4/Fosc)*(2^bits - ValorTMR0)*Prescaler
  218.     // TiempoTMR0 = (4/20000000)*(2^16 - ValorTMR0)*4
  219.     RCONbits.IPEN = 1;          // Enable interrupt priorities
  220.     INTCONbits.GIE = 1;         // Globally enable interrupts
  221.     INTCONbits.PEIE = 1;
  222.  
  223.     printf("Prueba servos con T0\r\n");
  224.     // inicializamos la variable "pos" con unoas valores aleatorios.
  225.     pos[0][0]=20;pos[0][1]=130;pos[0][2]=5;
  226.     pos[0][3]=100;pos[0][4]=90;pos[0][5]=4;
  227.     // recordad que siempre que modifiqueis las variables de las posiciones,
  228.     // estas siguientes variables se han de inicializar de igual manera.
  229.     pos[1][0]=0;pos[1][1]=1;pos[1][2]=2;
  230.     pos[1][3]=3;pos[1][4]=4;pos[1][5]=5;
  231.  
  232.     // imprimimos los valores iniciales sin ordenar
  233.     print_servos();
  234.  
  235.     // calculamos los tiempos para el "writetimer0"
  236.     calc_tiempos();
  237.  
  238.     // inicializamos "WriteTimer0"
  239.     servo=6;
  240.     cont=0;
  241.     WriteTimer0(T_OFF);
  242.  
  243.     while(1){
  244.         if  (PORTAbits.RA4==0){
  245.             // random para cada uno de los 6 servos,
  246.             pos[0][0]=rand()%180;pos[0][1]=rand()%180;pos[0][2]=rand()%180;
  247.             pos[0][3]=rand()%180;pos[0][4]=rand()%180;pos[0][5]=rand()%180;
  248.             // inicalizamos los índices de los servos.
  249.             pos[1][0]=0;pos[1][1]=1;pos[1][2]=2;
  250.             pos[1][3]=3;pos[1][4]=4;pos[1][5]=5;
  251.  
  252.             // imprimimos los servos
  253.             print_servos();
  254.  
  255.             // calculamos los tiempos.
  256.             calc_tiempos();
  257.            
  258.             while (PORTAbits.RA4==0){
  259.                    Delay1KTCYx(1);
  260.             }
  261.         }
  262.     }
  263. }


los archivos del proyecto y la simulación en proteus lo pueden encontrar en el enlace:
http://www.todopic.com.ar/foros/index.php?topic=43560.0

Desconectado illusionista_86

  • PIC10
  • *
  • Mensajes: 23
Re: Mini curso "Programación en XC8"
« Respuesta #269 en: 12 de Octubre de 2014, 22:48:22 »
un ejemplo del uso de i2c, me parece interesante porque es entro dos pics, en este caso dos 18f2550 y la utilización de enteros.

codigo del maestro:

Código: C
  1. /*
  2.  * File:   prueba_lcd.c
  3.  * Author: Enrique
  4.  *
  5.  * Created on 6 de octubre de 2014, 20:15
  6.  */
  7. #include <p18f2550.h>
  8. #include <delays.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <i2c.h>
  12. #include <usart.h>
  13. #include <stdio.h>
  14. #include <math.h>
  15. #include "i2c_func.h"
  16.  
  17. #pragma config FOSC=XT_XT, FCMEN=OFF,IESO=OFF,CPUDIV=OSC1_PLL2
  18. #pragma config PWRT=ON,BOR=OFF,BORV=0,WDT=OFF,WDTPS=32768
  19. #pragma config MCLRE=ON,LPT1OSC=OFF,PBADEN=OFF,CCP2MX=OFF
  20. #pragma config STVREN=OFF,LVP=OFF,XINST=OFF,DEBUG=OFF
  21. #pragma config CP0=OFF,CP1=OFF,CP2=OFF,CPB=OFF,CPD=OFF
  22. #pragma config WRT0=OFF,WRT1=OFF,WRT2=OFF
  23. #pragma config WRTB=OFF,WRTC=OFF,WRTD=OFF
  24. #pragma config EBTR0=OFF,EBTR1=OFF,EBTR2=OFF,EBTRB=OFF
  25.  
  26. #define _RAND_MAX 10;
  27.  
  28. unsigned char ebuffer[30];
  29. unsigned char ebuffer2[2];
  30. unsigned long long value[10];
  31. char MensajeTx[] = "Pruba Comunicacion I2C maestro: \n\r";
  32. int cont;
  33.  
  34. void putch(unsigned char byte)
  35. {
  36.             TXSTA=0x26;
  37.             SPEN=1;
  38.             TXREG=byte;            /* transmit a character to Serial IO */
  39.             while(!TXIF)continue;
  40.             TXIF=0;
  41. }
  42.  
  43. void main(void){
  44.  
  45.     ADCON1 = 0xFF;      // Deshabilita las entradas analogas.
  46.     TRISA=0b00010000;
  47.     TRISB=0b00000011;
  48.     TRISCbits.TRISC6=0; TRISCbits.TRISC7=1;
  49.     OpenUSART(USART_TX_INT_OFF &
  50.             USART_RX_INT_ON &       //Activar la interrupcion por la recepcion de dato del buffer de Rx del USART
  51.             USART_ASYNCH_MODE &     //Modo asincrono (fullduplex)
  52.             USART_EIGHT_BIT &       //8 bits de datos
  53.             USART_CONT_RX &         //Recepción continua
  54.             USART_BRGH_HIGH, 51);  //9600 Baudios
  55.     OpenI2C( MASTER, SLEW_OFF);
  56.     // Clock = FOSC/(4 * (SSPADD + 1)) // 100 KHz = 8E6/4*20 = 100 KHz.
  57.     // SSPADD=(FOSC/(Clock*4))-1; Para Clock=50Khz. -> SSPADD=(8000000/(4*100000))-1=19
  58.     SSPADD = 19;
  59.     PORTAbits.RA3=0;
  60.  
  61.     putsUSART(MensajeTx);
  62.     cont=1;
  63.     value[0]=9;
  64.     value[1]=25;
  65.     value[2]=480;
  66.     value[3]=3124;
  67.     value[4]=48215;
  68.     value[5]=147348;
  69.     value[6]=3648975;
  70.     value[7]=12473587;
  71.     value[8]=318974698;
  72.     value[9]=1475286934;
  73.  
  74.     while(1){
  75.  
  76.         Delay1KTCYx(2);
  77.         PORTAbits.RA3=~PORTAbits.RA3;
  78.         if  (PORTAbits.RA4==0){
  79. //            value=rand();
  80.             for (int i=0;i<10;i++){
  81.                 printf("Dato %d enviado: %llu\n\r",cont,value[i]);
  82.                 Empezar_i2c(0x0A);
  83.                 Escribir_int_i2c(value[i]);
  84.                 Cerrar_i2c();
  85.                 cont++;
  86.                 Delay1KTCYx(20);
  87.                 while (PORTAbits.RA4==0){
  88.                     Delay1KTCYx(1);
  89.                 }
  90.             }
  91.         }
  92.     }
  93. }

codigo del esclavo:

Código: C
  1. /*
  2.  * File:   prueba_lcd.c
  3.  * Author: Enrique
  4.  *
  5.  * Created on 6 de octubre de 2014, 20:15
  6.  */
  7. #include <p18f2550.h>
  8. #include <delays.h>
  9. #include <string.h>
  10. #include <i2c.h>
  11. #include <usart.h>
  12. #include <stdio.h>
  13. #include <math.h>
  14. #include <stdarg.h>
  15. #include "i2c_func.h"
  16. #include <stdlib.h>
  17.  
  18. #pragma config FOSC=XT_XT, FCMEN=OFF,IESO=OFF,CPUDIV=OSC1_PLL2
  19. #pragma config PWRT=ON,BOR=OFF,BORV=0,WDT=OFF,WDTPS=32768
  20. #pragma config MCLRE=ON,LPT1OSC=OFF,PBADEN=OFF,CCP2MX=OFF
  21. #pragma config STVREN=OFF,LVP=OFF,XINST=OFF,DEBUG=OFF
  22. #pragma config CP0=OFF,CP1=OFF,CP2=OFF,CPB=OFF,CPD=OFF
  23. #pragma config WRT0=OFF,WRT1=OFF,WRT2=OFF
  24. #pragma config WRTB=OFF,WRTC=OFF,WRTD=OFF
  25. #pragma config EBTR0=OFF,EBTR1=OFF,EBTR2=OFF,EBTRB=OFF
  26.  
  27. unsigned char ebuffer[15];
  28. unsigned char ebuffer2[5];
  29. int kbit,cont;
  30. char adress;
  31. unsigned long long reciv;
  32.  
  33. char MensajeTx[] = "Pruba Comunicacion I2C esclavo: \n\r";
  34.  
  35. // para que funcione "printf" en la USART
  36. //void putch(char data) {
  37. //while( ! TXIF)
  38. //continue;
  39. //TXREG = data;
  40. //}
  41. void putch(unsigned char byte)
  42. {
  43.             TXSTA=0x26;
  44.             SPEN=1;
  45.             TXREG=byte;            /* transmit a character to Serial IO */
  46.             while(!TXIF)continue;
  47.             TXIF=0;
  48. }
  49.  
  50. void interrupt isr(void)
  51. {
  52.  
  53.     if (PIR1bits.SSPIF) {        // Check for SSP interrupt
  54.         kbit=1;
  55.         adress = ReadI2C();
  56.         IdleI2C();
  57.  
  58.         reciv=Recibir_int_i2c();
  59.         IdleI2C();
  60.  
  61.         PIR1bits.SSPIF = 0;  // Clear the interrupt flag
  62.  
  63.        
  64.     }
  65.     return;
  66. }
  67.  
  68.  
  69. void main(void){
  70.  
  71.    
  72.     ADCON1 = 0xFF;      // Deshabilita las entradas analogas.
  73.     TRISA=0;
  74.     TRISB=0b00000011;
  75.     TRISCbits.TRISC6=0; TRISCbits.TRISC7=1;  
  76.     OpenUSART(USART_TX_INT_OFF &
  77.             USART_RX_INT_ON &       //Activar la interrupcion por la recepcion de dato del buffer de Rx del USART
  78.             USART_ASYNCH_MODE &     //Modo asincrono (fullduplex)
  79.             USART_EIGHT_BIT &       //8 bits de datos
  80.             USART_CONT_RX &         //Recepción continua
  81.             USART_BRGH_HIGH, 51);  //9600 Baudios
  82.     OpenI2C( SLAVE_7, SLEW_OFF);
  83.     // Clock = FOSC/(4 * (SSPADD + 1)) // 100 KHz = 8E6/4*20 = 100 KHz.
  84.     // SSPADD=(FOSC/(Clock*4))-1; Para Clock=50Khz. -> SSPADD=(4000000/(4*100000))-1=19
  85.     SSPADD = 0x0A;
  86.     RCONbits.IPEN = 1;          // Enable interrupt priorities
  87.     INTCONbits.GIE = 1;             // Globally enable interrupts
  88.     PIE1bits.SSPIE = 1;         // Enable SSP interrupt
  89.     IPR1bits.SSPIP = 1;         // Set SSP interrupt priority to high
  90.     INTCONbits.PEIE = 1;
  91.  
  92.     PORTAbits.RA2=0;
  93.     PORTAbits.RA3=0;
  94.     putsUSART(MensajeTx);
  95.     cont=1;
  96.     while(1){
  97.         PORTAbits.RA3=~PORTAbits.RA3;
  98.         Delay1KTCYx(5);
  99.         if (kbit==1){
  100.             printf("Dato %d recivido: %llu\n\r",cont,reciv);
  101.             cont++;
  102.             kbit=0;
  103.         }
  104.     }
  105.  
  106.  
  107.  
  108.  
  109. }


libreria utilizada para enviar los datos:

Código: C
  1. /*
  2.  * File:   i2c_func.h
  3.  * Author: Enrique
  4.  *
  5.  * Created on 10 de octubre de 2014, 15:27
  6.  */
  7.  
  8. #ifndef I2C_FUNC_H
  9. #define I2C_FUNC_H
  10.  
  11. #include <i2c.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15.  
  16. int Escribir_dato_i2c(char Address, char Data) // Escribe un byte a un esclavo en I2C
  17.  {
  18.     IdleI2C();                          // ensure module is idle
  19.     StartI2C();                         // initiate START condition
  20.     while ( SSPCON2bits.SEN );          // wait until start condition is over
  21.     WriteI2C( Address );                        // Selecciona el dispositivo esclavo
  22.     IdleI2C();                          // Asegura que el modulo este desocupado
  23.     if ( SSPCON2bits.ACKSTAT )          // Prueba por la condicion de ACK, si es recibida
  24.     {
  25.             StopI2C();                  // send STOP condition
  26.             while ( SSPCON2bits.PEN );  // wait until stop condition is over
  27.             return 1;
  28.     }
  29.     WriteI2C( Data );
  30.     IdleI2C();
  31.     AckI2C();
  32.     StopI2C();                  // send STOP condition
  33.     while ( SSPCON2bits.PEN );  // wait until stop condition is over
  34.     return 0;
  35.  }
  36.  
  37. void Escribir_int_i2c(unsigned long long value) // Escribe un byte a un esclavo en I2C
  38.  {
  39.     unsigned char buff_leng[2];
  40.     unsigned char buff_value[10];
  41.     int leng;
  42.  
  43.     ltoa(buff_value,value,10);
  44.     leng=strlen(buff_value);
  45.     leng=leng-1;
  46.     itoa(buff_leng,leng,10);
  47.  
  48.     IdleI2C();
  49.     putsI2C(buff_leng);
  50.     IdleI2C();
  51.     putsI2C(buff_value);
  52.     IdleI2C();    
  53.  }
  54.  
  55. unsigned long long int Recibir_int_i2c(void) // Escribe un byte a un esclavo en I2C
  56. {
  57.     unsigned char buff_leng[2];
  58.     unsigned char buff_value[15];
  59.     int leng;
  60.     unsigned long long reciv;
  61.  
  62.     getsI2C(buff_leng,1);
  63.     IdleI2C();
  64.     leng=(atoi(buff_leng)+1);
  65.     getsI2C(buff_value,leng);
  66.     IdleI2C();
  67.     reciv=atol(buff_value);
  68.  
  69.     return reciv;
  70.  }
  71.  
  72. void Empezar_i2c(char Address) // Escribe un byte a un esclavo en I2C
  73.  {
  74.     IdleI2C();                          // ensure module is idle
  75.     StartI2C();                         // initiate START condition
  76.     while ( SSPCON2bits.SEN );          // wait until start condition is over
  77.     WriteI2C( Address );                        // Selecciona el dispositivo esclavo
  78.     IdleI2C();                          // Asegura que el modulo este desocupado
  79.     if ( SSPCON2bits.ACKSTAT )          // Prueba por la condicion de ACK, si es recibida
  80.     {
  81.             StopI2C();                  // send STOP condition
  82.             while ( SSPCON2bits.PEN );  // wait until stop condition is over
  83.     }
  84. }
  85.  
  86. void Cerrar_i2c(void) // Escribe un byte a un esclavo en I2C
  87. {
  88.     IdleI2C();
  89.     AckI2C();
  90.     StopI2C();                  // send STOP condition
  91.     while ( SSPCON2bits.PEN );  // wait until stop condition is over
  92. }
  93. #endif  /* I2C_FUNC_H */


los archivos del proyecto en mplabX y proteus en el enlace:
http://www.todopic.com.ar/foros/index.php?topic=43560.0


 

anything