![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
g-netix
Joined: 19 Aug 2012 Posts: 19
|
how to detect framing error |
Posted: Fri Jul 26, 2013 11:10 am |
|
|
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! ;) |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9173 Location: Greensville,Ontario
|
|
Posted: Fri Jul 26, 2013 2:33 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
g-netix
Joined: 19 Aug 2012 Posts: 19
|
|
Posted: Fri Jul 26, 2013 3:51 pm |
|
|
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'... |
|
![](templates/subSilver/images/spacer.gif) |
g-netix
Joined: 19 Aug 2012 Posts: 19
|
|
Posted: Sun Jul 28, 2013 2:11 pm |
|
|
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](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
spilz
Joined: 30 Jan 2012 Posts: 218
|
|
Posted: Thu Sep 11, 2014 1:29 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|