cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407VG Custom Break over UART1 for DMX transmitting

PUrsu.1
Associate II

Hi everyone,

I am trying to output DMX data over UART1 at 25Hz. Therefore I need a break for 88us. My plan was to take control over the port and set it into GPIO Mode. After 88us I set it back to UART mode.

For breaktimes > 250us it works fine. But below that value the voltage spike only goes to roundabout 800mV. What am I doing wrong?

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
	if(htim == &htim3) {
		    setGPIOMode();
		    // wait 88 microseconds for the DMX break
		    delay_us(88);
		   setUartMode();
 
		    // wait 8 microseconds for the MAB (Mark After Break)
		    delay_us(8);
	}
}

void setGPIOMode() {
	GPIOA->MODER = (GPIOA->MODER & ~GPIO_MODER_MODER9_Msk) | (1 << GPIO_MODER_MODER9_Pos);
}
 
void setUartMode() {
	GPIOA->MODER = (GPIOA->MODER & ~GPIO_MODER_MODER9_Msk) | (2 << GPIO_MODER_MODER9_Pos);
}
void delay_us (uint16_t us)
{
 
	__HAL_TIM_SET_COUNTER(&htim2,0);  // set the counter value a 0
	while (__HAL_TIM_GET_COUNTER(&htim2) < us);  // wait for the counter to reach the us input in the parameter
}
static void MX_USART1_UART_Init(void)
{
 
  /* USER CODE BEGIN USART1_Init 0 */
 
  /* USER CODE END USART1_Init 0 */
 
  /* USER CODE BEGIN USART1_Init 1 */
 
  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 250000;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_2;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
  /* USER CODE END USART1_Init 2 */
 
}
static void MX_TIM2_Init(void)
{
 
  /* USER CODE BEGIN TIM2_Init 0 */
 
  /* USER CODE END TIM2_Init 0 */
 
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
 
  /* USER CODE BEGIN TIM2_Init 1 */
 
  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 83;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 4294967295;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */
 
  /* USER CODE END TIM2_Init 2 */
 
}
 
/**
  * @brief TIM3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM3_Init(void)
{
 
  /* USER CODE BEGIN TIM3_Init 0 */
 
  /* USER CODE END TIM3_Init 0 */
 
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
 
  /* USER CODE BEGIN TIM3_Init 1 */
 
  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 55;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 59999;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM3_Init 2 */
 
  /* USER CODE END TIM3_Init 2 */
 
}

 0693W000006FZooQAG.png

8 REPLIES 8

Where and how do you measure that voltage? Can you show oscilloscope screenshots for the two different cases?

JW

PUrsu.1
Associate II

0693W000006FaoLQAS.jpg0693W000006FaoaQAC.jpgHey Jan,

sure! Here are pictures with the delay set to 80us / 3000us.

Can't this be just your oscilloscope's limitation?

Do you measure after some optocoupler? If yes, try measuring directly on mcu pin.

JW

PUrsu.1
Associate II

Hey Jan,

I also had this thought. But toggling a normal GPIO pin with 80us delay in between works fine and the oscilloscope (100MHz 1GSa/s) displays the correct voltage (around 3,3V). I am measuring directly on the pin.

//I tried this code and the voltage of PD9 is at arround 300mV, the voltage of the oszi_Pin is at 3,3V
 
HAL_GPIO_TogglePin(oszi_GPIO_Port, oszi_Pin);
setGPIOMode();
delay_us(88);
setUartMode();
HAL_GPIO_TogglePin(oszi_GPIO_Port, oszi_Pin);
delay_us(88);

Tx on PA9 at 250kBaud works normally? at 250kBaud, one bit is 4us, if you transmit something like 0x55, do you see individual bits?

How is GPIO_OSPEEDR set for PA9? GPIO_ODR is set to 0 for PA9, I presume; but maybe you should read out the GPIOA registers and post them here.

Do you use OTG_FS?

JW

Hey Jan,

I should have probably mentioned that I'm using a STM32F407 discovery board. I found out that UART2 works fine for my purposes. I think that there must be any components on the board which disturb USART1. Could that be possible?

PUrsu.1
Associate II

Hey Jan,

thank you for your help. I can now successfully output DMX.

Edit for others with probably the same problem:

I figured out that there is a problem on the STM32F407 Discovery board when trying to use UART1. Using another UART solved the problem for me. I think there are some components on the PCB which cause problems with higher baud rates on UART1.

I have another question (I don't know if I should open another thread for that). I now have one DMX output. My goal is to output way more data (8 DMX ports). Where should I begin researching this "multi" task? Just outputting the universes one after one should be too slow in my thought.

Is FreeRTOS the way to go for?

DEdwi.1
Associate II

@PUrsu.1​ Would you consider using the PWM to generate the DMX512 signal ? there seems to be a lot of timers on the STM32F407 which can be used for PWM outputs