Autor Tema: Receptor DMX (DMX512)  (Leído 162731 veces)

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

Desconectado mrlicho

  • PIC10
  • *
  • Mensajes: 5
Re: Receptor DMX (DMX512)
« Respuesta #75 en: 15 de Junio de 2010, 11:37:25 »
Bueno, no quiero molestar tanto, pero la verdad me está ganando de lo lindo esto... a ver si alguien ve dónde le estoy errando:

Aclaro que el WatchDog está habilitado porque así estaba en el programa de Nocturno, pero no entiendo qué función está cumpliendo aquí...

Donde tengo una duda también es en la definición de la constante TotalCanales, que lo cambié de 512 a 3, sigo el código pero no estoy seguro de que al recibir el tercer canal luego se quede esperando a que reciba los 509 canales restantes sin almacenarlos, y luego esperando por el break, o si directamente espera por el Break. Tengo la duda de que no se desincronice en este punto. Por otro lado, el compañero Tinho lo ha implementado para 12 canales en un 16F876 y realizó la misma modificación en esa constante, y no vi que Nocturno lo corrigiera... Bueno, esa es la duda principal.

Aclaro lo que hace el pic cuando testeo el circuito:

Pasado el segundo de delay que tiene el programa, se enciende el led indicador que está conectado al pin B7 y se encienden también los leds conectados en los pines B4 y B5, correspondientes a los canales DMX 1 y 2, pero independientemente del valor que entrega la consola, pues muevo los 3 potenciometros desde 0 a 255 y no pasa naaadaaa.

Bueno, disculpen lo largo del mensaje, pero así se entiende mejor tal vez. Desde ya: GRACIAS! :)

Código: [Seleccionar]

#include <16F628A.h>

#FUSES WDT                      //Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES PUT                      //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,RESTART_WDT)             // Utilizo clock de 20MHz porque me facilita la elección exacta del baudrate a 250k y tenia el cristal


/************************************************************************
*                    Registros USART                                    *
************************************************************************/

#byte SPBRG=              0x99         // Registros para el pic 16F628
#byte RCSTA=              0x18         // Aqui se han modificado las direcciones correspondientes para el 628
#byte TXSTA=              0x98     
#byte RCREG=              0x1A     
#byte PIR1=               0x0C     
#byte PIE1=               0x8C     


#bit SPEN=                RCSTA.7     
#bit RX9=                 RCSTA.6   
#bit SREN=                RCSTA.5     
#bit CREN=                RCSTA.4   
#bit ADDEN=               RCSTA.3     
#bit FERR=                RCSTA.2   
#bit OERR=                RCSTA.1     
#bit RX9D=                RCSTA.0     
#bit BRGH=                TXSTA.2   
#bit SYNC=                TXSTA.4       
#bit RCIF=                PIR1.5       
#bit RCIE=                PIE1.5       


/************************************************************************
*                    Estados protocolo DMX                              *
************************************************************************/

#define       DMX_ESPERA_BYTE              0
#define       DMX_ESPERA_BREAK            1
#define       DMX_ESPERA_START            2
#define       DMX_ESPERA_DATO             3
#define       DMX_RECEPCION_DATOS     4


/************************************************************************
*                    Variables globales y constantes                    *
************************************************************************/

//--------------------Se han quitado las variables que no utilizo--------------------------------------

int8 DMX_Estado = DMX_ESPERA_BREAK;                        // Estado de la máquina de estados
int8 DatoRX;                                                                  // Dato genérico recibido en USART
int8 DMX_Indice = 0;                                                      // Apuntador a una posición de la trama DMX

#define TotalCanales          3            // Total canales a almacenar en este caso solo interesan los 3 primeros
int8 TramaDMX[TotalCanales];          // Trama completa de valores DMX

union                                               // Estructura para hacer una copia del registro RCSTA
  {
    unsigned char registro;
    struct {
        unsigned char RX9D:1;
        unsigned char OERR:1;
        unsigned char FERR:1;
        unsigned char ADDEN:1;
        unsigned char CREN:1;
        unsigned char SREN:1;
        unsigned char RX9:1;
        unsigned char SPEN:1;
    } bits ;
  }Copia_RCSTA;


/************************************************************************
*          Interrupción Timer 0:                                        *
************************************************************************/
#int_Timer0
TIMER0_isr()
{
}
/************************************************************************
*  Interrupción RDA: dato recibido por la USART                         *
*  Esta interrupción se activa cada vez que se recibe un dato en la     *
*  USART. Mediante el control de una máquina de estados se determina    *
*  la validez y el significado del dato recibido, y se obra en          *
*  consecuencia.                                                        *
************************************************************************/

//--------La interrupción de la USART no se ha modificado, esta tal cual el receptor de Nocturno----------------
//--------solo cambia el hecho de que TotalCanales vale 3 en lugar de 512----------------------------------------

#int_rda
void Dato_Recibido_USART(void)
{
   while (RCIF) // ejecutamos mientras haya un dato pendiente de procesar
   {
    // Hacemos una copia del registro RCSTA porque sus bits cambian de valor
    // al leer RCREG y modificar CREN
    Copia_RCSTA.registro = RCSTA;

    // En RCREG está el dato que acaba de recibir la USART
    DatoRX = RCREG;

    // Si se reciben más de 3 bytes sin haberlos procesado, se produce un error
    // de Overrun. En este caso, se borra el error reiniciando CREN y dejamos
    // la interrupción preparada para procesar la siguiente trama DMX
    if (Copia_RCSTA.bits.OERR)
    {
      CREN=0;
      CREN=1;
      DMX_Estado = DMX_ESPERA_BYTE;
      return;
    }

    // Máquina de estados
    switch (DMX_Estado)
    {
      case DMX_ESPERA_BYTE:   // si estamos en este estado y hay error FRAME
      // es que nos ha pillado en medio de un Byte. Hay que seguir esperando
      // hasta que desaparezca el error.
        if (!Copia_RCSTA.bits.FERR)
              // Ha llegado un byte. Ahora esperaremos la señal Break
          DMX_Estado = DMX_ESPERA_BREAK;
        break;


      case DMX_ESPERA_BREAK:   // estamos esperando la señal Break
        // Esta señal se identifica porque aparece el error de Frame
        if (Copia_RCSTA.bits.FERR)
          // Tras recibir el error de Break, hay que esperar un byte de valor 0
          if (!DatoRX)
            DMX_Estado = DMX_ESPERA_START;
        break;
      case DMX_ESPERA_START: // ya hemos recibido el Break y ahora hay que
          // esperar un Byte con valor 0, que será la señal de Start
        // Mientras tanto, si recibimos un error de Frame, hay que volver a
        // empezar para recibir la señal de comienzo de trama.
        if (Copia_RCSTA.bits.FERR)
            DMX_Estado = DMX_ESPERA_BYTE;
        else {
          if (!DatoRX)
          {
            // Llegados a este punto, ya hemos recibido el Byte Start=0
            // y comenzamos la trama de valores DMX.
            DMX_Indice = 0;
            DMX_Estado = DMX_RECEPCION_DATOS;
          } else
            // Si el dato recibido no es 0, volvemos a empezar
            DMX_Estado = DMX_ESPERA_BREAK;
        }
        break;
      case DMX_RECEPCION_DATOS:
        // En este estado estamos recibiendo la trama de datos DMX
        // Si se detecta un error de Frame es que ha habido un error y estamos
        // al principio
        if (Copia_RCSTA.bits.FERR)
          if (!DatoRX)
            DMX_Estado = DMX_ESPERA_START;
          else
            DMX_Estado = DMX_ESPERA_BYTE;
        else
        {
          // Almacenamos el dato recibido en nuestro array
          TramaDMX[DMX_Indice++] = DatoRX;

          // Si ha llegado al final de la capacidad, cambiamos al estado de espera
          // de nueva trama
          if (DMX_Indice >= TotalCanales)
            DMX_Estado = DMX_ESPERA_BREAK;
        }
        break;
   }
}
return;
}

void main()
{
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_wdt(WDT_18MS);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(False);
   
   // Activamos las interrupciones de recepción de la USART y del Timer0

   enable_interrupts(INT_RDA);     
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);

   // Configuración de la USART
   
SPBRG=4;          // A 20Mhz el baudrate es 250.000, sale de la tabla de la hoja de datos del 16F628
BRGH=1;           // Seleccionamos high speed
SYNC=0;           // Transmisión asíncrona
SPEN=1;           // Activamos la USART
RX9=1;            // 9 bit para la recepcion
SREN=0;           // Desactiva recepción de un byte
CREN=1;           // Recepción activada
ADDEN=0;          // Desactivada la autodetección de dirección
FERR=0;           // No hay error de frame con 1 se activa
OERR=0;           // No hay error de overrun con 1 se activa


//-----------------------------------------------------------


   delay_ms(1000);            // delay de 1 seg y enciendo un led en el pin B7 para saber que por lo menos está corriendo el programa
   output_high(pin_B7);
   
   while(1) {

           if (TramaDMX[0]>128)output_high(pin_B4);                 // La idea es hacer PWM pero primero quiero recibir la señal DMX exitosamente
                   else output_low(pin_B4);                                    // por eso primero trabajo ON-OFF a la mitad del potenciómetro
           if (TramaDMX[1]>128)output_high(pin_B5);                 
                   else output_low(pin_B5);                                    // Los valores de TramaDMX 0, 1 y 2 deberian corresponderse con los canales 1, 2 y 3
           if (TramaDMX[2]>128)output_high(pin_B6);
                   else output_low(pin_B6);
           
            delay_ms(25);                 // pequeña espera y refresco del Watchdog automático
             }
}

Desconectado mrlicho

  • PIC10
  • *
  • Mensajes: 5
Re: Receptor DMX (DMX512)
« Respuesta #76 en: 24 de Junio de 2010, 19:20:35 »
Bueno, finalmente logré hacer funcionar el programa! Mil gracias por el ejemplo Nocturno, la verdad ha sido de una gran utilidad. Paso a comentar que el problema se debía a mi compilador, el código estaba perfecto, reinstalé una versión anterior del ccs y anduvo perfectamente. Recién he recibido la trama DMX, pero aún tengo que terminar el programa para que funcione con pwm, dimmer y flash. Cuando esté terminado lo posteo por si a alguien le sirve.

Saludos!

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: Receptor DMX (DMX512)
« Respuesta #77 en: 24 de Junio de 2010, 19:23:30 »
Perfecto, me alegro mucho. Espero verlo publicado, sí.

Desconectado sistemas

  • PIC10
  • *
  • Mensajes: 3
Re: Receptor DMX (DMX512)
« Respuesta #78 en: 31 de Agosto de 2010, 18:27:45 »
hola manolo

Exelente trabajo pero he tenido problemas con el registo en MicroPIC me preguntaba si no puedes poner otro link para el codigo fuente y el esquematico. o bie me lo puedadas enviar a key_word@hotmail.com
se te agradece de antemano por semejante aportacion
saludos



Gracias por vuestras palabras. (Akenafab, esas pilas son las que venden en la cadena de supermercados Mercadona, seguro que muchos de mis compatriotas las conocen. Jesús, el conector no lo venden en Mercadona :D)

Ya he subido el código fuente y el esquemático, que podéis descargar aquí: Descargas de ReceptorDMX



Del código fuente pegaré aquí sólo la rutina de atención a la interrupción de la USART, que es donde está el meollo de la cuestión. El programa completo está disponible para descargar en el link que puse antes. El código está comentado, así que me ahorro explicarlo.

Si necesitáis algo más, no tenéis más que decirlo.

Código: C
  1. /************************************************************************
  2. *  Interrupción RDA: dato recibido por la USART                         *
  3. *  Esta interrupción se activa cada vez que se recibe un dato en la     *
  4. *  USART. Mediante el control de una máquina de estados se determina    *
  5. *  la validez y el significado del dato recibido, y se obra en          *
  6. *  consecuencia.                                                        *
  7. ************************************************************************/
  8.  
  9. #int_rda
  10. void Dato_Recibido_USART(void)
  11. {
  12.         while (RCIF) // ejecutamos mientras haya un dato pendiente de procesar
  13.         {
  14.          // Hacemos una copia del registro RCSTA porque sus bits cambian de valor
  15.          // al leer RCREG y modificar CREN
  16.          Copia_RCSTA.registro = RCSTA;
  17.  
  18.          // En RCREG está el dato que acaba de recibir la USART
  19.          DatoRX = RCREG;
  20.  
  21.          // Si se reciben más de 3 bytes sin haberlos procesado, se produce un error
  22.          // de Overrun. En este caso, se borra el error reiniciando CREN y dejamos
  23.          // la interrupción preparada para procesar la siguiente trama DMX
  24.          if (Copia_RCSTA.bits.OERR)
  25.          {
  26.            CREN=0;
  27.            CREN=1;
  28.            DMX_Estado = DMX_ESPERA_BYTE;
  29.            return;
  30.          }
  31.  
  32.          // Máquina de estados
  33.          switch (DMX_Estado)
  34.          {
  35.            case DMX_ESPERA_BYTE:        // si estamos en este estado y hay error FRAME
  36.                 // es que nos ha pillado en medio de un Byte. Hay que seguir esperando
  37.                 // hasta que desaparezca el error.
  38.              if (!Copia_RCSTA.bits.FERR)
  39.                                 // Ha llegado un byte. Ahora esperaremos la señal Break
  40.                DMX_Estado = DMX_ESPERA_BREAK;
  41.              break;
  42.  
  43.  
  44.            case DMX_ESPERA_BREAK:       // estamos esperando la señal Break
  45.              // Esta señal se identifica porque aparece el error de Frame
  46.              if (Copia_RCSTA.bits.FERR)
  47.                // Tras recibir el error de Break, hay que esperar un byte de valor 0
  48.                if (!DatoRX)
  49.                  DMX_Estado = DMX_ESPERA_START;
  50.              break;
  51.            case DMX_ESPERA_START: // ya hemos recibido el Break y ahora hay que
  52.                  // esperar un Byte con valor 0, que será la señal de Start
  53.              // Mientras tanto, si recibimos un error de Frame, hay que volver a
  54.              // empezar para recibir la señal de comienzo de trama.
  55.              if (Copia_RCSTA.bits.FERR)
  56.                  DMX_Estado = DMX_ESPERA_BYTE;
  57.              else {
  58.                if (!DatoRX)
  59.                {
  60.                  // Llegados a este punto, ya hemos recibido el Byte Start=0
  61.                  // y comenzamos la trama de valores DMX.
  62.                  DMX_Indice = 0;
  63.                  DMX_Estado = DMX_RECEPCION_DATOS;
  64.                } else
  65.             // Si el dato recibido no es 0, volvemos a empezar
  66.                  DMX_Estado = DMX_ESPERA_BREAK;
  67.              }
  68.              break;
  69.            case DMX_RECEPCION_DATOS:
  70.              // En este estado estamos recibiendo la trama de datos DMX
  71.         // Si se detecta un error de Frame es que ha habido un error y estamos
  72.         // al principio
  73.              if (Copia_RCSTA.bits.FERR)
  74.                if (!DatoRX)
  75.                  DMX_Estado = DMX_ESPERA_START;
  76.                else
  77.                  DMX_Estado = DMX_ESPERA_BYTE;
  78.              else
  79.              {
  80.                // Almacenamos el dato recibido en nuestro array
  81.                TramaDMX[DMX_Indice++] = DatoRX;
  82.  
  83.                // Si ha llegado al final de la capacidad, cambiamos al estado de espera
  84.           // de nueva trama
  85.                if (DMX_Indice >= TotalCanales)
  86.                  DMX_Estado = DMX_ESPERA_BREAK;
  87.              }
  88.              break;
  89.    }
  90. }
  91. return;
  92. }

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: Receptor DMX (DMX512)
« Respuesta #79 en: 01 de Septiembre de 2010, 01:58:11 »
Ya estás registrado en MicroPIC. Mira tu correo.

Desconectado PACMER

  • PIC10
  • *
  • Mensajes: 18
Receptor DMX (DMX512)
« Respuesta #80 en: 25 de Octubre de 2010, 03:46:54 »
MrLicho si te funciono con el 16F628, es decir ya lo probaste con un controlador DMX, cambia el valor en los displays

Saludos a Todos

Desconectado lagruya

  • PIC16
  • ***
  • Mensajes: 204
Re: Receptor DMX (DMX512)
« Respuesta #81 en: 16 de Abril de 2011, 13:41:19 »
hola nocturno, hace un tiempo que vengo dandole vueltas al dmx y tu receptor ha sido el detonante  :5] para que me decida, ademas me viene barbaro para familiarizarme con el tema de la transmision serie por pic.

voy al grano, estoy tratando de comprender al detalle el codigo del receptor y se me plantean las siguientes dudas:

1- Estado DMX_ESPERA_BYTE, no comprendo su funcion. ¿Esta relacionado con la situacion del error de overrun? ¿si ocurrio un error de overrun se deja pasar una trama completa de los 512 canales para esperar una señal de  Break? ¿por que no arrancar con el estado DMX_ESPERA_BRAKE?

2- La señal de BREAK no se envia en el formato de USART, por eso se detecta con el error de frame (salta porque el bit stop no esta a "1") mas la confirmacion de que RCREG = 00000000

3- No se espera la señal AFTER BREAK? luego del estado DMX_ESPERA_BRAKE (la de 8 microsegundos), se pasa al estado DMX_ESPERA_START, ¿esto no genera problemas de lecturas?

hasta acá llegue, la verdad es que estoy muy entusiasmado con este tema.

abrazo.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: Receptor DMX (DMX512)
« Respuesta #82 en: 18 de Abril de 2011, 02:41:59 »
Hola lagruya, la verdad es que no recuerdo el protocolo con un nivel de detalle como para poder contestarte, y me pillas de viaje.
Pero en cuanto vuelva a casa y pueda dedicarle un ratito intentaré encontrar la respuesta a tus dudas. Un saludo

Desconectado lagruya

  • PIC16
  • ***
  • Mensajes: 204
Re: Receptor DMX (DMX512)
« Respuesta #83 en: 18 de Abril de 2011, 22:46:26 »
 :mrgreen: esperare con ansias tu respuesta, desde ya muchas gracias. Mientras tanto le sigo echando el ojo haber que descubro.

saludos.

Desconectado lagruya

  • PIC16
  • ***
  • Mensajes: 204
Re: Receptor DMX (DMX512)
« Respuesta #84 en: 10 de Mayo de 2011, 10:28:26 »
despues de recorrer una y otra vez el codigo saco las siguientes conclusiones y dudas:


El baud rate es de 250khz esto implicaria que un bit equivale a 4µseg .

La recepcion del noveno bit esta habilitada con lo cual si tenemos en cuenta el bit de stop y el de start tenemos un formato exacto al de datos de DMX con la coincidencia del tiempo tambien (en total 44µseg).

primera duda:

La señal de break en DMX es mayor o igual a 88µseg y menor a 1seg. Esta señal no se adapta al formato de datos de la usart, por eso se la detecta como un error de frame porque el bit STOP es igual a 0 y segun el codigo como DATORX = 0, DMX ESTADO = DMX ESPERA START.
Acá la duda:
BREAK es >= a 88µseg el dato leido (DATORX) junto con el 9no bit mas los de start y stop dan un total de 44µseg, esto implica que el siguiente dato a leer seguira siendo la marca de BREAK y habra otro error de FRAME pero ahora el DMX ESTADO = ESPERA START y en ese caso si FERR = 1 DMX ESTADO pasa a ser DMX ESPERA BYTE, esto seria un circulo visioso.

segunda duda:

CASE DMX ESPERA START: en este caso se saltea la MARK AFTER BREAK y segun el codigo si DATORX = 0,  DMX ESTADO = DMX ESPERA BREAK. Como no se espera la marka AFTER BREAK acá veo otro circulo vicioso, porque la marca AFTER BREAK es distinta de cero, que es lo que se espra en el case DMX ESPERA START.

espero no ser un pesado con estas preguntas, pero es que me resulta muy interesante el  tema, ademas es obvio que el codigo funciona. Es que no me gusta la idea de copiarlo sin comprenderlo.

gracias!

Desconectado Chipcon

  • PIC12
  • **
  • Mensajes: 63
Re: Receptor DMX (DMX512)
« Respuesta #85 en: 10 de Mayo de 2011, 11:28:10 »
Saludos lagruya estoy leyendo el tema y creo que tus dudas son de acuerdo al software pero no con el comportamiento del hardware.
Lo que he comprendido del código del amigo nocturno es que lee toda una trama y solo hasta detectar el ultimo byte de la trama entonces inicia el procesamiento.
Entonces el space to break como bien sabes sincroniza una trama este valor es una señal a 0 que tiene un tiempo de 88uS mínimo y típico de 176uS.

Cuando sucede el break la usart detecta el frame error pues no detecto stop bit, entonces ya tenemos detectado el space to break y solo verifica esto con DatoRX == 0 pero la señal no cambia, entonces la usart se queda en ese estado, sin embargo la maquina de estados ya paso a espera start.

Pero solo se iniciara una nueva lectura hasta producir otro start bit; esto sucede hasta terminar mark after break.

Es decir que el siguiente dato que la usart recibe es start code, entonce la maquina de estados pasa a recepción de datos,creo que solo por seguridad con cada nueva recepción verifica si existe un frame error
pero una vez iniciada la trama es muy difícil que se produzca un error en algún byte.

Ya por ultimo por que entonces no se produce otro frame error??.
La usart utiliza un reloj asíncrono, sample bit que se encarga de verificar el estado de cada bit pero esto no es inmediato en cada flanco es decir; que frame error solo ocurre si después de detectar el 9nvo. bit
el siguiente sample bit la señal no paso a '1'

Bueno espero haber ayudado con tus dudas
saludos
 

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: Receptor DMX (DMX512)
« Respuesta #86 en: 10 de Mayo de 2011, 11:35:30 »
Efectivamente, no cambia de byte, y por tanto de estado, hasta que la señal sube a 1. Es por ello que al recibir un 1 transcurridos más de 44us levanta el error de frame.
Disculpa que no haya contestado antes; se me olvidó volver a este hilo.

Desconectado lagruya

  • PIC16
  • ***
  • Mensajes: 204
Re: Receptor DMX (DMX512)
« Respuesta #87 en: 10 de Mayo de 2011, 13:41:15 »
 :cheesy: y se hizo la luz  :cheesy:

el meollo de mi confucion estaba en que no tuve en cuenta el START BIT ya que no hay cambio de flanco no lo encuentra lo que implica que no se produce ninguna nueva recepcion de datos, HASTA que llega la marca AFTER BREAK que su flanco de caida es interpretado como el start bit de una nueva transmision de datos, luego de ese momento tenemos otro DATORX == 0 y ya estamos en condiciones de ir al estado DMX_RECEPCION_DATOS !!!!!!!!!!!!!!!!

Estimado Chipcon, chagracia por la pronta y eficaz respuesta!!!!!!!!!!
Estimado Nocturno: recontra agradecido por la inteligencia empleada en tan util programa!!!!!

saludos!  :mrgreen:

Desconectado chirola83

  • PIC10
  • *
  • Mensajes: 4
Re: Receptor DMX (DMX512)
« Respuesta #88 en: 10 de Mayo de 2011, 21:31:25 »
Hola a todos, primero que nada, un capo el Sr. Nocturno!. Tu codigo y documentacion me ha sido de mucha utilidad y tambien las modificaciones realizadas por mrlicho.

En resumen, aqui esta el resultado de mi implementacion con un PIC16F628, con salida para 9 canales.


Saludos!
« Última modificación: 10 de Mayo de 2011, 22:20:24 por chirola83 »

Desconectado chirola83

  • PIC10
  • *
  • Mensajes: 4
Re: Receptor DMX (DMX512)
« Respuesta #89 en: 10 de Mayo de 2011, 22:18:07 »
Se que el codigo puede mejorarse, estas son solo pruebas y tal vez a alguien le pueda servir.





Código: [Seleccionar]
#include <16F628A.h>

#FUSES WDT                      //Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES PUT                      //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,RESTART_WDT)             // Utilizo clock de 20MHz porque me facilita la elección exacta del baudrate a 250k y tenia el cristal


/************************************************************************
*                    Registros USART                                    *
************************************************************************/

#byte SPBRG=              0x99         // Registros para el pic 16F628
#byte RCSTA=              0x18         // Aqui se han modificado las direcciones correspondientes para el 628
#byte TXSTA=              0x98     
#byte RCREG=              0x1A     
#byte PIR1=               0x0C     
#byte PIE1=               0x8C     


#bit SPEN=                RCSTA.7
#bit RX9=                 RCSTA.6
#bit SREN=                RCSTA.5     
#bit CREN=                RCSTA.4   
#bit ADDEN=               RCSTA.3
#bit FERR=                RCSTA.2   
#bit OERR=                RCSTA.1
#bit RX9D=                RCSTA.0     
#bit BRGH=                TXSTA.2
#bit SYNC=                TXSTA.4       
#bit RCIF=                PIR1.5       
#bit RCIE=                PIE1.5       


/************************************************************************
*                    Estados protocolo DMX                              *
************************************************************************/

#define       DMX_ESPERA_BYTE              0
#define       DMX_ESPERA_BREAK            1
#define       DMX_ESPERA_START            2
#define       DMX_ESPERA_DATO             3
#define       DMX_RECEPCION_DATOS     4


/************************************************************************
*                    Variables globales y constantes                    *
************************************************************************/

//--------------------Se han quitado las variables que no utilizo--------------------------------------

int8 DMX_Estado = DMX_ESPERA_BREAK;                        // Estado de la máquina de estados
int8 DatoRX;                                                                  // Dato genérico recibido en USART
int8 DMX_Indice = 0;                                                      // Apuntador a una posición de la trama DMX
int8 Ticks = 0;

#define TotalCanales          9            // Total canales a almacenar en este caso solo interesan los 3 primeros
int8 TramaDMX[TotalCanales]= {0,0,0,0,0,0,0,0,0};          // Trama completa de valores DMX
int8 r1,g1,b1,r2,g2,b2,r3,g3,b3;

union                                               // Estructura para hacer una copia del registro RCSTA
  {
    unsigned char registro;
    struct {
        unsigned char RX9D:1;
        unsigned char OERR:1;
        unsigned char FERR:1;
        unsigned char ADDEN:1;
        unsigned char CREN:1;
        unsigned char SREN:1;
        unsigned char RX9:1;
        unsigned char SPEN:1;
    } bits ;
  }Copia_RCSTA;


/************************************************************************
*          Interrupción Timer 0:                                        *
************************************************************************/
#int_Timer0
TIMER0_isr()
{
   Ticks++;

   if (Ticks==0)
   {
      r1 = TramaDMX[0];
      g1 = TramaDMX[1];
      b1 = TramaDMX[2];
      r2 = TramaDMX[3];
      g2 = TramaDMX[4];
      b2 = TramaDMX[5];
      r3 = TramaDMX[6];
      g3 = TramaDMX[7];
      b3 = TramaDMX[8];

      output_high(pin_A1);
      output_high(pin_A0);
      output_high(pin_B7);
      output_high(pin_B4);
      output_high(pin_B5);
      output_high(pin_B6);
      output_high(pin_A2);
      output_high(pin_A3);
      output_high(pin_B3);
   }

   if(Ticks==r1)
      output_low(pin_A2);
   if(Ticks==g1)
      output_low(pin_A3);
   if(Ticks==b1)
      output_low(pin_B3);

   if(Ticks==r2)
      output_low(pin_B4);
   if(Ticks==g2)
      output_low(pin_B5);
   if(Ticks==b2)
      output_low(pin_B6);

   if(Ticks==r3)
      output_low(pin_B7);
   if(Ticks==g3)
      output_low(pin_A0);
   if(Ticks==b3)
      output_low(pin_A1);

   set_timer0(128);
}
/************************************************************************
*  Interrupción RDA: dato recibido por la USART                         *
*  Esta interrupción se activa cada vez que se recibe un dato en la     *
*  USART. Mediante el control de una máquina de estados se determina    *
*  la validez y el significado del dato recibido, y se obra en          *
*  consecuencia.                                                        *
************************************************************************/

//--------La interrupción de la USART no se ha modificado, esta tal cual el receptor de Nocturno----------------
//--------solo cambia el hecho de que TotalCanales vale 3 en lugar de 512----------------------------------------

#int_rda
void Dato_Recibido_USART(void)
{
   while (RCIF) // ejecutamos mientras haya un dato pendiente de procesar
   {
    // Hacemos una copia del registro RCSTA porque sus bits cambian de valor
    // al leer RCREG y modificar CREN
    Copia_RCSTA.registro = RCSTA;

    // En RCREG está el dato que acaba de recibir la USART
    DatoRX = RCREG;

    // Si se reciben más de 3 bytes sin haberlos procesado, se produce un error
    // de Overrun. En este caso, se borra el error reiniciando CREN y dejamos
    // la interrupción preparada para procesar la siguiente trama DMX
    if (Copia_RCSTA.bits.OERR)
    {
      CREN=0;
      CREN=1;
      DMX_Estado = DMX_ESPERA_BYTE;
      return;
    }

    // Máquina de estados
    switch (DMX_Estado)
    {
      case DMX_ESPERA_BYTE:   // si estamos en este estado y hay error FRAME
      // es que nos ha pillado en medio de un Byte. Hay que seguir esperando
      // hasta que desaparezca el error.
        if (!Copia_RCSTA.bits.FERR)
              // Ha llegado un byte. Ahora esperaremos la señal Break
          DMX_Estado = DMX_ESPERA_BREAK;
        break;


      case DMX_ESPERA_BREAK:   // estamos esperando la señal Break
        // Esta señal se identifica porque aparece el error de Frame
        if (Copia_RCSTA.bits.FERR)
          // Tras recibir el error de Break, hay que esperar un byte de valor 0
          if (!DatoRX)
            DMX_Estado = DMX_ESPERA_START;
        break;
      case DMX_ESPERA_START: // ya hemos recibido el Break y ahora hay que
          // esperar un Byte con valor 0, que será la señal de Start
        // Mientras tanto, si recibimos un error de Frame, hay que volver a
        // empezar para recibir la señal de comienzo de trama.
        if (Copia_RCSTA.bits.FERR)
            DMX_Estado = DMX_ESPERA_BYTE;
        else {
          if (!DatoRX)
          {
            // Llegados a este punto, ya hemos recibido el Byte Start=0
            // y comenzamos la trama de valores DMX.
            DMX_Indice = 0;
            DMX_Estado = DMX_RECEPCION_DATOS;
          } else
            // Si el dato recibido no es 0, volvemos a empezar
            DMX_Estado = DMX_ESPERA_BREAK;
        }
        break;
      case DMX_RECEPCION_DATOS:
        // En este estado estamos recibiendo la trama de datos DMX
        // Si se detecta un error de Frame es que ha habido un error y estamos
        // al principio
        if (Copia_RCSTA.bits.FERR)
          if (!DatoRX)
            DMX_Estado = DMX_ESPERA_START;
          else
            DMX_Estado = DMX_ESPERA_BYTE;
        else
        {
          // Almacenamos el dato recibido en nuestro array
          TramaDMX[DMX_Indice++] = DatoRX;

          // Si ha llegado al final de la capacidad, cambiamos al estado de espera
          // de nueva trama
          if (DMX_Indice >= TotalCanales)
            DMX_Estado = DMX_ESPERA_BREAK;
        }
        break;
      }
   }
   return;
}

void main()
{
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_wdt(WDT_18MS);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(False);
   


   // Configuración de la USART

SPBRG=4;          // A 20Mhz el baudrate es 250.000, sale de la tabla de la hoja de datos del 16F628
BRGH=1;           // Seleccionamos high speed
SYNC=0;           // Transmisión asíncrona
SPEN=1;           // Activamos la USART
RX9=1;            // 9 bit para la recepcion
SREN=0;           // Desactiva recepción de un byte
CREN=1;           // Recepción activada
ADDEN=0;          // Desactivada la autodetección de dirección
FERR=0;           // No hay error de frame con 1 se activa
OERR=0;           // No hay error de overrun con 1 se activa


 // Activamos las interrupciones de recepción de la USART y del Timer0

   enable_interrupts(INT_RDA);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);



//-----------------------------------------------------------

   set_timer0(128);

   while(1){ delay_ms(5000);}
}


Saludos!