AnsweredAssumed Answered

STM32F4 DMX-512 Receiver (with separate timer pin, DMA RX)

Question asked by reimer.paul on Feb 1, 2015
Latest reply on Jul 28, 2015 by aguilar.genis
I have spent the last couple days debugging the behaviour of a DMX-512 driver using the older STM32 STDPERIPH libraries.

In this implementation, I am using USART1/DMA for data rx, and TIM4 ch1 in PWM input capture mode to detect the 88usec break before USART data can be received. I simply joined the two pins together in push-pull floating mode. I made a simple test case using an RTOS, and I can confirm the hardware seems fine for this case.

For the STDPERIPH version, the timer for BREAK detection works fine, and *should* trigger a DMA transfer for the expected 512+1 bytes (513 total size). Confirmed with logic analyzer, it can toggle a pin after each BREAK is detected, but before the first USART start bit is received.

MY PROBLEM IS: the DMA and/or the USART does not seem to be responding. Same configuration; USART works fine in TX mode with DMA transfers (250kbaud, 2 stop bits, etc. as per DMX standard), although I do not have an example that generates a BREAK before TX.

Attached is the DMX rx driver code:
001.// Private typedef -------------------------------------------------------------
002.// Private define --------------------------------------------------------------
003.// Private macro ---------------------------------------------------------------
004.// Private variables -----------------------------------------------------------
005.uint8_t DMX_rx_mark_overflow = 0;
006.uint8_t DMX_rx_transferInProgress = 0;
007. 
008.uint8_t DMX_rxBuffer[513];
009. 
010.// Private function prototypes -------------------------------------------------
011.static void DMX_RCC_Config(void);
012.static void DMX_GPIO_Config(void);
013.static void DMX_NVIC_Config(void);
014.static void DMX_USART_Config(void);
015.static void DMX_RX_DMA_Config(void);
016.static void DMX_TIM_Config(void);
017. 
018.// Private functions -----------------------------------------------------------
019.void
020.DMX_Config(void)
021.{
022.  DMX_RCC_Config();
023.  DMX_NVIC_Config();
024.  DMX_GPIO_Config();
025.  DMX_USART_Config();
026.  DMX_TIM_Config();
027. 
028.  // Enable TIM4 counter
029.  TIM_Cmd(TIM4, ENABLE);
030. 
031.  // Enable USART
032.  USART_Cmd(USART1, ENABLE);
033. 
034.  DMX_RX_DMA_Config();
035.  // Enable the USART Rx DMA request
036.  USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
037.}
038. 
039.static void DMX_RCC_Config(void)
040.{
041.  // Enable GPIO clocks
042.  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
043. 
044.  // USART1 clock enable
045.  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
046. 
047.  // DMA clock enable
048.  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
049. 
050.  // TIM4 clock enable
051.  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
052.}
053. 
054.static void DMX_GPIO_Config(void)
055.{
056.  GPIO_InitTypeDef GPIO_InitStructure;
057.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
058.  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
059.  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
060.  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
061. 
062.  // DMX RX pin configuration
063.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
064.  GPIO_Init(GPIOB, &GPIO_InitStructure);
065.  // Connect DMX RX pin to AF
066.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
067. 
068.  // DMX MARK pin configuration
069.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
070.  GPIO_Init(GPIOB, &GPIO_InitStructure);
071.  // Connect DMX MARK pin to AF
072.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_TIM4);
073. 
074.  // debug MARK pin configuration
075.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
076.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
077.  GPIO_Init(GPIOA, &GPIO_InitStructure);
078.}
079. 
080.static void DMX_NVIC_Config(void)
081.{
082.  NVIC_InitTypeDef NVIC_InitStructure;
083.  // Enable the USART1 global Interrupt
084.  // Configure the Priority Group to 2 bits
085.  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
086. 
087.  // Enable the UART RX DMA Interrupt
088.  NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn;
089.  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
090.  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
091.  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
092.  NVIC_Init(&NVIC_InitStructure);
093. 
094.  // Enable the TIM4 global Interrupt
095.  NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
096.  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
097.  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
098.  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
099.  NVIC_Init(&NVIC_InitStructure);
100.}
101. 
102.static void DMX_USART_Config(void)
103.{
104.  USART_InitTypeDef DMX_InitStructure;
105. 
106.  // Enable the USART OverSampling by 8
107.  USART_OverSampling8Cmd(USART1, ENABLE);
108. 
109.  DMX_InitStructure.USART_BaudRate = 250000;
110.  DMX_InitStructure.USART_WordLength = USART_WordLength_8b;
111.  DMX_InitStructure.USART_StopBits = USART_StopBits_2;
112.  DMX_InitStructure.USART_Parity = USART_Parity_No;
113.  DMX_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
114.  DMX_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
115.  USART_Init(USART1, &DMX_InitStructure);
116.}
117. 
118.static void DMX_RX_DMA_Config(void)
119.{
120.  DMA_InitTypeDef DMA_InitStructure;
121. 
122.  // Configure DMA controller to manage TX DMA requests
123.  // first make sure we are using the default values
124.  DMA_StructInit(&DMA_InitStructure);
125. 
126.  // Configure DMA controller to manage USART TX and RX DMA request ------------
127.  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(USART1->DR);
128.  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
129.  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
130. 
131.  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
132.  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
133.  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
134.  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
135.  //DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
136. 
137.  // RX Stream -----------------------------------------------------------------
138.  DMA_DeInit(DMA2_Stream2);
139. 
140.  DMA_InitStructure.DMA_Channel = DMA_Channel_4;
141.  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
142.  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DMX_rxBuffer;
143.  DMA_InitStructure.DMA_BufferSize = sizeof(DMX_rxBuffer);
144. 
145.  DMA_Init(DMA2_Stream2, &DMA_InitStructure);
146. 
147.  DMA_ITConfig(DMA2_Stream2, DMA_IT_TC, ENABLE);
148.  DMA_ITConfig(DMA2_Stream2, DMA_IT_HT, ENABLE);
149.}
150. 
151.static void DMX_TIM_Config(void)
152.{
153.  TIM_ICInitTypeDef TIM_ICInitStructure;
154.  NVIC_InitTypeDef NVIC_InitStructure;
155. 
156.  // TIM4 configuration
157.  TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
158.  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
159.  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
160.  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
161.  TIM_ICInitStructure.TIM_ICFilter = 0x0;
162. 
163.  TIM_PWMIConfig(TIM4, &TIM_ICInitStructure);
164. 
165.  // Select the TIM4 Input Trigger
166.  TIM_SelectInputTrigger(TIM4, TIM_TS_TI1FP1);
167. 
168.  // Select the slave Mode: Reset Mode
169.  TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
170.  TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable);
171. 
172.  // Only generate Update Event on counter overflow
173.  TIM_UpdateRequestConfig(TIM4, TIM_UpdateSource_Regular);
174. 
175.  // Enable the DMX_MARK_TIM_IT_CCx Interrupt Requests
176.  TIM_ITConfig(TIM4, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_Update, ENABLE);
177.}
178. 
179.int
180.DMX_is_recv_done()
181.{
182.  return (DMX_rx_transferInProgress == 0);
183.}
184. 
185.void TIM4_IRQHandler(void)
186.{
187.  if (TIM_GetITStatus(TIM4, TIM_IT_CC1))
188.  {
189.    TIM_ClearITPendingBit(TIM4, TIM_IT_CC1);
190.  }
191. 
192.  if (TIM_GetITStatus(TIM4, TIM_IT_CC2))
193.  {
194.    TIM_ClearITPendingBit(TIM4, TIM_IT_CC2);
195. 
196.    if (DMX_rx_mark_overflow == 1)
197.    {
198.      DMX_rx_mark_overflow = 0;
199.    }
200.    else {
201.      uint16_t pulseValue = TIM_GetCapture2(TIM4);
202. 
203.      if ((pulseValue > 8800))
204.      {
205.        DMX_RX_DMA_Config();
206.        DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2);
207.        DMA_Cmd(DMA2_Stream2, ENABLE);
208. 
209.        DMX_rx_transferInProgress = 1;
210. 
211.        //GPIO_ToggleBits(GPIOA, GPIO_Pin_8);
212.        GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
213.      }
214.    }
215.  }
216. 
217.  if (TIM_GetITStatus(TIM4, TIM_IT_Update))
218.  {
219.    TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
220. 
221.    DMX_rx_mark_overflow = 1;
222.  }
223.}
224. 
225.void DMA2_Stream2_IRQHandler(void)
226.{
227.  if (DMA_GetITStatus(DMA2_Stream2, DMA_IT_TCIF2))
228.  {
229.    DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TCIF2);
230.    DMX_rx_transferInProgress = 0;
231. 
232.    GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);
233.  }
234.}

Thanks in advance for your help!

Outcomes