cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 USART1 Reception: glitch/noise issue

jfduval
Associate
Posted on July 31, 2014 at 00:05

Hello!

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.

Code:

USART1 MSP:

void HAL_USART_MspInit( USART_HandleTypeDef * husart)

{

if(husart-> Instance==USART1)

{

/* Peripheral clock enable */

__USART1_CLK_ENABLE();

__GPIOA_CLK_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

// Ref:http://eliaselectronics.com/stm32f4-tutorials/stm32f4-usart-tutorial/and Cube functions

void USART1_Init( void )

{

husart1. Instance = USART1;

//MSP Init (enables clock, GPIOs)

HAL_USART_MspInit(&husart1);

//Interrupts:

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;

HAL_USART_Init(&husart1);

//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

rs485_set_mode(RS485_RX);

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;

cnt++;

if (cnt >= 20)

cnt = 0;

}

HAL_USART_IRQHandler(&husart1);

}

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?

Thanks!

1 REPLY 1
ivani
Associate II
Posted on July 31, 2014 at 11:13

The glitch could be a result of cross-coupling between the receiver output and enable lines. For sure it shouldn't there (at least I don't see it on my board with SN65HVD1781D chip on it).

Try to use an external pull-up, or even a small capacitor on the Rx pin.

Or, as a software workaround - disable the receiver before changing the driver in Tx mode and enable it after it is changed to Rx. Definitely, the USART can't detect a start bit while the receiver is disabled.