cancel
Showing results for 
Search instead for 
Did you mean: 

Receive DMX-512 in STM32 USART, without timer

FordFairlane
Associate III
Posted on February 04, 2011 at 12:25

Receive DMX-512 in STM32 USART, without timer

7 REPLIES 7
Posted on May 17, 2011 at 14:23

Perhaps because it has to synchronize data transmissions in the time domain to some reasonable precision.

If you can't use timers, look at using SysTick and the 32-bit instruction cycle (72 MHz) counter within the trace unit of the core for fine grain measurements.

You could also generate timing externally, or use some of the timers that don't do PWM

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
ColdWeather
Senior
Posted on May 17, 2011 at 14:23

Hello!

I have not seen the example yet, you talk about, but I suppose, a timer is used to recognize the BREAK condition strictly according to the DMX-512 specification (BREAK duration = 88us).

My experience says, it's not really necessary. You can use FE flag along with the fact, that BREAK makes data == 0. The BREAK detection part of the UART ISR can look like (using STM32F Device Library calls):

    if (USART_GetITStatus(usart, USART_IT_RXNE) == SET) {

        Flag = USART_GetFlagStatus(usart, USART_FLAG_FE);

        Data = USART_ReceiveData(usart);

        if (Flag == SET && Data == 0)

        {

             // BREAK condition recognized.

        }

         // do other jobs

    }

FordFairlane
Associate III
Posted on May 17, 2011 at 14:23

Thank you

I developed a DMX light some years ago with an 8 bit microcontroller using the UART built-in break detector, with 0 problems in some years and many users, but I wonder if the DMX512 2008 specification has changed the break timing or the STM32 LIN break detector is not compatible with DMX512 2008. I will study the STM32 LIN break detector and the framing error with 0 data to decide wich one suits better que DMX 2008 specification. Which one is better for DMX?, I think framing error with 0 data can cause problems in case the break is too long because it can be seen as many breaks.

Regards

Andrew Neil
Chief II
Posted on May 17, 2011 at 14:23

''... in case the break is too long ... it can be seen as many breaks''

 

I don't think so - because the UART won't start a new frame until it sees a valid start bit ?
FordFairlane
Associate III
Posted on May 17, 2011 at 14:23

Maybe the USART receives only one framing error. The framing error flag is set just after the first byte, while the break is detected when the pin goes high.

Maybe both of them could detect the start of DMX data, but this is not my question. 

Is the timer absolutely necessary to comply with DMX512 2008?

If I don't use the timer and I don't measure the break, could my customers find any problem?. This is for a commercial application, compatibility is mandatory.

(I have selected another STM32 with more timers, but I woluld like to clarify this issue)

Thank you

ColdWeather
Senior
Posted on May 17, 2011 at 14:23

Is the timer absolutely necessary to comply with DMX512 2008?

If I don't use the timer and I don't measure the break, could my customers find any problem?.

 

No problem. As long as the DMX line is not noisy, the cable is good, the UART has exactly 250kbps, everything works fine. Under normal conditions the only case you get FE is BREAK. And if not, that is a hardware fault. DMX-512 has no error correction. What are you gonna do if the UART does receive errors (mostly FE) for data bytes? You can do nothing even if you implement an exact measurement of BREAK duration. So you can rely upon that BREAK only generates data==0 and FE==set.

HThai
Associate

@ColdWeather​ Can you point out where those lines of codes have to be written to. In my program i put those in USART_IRQHandler ( in stm32f10x_it.c ) but it seems the interrupt never happens.

uint8_t dmx_receive[512];
uint16_t dmx_counter=0; 
bool breakCondition=false, startFrame=false; 
 
void USART1_IRQHandler(void){
 	if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET){/*Receive not Empty is True*/	
 
	FlagStatus FlagFrameError = USART_GetFlagStatus(USART1, USART_FLAG_FE);
 	uint8_t Data = USART_ReceiveData(USART1);
		 
	if(FlagFrameError == SET && Data == 0){
 	//Break condition recognized
	breakCondition = true;}
 
	if(breakCondition && USART_GetITStatus(USART1,USART_FLAG_FE)==RESET){
/*If in break condition and detect first frame recevied correctly*/
			startFrame=true;}
 
	if(startFrame){/*Receive 512 Bytes*/
            if(dmx_counter<512){/*data to dmx_receive*/
		dmx_receive[dmx_counter++]=USART_ReceiveData(USART1);}
	    else{/*reset breakCondition, startFrame*/
		breakCondition=false;
		startFrame=false;
		dmx_counter=0;
	    }
	}			 
    }
}

 My UART and NVIC configuration

void UART_Configuration(void){
	USART_InitTypeDef USART_InitStructure;
	
	USART_InitStructure.USART_BaudRate = 250000;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_2;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx;
	USART_Init(USART1,&USART_InitStructure);
	
	/*Clear Receive Flag*/
	USART_ClearFlag(USART1,USART_IT_RXNE);
	
	/*Enable interrupt when receive*/
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	
	/*Enable UART*/
	USART_Cmd(USART1,ENABLE);
}
void NVIC_Config(void){
	NVIC_InitTypeDef NVIC_InitStructure;
	/*Enable TIM2 interrupt*/
	NVIC_EnableIRQ(TIM2_IRQn);
	
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}