0
\$\begingroup\$

I have a NUCLEO-F303RE board and try to send some data by one-wire UART with 57600 baudrate. But frames are sent broken (see images below):

How must to be: enter image description here

What I get: enter image description here

I've tried to use different clocks (HSE 32MHz and internal HSI 8MHz), change baud rate to 9600, but nothing helps and frames are broken the same way. I suppose I have a bad configuration of something, but I have no idea what is wrong. I have another UART connected which is used for debug and it works fine on 57600 baud rate (not in half-duplex mode) with same clock.

My UART configuration:

#define SERVO_PORT            GPIOB
#define SERVO_PIN             GPIO_PIN_10
#define SERVO_GPIO_ENABLE()   __HAL_RCC_GPIOB_CLK_ENABLE()

#define UART_INSTANCE         USART3
#define UART_CLK_ENABLE()     __HAL_RCC_USART3_CLK_ENABLE()
#define UART_AF               GPIO_AF7_USART3
#define UART_IRQ              USART3_IRQn
#define UART_IRQ_HANDLER      USART3_IRQHandler

static UART_HandleTypeDef huart = {
  .Instance          = UART_INSTANCE,
  .Init.BaudRate     = 57600,
  .Init.WordLength   = UART_WORDLENGTH_8B,
  .Init.StopBits     = UART_STOPBITS_1,
  .Init.Mode         = UART_MODE_TX_RX,
  .Init.Parity       = UART_PARITY_NONE,
};

/* Called later in HAL_UART_MspInit */
void Servo_UART_MspInit(UART_HandleTypeDef* h) {
  if (h == &huart) {
    SERVO_GPIO_ENABLE();
    UART_CLK_ENABLE();

    GPIO_InitTypeDef pin = {
      .Pin        = SERVO_PIN,
      .Mode       = GPIO_MODE_AF_PP,
      .Pull       = GPIO_NOPULL,
      .Speed      = GPIO_SPEED_FREQ_HIGH,
      .Alternate  = UART_AF,
    };
    HAL_GPIO_Init(SERVO_PORT, &pin);
  }
}

void initUART() {
  HAL_TIM_PWM_DeInit(&htim);

  HAL_HalfDuplex_Init(&huart);

  HAL_NVIC_SetPriority(UART_IRQ, 0, 0);
  HAL_NVIC_EnableIRQ(UART_IRQ);
  HAL_HalfDuplex_EnableReceiver(&huart);
}

bool servoSend(uint8_t* data, uint8_t size) {
  HAL_HalfDuplex_EnableTransmitter(&huart);
  return HAL_OK == HAL_UART_Transmit(&huart, data, size, HAL_MAX_DELAY);
}

And I send data like this:

...
uint8_t d[5] = {0x2B, 0x0, 0xD5, 2, 0xB1};
bool ret = servoSend(d, 5); 
if (!ret) return DITEX_SERVO_CALLBACK_FAILED;
...

My clock initialization:

static void initSystemClock() {
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;
  RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV2;
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_USART3
                              |RCC_PERIPHCLK_TIM2;
  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_SYSCLK;
  PeriphClkInit.Usart3ClockSelection = RCC_USART3CLKSOURCE_SYSCLK;
  PeriphClkInit.Tim2ClockSelection = RCC_TIM2CLK_HCLK;
}
\$\endgroup\$
6
  • \$\begingroup\$ Well the first problem I see is that your signal is inverted. That, of course, will confuse the receiver and cause a framing error. \$\endgroup\$
    – jwh20
    Jan 7 at 19:27
  • \$\begingroup\$ @jwh20 I've tried invert data logic or tx active level but then data is completely incorrect. Invertion of rx active level changes nothing \$\endgroup\$
    – Shadasviar
    Jan 7 at 19:34
  • \$\begingroup\$ Well it's inverted and that's wrong. Fix that and move to next problem. \$\endgroup\$
    – jwh20
    Jan 7 at 19:52
  • 1
    \$\begingroup\$ What does "one-wire UART" mean? You are using a common ground, aren't you? \$\endgroup\$ Jan 7 at 21:35
  • 1
    \$\begingroup\$ Are you checking that the content of your UART TX data register have been successfully shifted by for example while(!(USART1->ISR & USART_ISR_TXE)) checking that the TX register is empty. Otherwise this smells like a clock/baud mismatch, show us your clock tree, the clock source for your USART is the system clock and not the APB where I assume the USART is connected to \$\endgroup\$
    – Sorenp
    Jan 8 at 7:02
1
\$\begingroup\$

Problem was in UART pin configuration: it needed to be pulled up instead of open drain:

GPIO_InitTypeDef pin = {                                                   
      .Pin        = SERVO_PIN,                                                 
      .Mode       = GPIO_MODE_AF_PP,                                           
      .Pull       = GPIO_PULLUP,                                               
      .Speed      = GPIO_SPEED_FREQ_HIGH,                                      
      .Alternate  = UART_AF,                                                   
};                                                                         
HAL_GPIO_Init(SERVO_PORT, &pin);
\$\endgroup\$
0
\$\begingroup\$

I believe that you have problem in configuring the system clock. You can use ST's STM32CubeIDE to get the right configuration.

If you are using crystal, use

  RCC_OscInitStruct.HSEState = RCC_HSE_ON;

You specified RCC_HSE_BYPASS, unless you have clock source (not crystal).

(sorry, I have to put this as answer as I do not have enough reputation)

\$\endgroup\$

This site is temporarily in read only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .