Autor Tema: Generando un pulso. 2ª Parte. Onda Simétrica Mediante INTCCP en modo Compare  (Leído 3551 veces)

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

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5388
    • Picmania by Redraven
Generando un pulso. 2ª Parte. Onda simétrica con INTCCP en modo Compare

A.- Conceptos involucrados:

Seguimos dándole vueltas al mismo concepto que en todas las Técnicas en C anteriores. Si lo deseáis podéis repasar esto mismo en cualquiera de ellas.



Volvemos a generar un pulso de Periodo T con dos semiperiodos iguales, simétrico, y de unos 2 Khz de frecuencia: unos 0.25 ms en alto y otros 0.25 ms en bajo, total 0.5 ms de periodo.

B.- Técnica a Aplicar:

Para generar el periodo T de nuestro pulso vamos a utilizar de nuevo el módulo CCP del que disponen la gran mayoria de los PIC's, tanto los de la serie 18F como los 16F.

Recordemos: En la Técnica Midiendo un pulso. 2ª Parte. Tiempo en Alto con INTCCP hacíamos uso de este mismo módulo utilizando su modo Capture en el que cuando detectábamos un flanco externo se nos capturaba el valor en ese momento del TMR1. Jugando con los sucesivos valores obteníamos la duración del pulso.

En ésta técnica que ahora describimos vamos a hacer lo diametralmente opuesto: Vamos a utilizar el CCP en modo Compare para que el CCP vaya comparando automáticamente el valor de TMR1 con un valor de referencia que le damos, CCP_x, y en cuanto lo alcance se realice la conmutación del Pin asociado a él y nos dispare la Petición de Servicio de Interrupción (ISR) INT_CCPx correspondiente.

En el código de esta interrupción volvemos a hacer lo mismo pero configurando el Compare para que cuando TMR1 alcance el valor de referencia conmute nuestro Pin CCP al estado contrario.

Si ambos valores de TMR1 de referencia, para el Compare a Alto y el Compare a bajo, son iguales tendremos un tren de pulsos simétricos, están el mismo tiempo en alto que en bajo, o sea que tienen un Duty Cycle del 50%. En caso contrario estarán mas tiempo en un estado que en otro y será una onda asimétrica, o sea que tendrá un Duty Cicle distinto del 50%.

El periodo será la suma de ambos tiempos, el que permanece en estado alto mas el que está en estado bajo.

Calculando cuidadosamente dichos tiempos podremos generar una onda del periodo que deseamos. Pondremos a 0  siempre TRM1 y cargaremos CCP_x con el número de Ticks de TMR1 en que deseamos que se dispare nuestra conmutación/interrupción.

C.- Implementación en C:

Para implementar nuestro Código en C vamos a centrarnos en los puntos que hemos descrito en la sección anterior.

Para configurar la interrpción CCP utilizaremos lo siguiente:

Código: C
  1.    setup_ccp2(CCP_COMPARE_SET_ON_MATCH);    // Configuro CCP2 en modo COMPARE cambiando a Alto
  2.    enable_interrupts(int_ccp2);             // Habilito la interrpción INT_CCP2
  3.    enable_interrupts(global);               // Habilito las interrupciones necesarias
  4.  

Con esta configuración inicial podemos ya escribir nuestra rutina ISR que es muy simple ya que únicamente selecciona mediante un flag si debe el siguiente cambio es a Alto o a Bajo y colocar el tiempo en que deseamos en que esto se produzca:

Código: C
  1. #int_ccp2
  2. void handle_ccp2_int(){
  3.  
  4.    if(++flagConmuta==1){
  5.      setup_ccp2(CCP_COMPARE_CLR_ON_MATCH);  // Configura CCP2 en modo COMPARE cambiando a Bajo
  6.     } else{
  7.      setup_ccp2(CCP_COMPARE_SET_ON_MATCH);  // Configura CCP2 en modo COMPARE cambiando a Alto
  8.    }
  9.    CCP_2=0;                                 // Pongo a cero el valor a comparar ...
  10.    set_timer1(0);                           // y el TMR1.
  11.    CCP_2 = 1250;                            // Quiero que se dispare cada 0.25 ms ...
  12.                                             // luego pongo los Ticks de TMR1 para ese tiempo.
  13. }
  14.  

Notad que estoy trabajando con una configuración particular a la que me sujeta el Hardware específico del que dispongo: El módulo CCP2 y un cuarzo de 20 Mhz.

Con un Cristal de 20 Mhz los cálculos me indican que el número de Ticks de TMR1 necesarios para realizar una conmutación cada 0.25 ms es de 1250 (0.00025 / (1/ FOSC)*4)

Con todo esto el programa completo para nuestro Generar una Onda Cuadrada Simétrica de 2 Khz de Frecuencia queda así:

Código: C
  1. ////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Generando_un_pulso_6_INTCCP.c
  4. //
  5. // SERIE: "Técnicas en C" para el Foro TODOPIC
  6. //
  7. // (c) 11.2006 by RedPic
  8. //
  9. // Propósito: Generar un pulso de 2 Khz (0.5 ms de periodo)
  10. //
  11. // Técnica Empleada: Habilitar INTCCP para conmutar el PIN CCP2 cada semiperiodo
  12. //                   utilizando el recurso CCP en modo compare.
  13. //
  14. ////////////////////////////////////////////////////////////////////////////////////
  15.  
  16. #include <18f4550.h>
  17. #fuses HS,MCLR,CCP2B3,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOPBADEN,NOLVP,NOCPD,NODEBUG,NOWRT,NOVREGEN
  18. #use delay(clock=20000000)
  19.  
  20. #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
  21.  
  22. ////////////////////////////////////////////////////////////////////////////////////
  23. //
  24. // Defines y Constantes
  25. //
  26. ////////////////////////////////////////////////////////////////////////////////////
  27.  
  28. #define LED PIN_E0                          // Defino el Pin del Led
  29. #define OUT PIN_B3
  30.  
  31. ////////////////////////////////////////////////////////////////////////////////////
  32. //
  33. // Variables en RAM
  34. //
  35. ////////////////////////////////////////////////////////////////////////////////////
  36.  
  37. int1 flagConmuta=0;
  38.  
  39. ////////////////////////////////////////////////////////////////////////////////////
  40. //
  41. // Interrupción CCP por Compare TMR1
  42. //
  43. ////////////////////////////////////////////////////////////////////////////////////
  44.  
  45. #int_ccp2
  46. void handle_ccp2_int(){
  47.  
  48.    if(++flagConmuta==1){
  49.      setup_ccp2(CCP_COMPARE_CLR_ON_MATCH);  // Configura CCP2 en modo COMPARE cambiando a Bajo
  50.     } else{
  51.      setup_ccp2(CCP_COMPARE_SET_ON_MATCH);  // Configura CCP2 en modo COMPARE cambiando a Alto
  52.    }
  53.    CCP_2=0;                                 // Pongo a cero el valor a comparar ...
  54.    set_timer1(0);                           // y el TMR1.
  55.    CCP_2 = 1250;                            // Quiero que se dispare cada 0.25 ms ...
  56.                                             // luego pongo los Ticks de TMR1 para ese tiempo.
  57.                                            
  58.    Output_Toggle(LED);                      // Monitorizo visualmente con el PIN de Led;
  59. }
  60.  
  61. ////////////////////////////////////////////////////////////////////////////////////
  62. //
  63. // Main
  64. //
  65. ////////////////////////////////////////////////////////////////////////////////////
  66.  
  67. void main() {
  68.  
  69.     ////////////////////////////////////////// INICIALIZACIONES GENERALES
  70.  
  71.    delay_ms(333);                           // Espero a que todo se estabilice e ...
  72.    disable_interrupts(global);              // Inicializo el Micro y ...
  73.    disable_interrupts(int_timer1);          // deshabilitando todo lo no necesario ...
  74.    disable_interrupts(int_rda);
  75.    disable_interrupts(int_ext);
  76.    disable_interrupts(int_ext1);
  77.    disable_interrupts(int_ext2);
  78.    setup_adc_ports(NO_ANALOGS);
  79.    setup_adc(ADC_OFF);
  80.    setup_spi(FALSE);
  81.    setup_psp(PSP_DISABLED);
  82.    setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
  83.    setup_timer_0(RTCC_OFF);
  84.    setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
  85.    setup_timer_2(T2_DISABLED,0,1);
  86.    setup_timer_3(T3_DISABLED);
  87.    setup_comparator(NC_NC_NC_NC);
  88.    setup_vref(FALSE);
  89.    port_b_pullups(FALSE);
  90.    delay_ms(333);
  91.  
  92.    /////////////////////////////////////////// INICIALIZACIONES PERTINENTES A LA APLICACION
  93.  
  94.    setup_ccp2(CCP_COMPARE_SET_ON_MATCH);    // Configura CCP2 en modo COMPARE cambiando a Alto
  95.    enable_interrupts(int_ccp2);             // Habilito la interrpción INT_CCP2
  96.    enable_interrupts(global);               // Habilito las interrupciones necesarias
  97.  
  98.    printf("\r\nGenerando un pulso : INTCCP Compare\r\n");
  99.    printf("By Redpic para Foro TODOPIC\r\n\n");
  100.  
  101.    do {
  102.    } while (TRUE);
  103. }
  104.  

D.- Ejemplo funcionando:


Je, je, je La foto es la misma que en Generando un pulso. 1ª Parte. Onda simétrica con INTRTCC ya que la única diferencia está en el Firmware del PIC: el resto visualmente y desde fuera es absolutamente igual.  :mrgreen:

Y esto es todo por hoy, amigos.  :mrgreen:
Mañana, más.

« Última modificación: 24 de Octubre de 2014, 10:01:14 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania