AnsweredAssumed Answered

STM32F407 USART1 Reception: glitch/noise issue

Question asked by JFDuval on Jul 31, 2014
Latest reply on Jul 31, 2014 by Ivan Ivanov

Setup: 2 custom boards (1 that's similar to the Discovery F4 and one that's based on a PSoC 5LP) linked by RS-485 (SN65HVD75 transceivers, half duplex, single twisted pair).

Data flow: the STM32F4 is the Master. It can send data to the PSoC and the PSoC can read it (no problem here). It can also request data from the slave. In that case, the STM32 will send a data request, configure its transceiver to listen to the bus and, after a fixed delay, the PSoC will send its answer (for now, 5 test bytes).

The problem: when I change the transceiver from TX to RX there is a glitch on the output line.  The line goes low for ~25ns. It seems to be detected as a start bit by the STM's USART1 peripheral. I receive 5 bytes, as expected, but they are not the right value. The first 4 have a constant value and the last one is different. Start and stop bits are being seen as data. Or at least that's what it looks like.

Experiments: I've tried to disable the USART, disable the reception, change the pin to be a GPIO, etc... without any success. Right now the test setup that I have has a wire going from the PSoC's TX line straight to the STM's RX line. By bypassing the transceiver I can receive the 5 bytes I'm sending by interrupt.



void HAL_USART_MspInit( USART_HandleTypeDef * husart)
  if(husart-> Instance==USART1)
    /* Peripheral clock enable */
        /**USART1 GPIO Configuration
       PA9   ------> USART1_TX
       PA10   ------> USART1_RX
    GPIO_InitStruct. Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct. Mode = GPIO_MODE_AF_PP;
    //GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct. Pull = GPIO_PULLUP;                 //Transceiver's R is Hi-Z when !RE=1
    GPIO_InitStruct. Speed = GPIO_SPEED_FAST;
    GPIO_InitStruct. Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

USART1 Init function:

//USART1 init function: RS-485 #1
void USART1_Init( void )
       husart1. Instance = USART1;
        //MSP Init (enables clock, GPIOs)
       HAL_NVIC_SetPriority( USART1_IRQn, 0, 1);
       HAL_NVIC_EnableIRQ( USART1_IRQn);
        //UART1 module:
        //husart1.Init.BaudRate = 115200;
       husart1. Init. BaudRate = 921600;
       husart1. Init. WordLength = USART_WORDLENGTH_8B;
       husart1. Init. StopBits = USART_STOPBITS_1;
       husart1. Init. Parity = USART_PARITY_NONE;
       husart1. Init. Mode = USART_MODE_TX_RX;
        //With only HAL_USART_Init() I never get an interrupt. Manually setting 5 bits:
       USART1-> CR1 |= 0b00000000000000010000000000100100;      //16x oversampling , Receive enable, enable RXNE interrupts
       USART1-> CR2 &= 0b11111111111111111111011111111111;      //Disable synchronous clock
       USART1-> CR3 &= 0b11111111111111111111011111111111;      //3 bits method

This is what I call after I send a Reply Request. The request is as simple as"HAL_USART_Transmit (&husart1,str,length,5000);"

//Prepares the board for a Reply (reception). Blocking.
unsigned char getc_rs485_1_blocking (void )
        unsigned int delay = 0;
        unsigned int tmp = 0;
        //Do not enable if still transmitting:
        while (husart1.State == HAL_USART_STATE_BUSY_TX);
        for (delay = 0; delay < 1000; delay++);           //Short delay
        //Receive enable
        for (delay 0; delay < 5000; delay++);           //Short delay
       tmp USART1-> DR;     //Read buffer to clear
        //Debug signal:
       HAL_GPIO_WritePin(GPIOF, GPIO_PIN_0, 1);
       HAL_GPIO_WritePin(GPIOF, GPIO_PIN_0, 0);
        return 0;

ISR (fires 5 times, once per byte):

void USART1_IRQHandler( void )
        uint32_t tmp1 = 0, tmp2 = 0;
        unsigned int tmp = 0;
        //Rising edge, end of reception
       HAL_GPIO_WritePin(GPIOF, GPIO_PIN_0, 1);
       HAL_GPIO_WritePin(GPIOF, GPIO_PIN_0, 0);
       tmp1 = __HAL_USART_GET_FLAG(&husart1, USART_FLAG_RXNE);
        if (tmp1)
              tmp = USART1-> DR;
              log_rx_bytes[cnt] = tmp;
               if (cnt >= 20)
                     cnt = 0;

As you can see in the code I've tried to use the 16x oversampling and the 3 bits averaging to filter out that glitch. It didn't change anything.

I'm obviously doing something wrong here. Can you spot my mistake?