CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

how to detect framing error

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
g-netix



Joined: 19 Aug 2012
Posts: 19

View user's profile Send private message

how to detect framing error
PostPosted: Fri Jul 26, 2013 11:10 am     Reply with quote

Hi,

I use hardware UART @ 250k baud with brgh1ok like this :

Code:
#include <18F46K22.h>
#device ICD=TRUE
#device adc=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOBROWNOUT               //No brownout reset
#FUSES WDT_NOSLEEP              //Watch Dog Timer, disabled during SLEEP
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on 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 NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES DEBUG                    //Debug mode for use with ICD

#use delay(int=64000000)

#use rs232(baud=250000,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=DMX,stop=1,brgh1ok,ERRORS)


I use it to generate a DMX frame :

Code:
#include <main.h>

#define BREAK_TIME      88                                                                // BREAK = 88us
#define MAB_TIME        8                                                                 // MARK AFTER BREAK = 8us
#define START_CODE      0x00                                                              // START CODE = 0 typical. other statement are reserved.
#define DMX_BREAK       setup_uart (FALSE); output_low (PIN_C6); delay_us (BREAK_TIME);   // Generate a LOW LEVEL on Tx PIN
#define DMX_MAB         output_high (PIN_C6); delay_us (MAB_TIME);                        // Generate an HIGH LEVEL on Tx PIN
#define DMX_START_CODE  setup_uart (TRUE); putc (START_CODE,DMX);                         // Send the code 0x00 on the UART

int i;
/*
#int_RDA
void RDA_isr(void)
   {
   
   }
*/ 
void main()
   {
   setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
   setup_timer_4(T4_DISABLED,0,1);
   setup_timer_5(T5_DISABLED | T5_DIV_BY_1);
   setup_timer_6(T6_DISABLED,0,1);
// enable_interrupts (INT_RDA);
// enable_interrupts (GLOBAL);
   while(TRUE)
      {
      if (i==0 || i==20)
         {
         i=0;
         DMX_BREAK;
         DMX_MAB;
         DMX_START_CODE;
         i=1;
         }
      putc (i,DMX);
      i++;
      }
   }


it works fine.

Now I'd like to do a receiver. For that I use RS232_ERRORS to detect the 88 µs length DMX_BREAK (level '0').
but I test RS232_ERRORS (each bit) and it appears that none change when I put a '0' on Rx pin... what should I do to detect framing error, which bit to test?

Thank's! ;)
temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jul 26, 2013 2:33 pm     Reply with quote

You should really download and read the 18F46k22 datasheet...well at least the section on the EUSART(chapter 16).Yes, I know reading 600 pages can be tedious but...the more you know, the better programmer you'll be.
In there, on page 275 you'll find the table with the information you need.
The 'errors' info might be in the CCS header file as well( I haven't checked) as I always consult the PIC datasheet first, then the header...

hth
jay
g-netix



Joined: 19 Aug 2012
Posts: 19

View user's profile Send private message

PostPosted: Fri Jul 26, 2013 3:51 pm     Reply with quote

Thank's for your reply ;)

So it seems not to be anything in the header, but I found in the datasheet that FERR is bit 2 of RCSTAx register.

I tried this :

Code:
#include <main.h>

#define BREAK_TIME      200//88                                                                // BREAK = 88us
#define MAB_TIME        8                                                                 // MARK AFTER BREAK = 8us
#define START_CODE      0x00                                                              // START CODE = 0 typical. other statement are reserved.
#define DMX_BREAK       setup_uart (FALSE); output_low (PIN_C6); delay_ms (BREAK_TIME);   // Generate a LOW LEVEL on Tx PIN
#define DMX_MAB         output_high (PIN_C6); delay_us (MAB_TIME);                        // Generate an HIGH LEVEL on Tx PIN
#define DMX_START_CODE  setup_uart (TRUE); putc (START_CODE,DMX);                         // Send the code 0x00 on the UART

int i;
char test;

#int_RDA
void RDA_isr(void)
   {
   test=getc (DMX);
   if ((RS232_ERRORS & 0x04)==0x04)
      {
      output_high (PIN_B5);
      }
   }
   
void main()
   {
   setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
   setup_timer_4(T4_DISABLED,0,1);
   setup_timer_5(T5_DISABLED | T5_DIV_BY_1);
   setup_timer_6(T6_DISABLED,0,1);
   enable_interrupts (INT_RDA);
   enable_interrupts (GLOBAL);
   while(TRUE)
      {
      if ((RS232_ERRORS & 0x04)!=0x04)
         {
         output_low (PIN_B5);
         }
      if (i==0 || i==2)
         {
         i=0;
         DMX_BREAK;
         DMX_MAB;
         DMX_START_CODE;
         i=1;
         }
      putc (i,DMX);
      i++;
      }
   }


it seems to appear something but it's not clear... if I put '1' then I put briefly few '0' and High-Z alternatively sometimes B5 switch to 1. But If I put Tx on Rx, I have my RS232 signal but nothing occurs on B5 while there is a period of 200 ms at '0'...
g-netix



Joined: 19 Aug 2012
Posts: 19

View user's profile Send private message

PostPosted: Sun Jul 28, 2013 2:11 pm     Reply with quote

Finally I think I've managed to implement a DMX512 receiver. I haven't tested it with a real DMX controller but it seems to do its job with the same PIC with UART1 TX linked to UART2 RX.

I can control an RGB LED with 8 bits PWM.

For those interrested in doing their own here is my programm ;)

Code:
#include <main.h>

#define BREAK_TIME         88                                                                   // BREAK = 88us
#define MAB_TIME           8                                                                    // MARK AFTER BREAK = 8us
#define DMX_START_CODE     0x00                                                                 // START CODE = 0 typical. other statement are reserved.
#define DMX_BREAK          setup_uart (FALSE,DMX); output_low (PIN_C6); delay_us (BREAK_TIME);  // Generate a LOW LEVEL on Tx PIN
#define DMX_MAB            output_high (PIN_C6); delay_us (MAB_TIME);                           // Generate an HIGH LEVEL on Tx PIN
#define DMX_START_CODE     setup_uart (TRUE,DMX); putc (START_CODE,DMX);                        // Send the code 0x00 on the UART
#define FRAMING_ERROR      (RS232_ERRORS & 0x04)==0x04                                          // Detecting framing error for 88µs DMX break detection

char dmx_trame [513];                                                                           // 0 to 512, 0 => Start code, 1 - 512 => DMX data bytes
int16 dmx_channel;                                                                              // byte/channel number : 0 to 512
int16 ptr_buffer;                                                                               // poiter to "dmx_trame [x]"
int16 dmx_address=0;                                                                            // Set the DMX receiver address
int start_code;                                                                                 // Start code, expect 0x00 when tested
int channel_1;                                                                                  // DMX receiver channel 1, idependent of DMX address number
int channel_2;                                                                                  // DMX receiver channel 2, idependent of DMX address number
int channel_3;                                                                                  // DMX receiver channel 3, idependent of DMX address number
int u1;                                                                                         // User data value for channel 1
int u2;                                                                                         // User data value for channel 2
int u3;                                                                                         // User data value for channel 3

#int_RDA2                                                                                       // DMX RECEIVER interrupt
void RDA2_isr(void)
   {
   dmx_trame [ptr_buffer] = getc (UART);                                                        // Receiving data
   ptr_buffer++;                                                                                // go to next byte
   if (FRAMING_ERROR)                                                                           // Detection of DMX Break (88µs à '0')
      {
      ptr_buffer=0;                                                                             // Re-init DMX trame
      output_high (PIN_B5);                                                                     // LED for test/debug
      delay_us (25);                                                                            // LED for test/debug
      output_low (PIN_B5);                                                                      // LED for test/debug
      }
   }
   
void main()
   {
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   setup_timer_3(T3_INTERNAL | T3_DIV_BY_1);
   setup_timer_4(T4_DIV_BY_1,0,1);
   setup_ccp1(CCP_PWM|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L|CCP_USE_TIMER3_AND_TIMER4);
   setup_ccp2(CCP_PWM|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L|CCP_USE_TIMER3_AND_TIMER4);
   setup_ccp3(CCP_PWM|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L|CCP_USE_TIMER3_AND_TIMER4);
   enable_interrupts (INT_RDA2);
   enable_interrupts (GLOBAL);
   
   while(TRUE)
      {
      dmx_address=0;                                                                            // Set the DMX address from 0 to 508 (1 to 509)
      u1=0x00;                                                                                  // Adjust manually the value or link it to a 8 bits ADC
      u2=0xff;                                                                                  // Adjust manually the value or link it to a 8 bits ADC
      u3=0xff;                                                                                  // Adjust manually the value or link it to a 8 bits ADC
     
/******************************************************************************/     
/************************* DMX TRANSMITTER ************************************/
/******************************************************************************/

      if (dmx_channel==0 || dmx_channel==512)                                                   // Beginning of a new DMX trame
         {
         dmx_channel=0;                                                                         // Re-init DMX byte/channel number     
         DMX_BREAK;                                                                             // Send a break : send a LOW level during 88µs
         DMX_MAB;                                                                               // Send an HIGH level during 8µs
         DMX_START_CODE;                                                                        // Send 0x00
         dmx_channel++;                                                                         // increment dmx_channel => dmx_channel=1
         }
      putc ((u1),DMX);                                                                          // transmit the first data byte
      putc ((u2),DMX);                                                                          // transmit the second data byte
      putc ((u3),DMX);                                                                          // transmit the third data byte
     
      // you can add as channel as you want on [1-512] range
     
/******************************************************************************/     
/************************* DMX RECEIVER ***************************************/
/******************************************************************************/

      dmx_channel++;                                                                            // go to next data byte
      start_code = dmx_trame [0];                                                               // receive Start code
      channel_1 = dmx_trame [1 + dmx_address];                                                  // receive 1st data byte
      channel_2 = dmx_trame [2 + dmx_address];                                                  // receive 2nd data byte
      channel_3 = dmx_trame [3 + dmx_address];                                                  // receive 3rd data byte
      set_pwm1_duty((int)channel_1);                                                            // Blue LED output
      set_pwm2_duty((int)channel_2);                                                            // Red LED output
      set_pwm3_duty((int)channel_3);                                                            // Green LED output
      }
   }


main.h :
Code:
#include <18F46K22.h>
#device ICD=TRUE
#device adc=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOBROWNOUT               //No brownout reset
#FUSES WDT_NOSLEEP              //Watch Dog Timer, disabled during SLEEP
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on 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 NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES DEBUG                    //Debug mode for use with ICD
#FUSES CCP3E0                   //CCP3 input/output multiplexed with RE0

#use delay(int=64000000)

#use rs232(baud=250000,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=DMX,stop=1,brgh1ok)//,ERRORS)
#use rs232(baud=250000,parity=N,xmit=PIN_D6,rcv=PIN_D7,bits=8,stream=UART,errors,brgh1ok)

// Don't forget to link PIN_C6 with PIN_D7

Let me know what you think ;)
Bye! Smile
spilz



Joined: 30 Jan 2012
Posts: 219

View user's profile Send private message

PostPosted: Thu Sep 11, 2014 1:29 am     Reply with quote

I know it's a old topic,

just something you have to be carefull : in DMX protocol, there is 2 stop bits

so I think you should have
Code:
#use rs232(baud=250000,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=DMX,stop=2,brgh1ok)//,ERRORS)


regards
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group