5 years, 3 months ago.

USART1 not working as RS 232 receiver on DISCO L476

I have a sensor with 2 wire (TX, GND) RS 232 interface with following configuration: Baud rate: 9600, Data: 8bit, Stop bit: 1, Parity bit: None, HW Flow control: None Data burst is of 8 bytes in following format: "=DDD.DDN" where D is for Digit and N for NULL

I verified that it is working fine using PC serial port as well as CH340 USB to serial converter with PC.

First I tried to use CH340 converter and DISCO L476 USB OTG. L476 successfully identified and enumerated CH340 however received data is always garbage. Since I didn't have ample information of CH340 driver so after a few attempts, I left this route.

Now I have unmounted the 24 segment LCD and using USART1 against PA_9 and PA_10. Following is my basic application:

Basic RS232 App

int main(void)
{
#define MAX_ARR_SIZE	0x08
	//Declare buffer to hold RX data
	char c[MAX_ARR_SIZE];

	//Open debug port with PC
	Serial pc(USBTX, USBRX, 9600);
	pc.printf("\r\nSerial init complete\r\n");

	// Show current settings
	pc.printf("CPU SystemCoreClock is %d Hz\r\n", SystemCoreClock);
	pc.printf("PCLK1 is %d Hz\r\n", HAL_RCC_GetPCLK1Freq());
	pc.printf("PCLK2 is %d Hz\r\n", HAL_RCC_GetPCLK2Freq());

	pc.printf("RCC_CFGR is 0x%08X\r\n", RCC->CFGR);

	//Open RS232 communication link
	RawSerial uHandle(PA_9, PA_10, 9600);    //Tried Serial, UARTSerial variant too
	pc.printf("UART init complete\r\n");

	//Read infinit time the RS232 data and throw it on PC for debug
	while(1)
	{
		if (uHandle.readable())
		{
			//uHandle.read((void *)c, MAX_ARR_SIZE);

			pc.printf("Received data is: ");
			for (int i = 0; i < MAX_ARR_SIZE; i++)
			{
				c[i] = uHandle.getc();
				pc.printf("0X%0x ", (uint8_t(c[i])));
			}
			pc.printf("\r\n");
		}
	}
}

Received data is still garbage but interestingly it has a fix pattern for first byte i.e. it will always receive 0x61 when it was actually 0x3D. But for other bytes it is not the case. To ensure it is not clocking problem, I have implemented HAL_UART_MspInit and HAL_UART_MspDeInit as follows:

HAL_UART_Msp implementation

/* Definition for USARTx clock resources */
#define USARTx_CLK_ENABLE()              __HAL_RCC_USART1_CLK_ENABLE()
#define USARTx_RX_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE()
#define USARTx_TX_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE()

#define USARTx_FORCE_RESET()             __HAL_RCC_USART1_FORCE_RESET()
#define USARTx_RELEASE_RESET()           __HAL_RCC_USART1_RELEASE_RESET()

/* Definition for USARTx Pins */
#define USARTx_TX_PIN                    GPIO_PIN_9
#define USARTx_TX_GPIO_PORT              GPIOA
#define USARTx_TX_AF                     GPIO_AF7_USART1
#define USARTx_RX_PIN                    GPIO_PIN_10
#define USARTx_RX_GPIO_PORT              GPIOA
#define USARTx_RX_AF                     GPIO_AF7_USART1

/**
  * @brief UART MSP Initialization 
  *        This function configures the hardware resources used in this example: 
  *           - Peripheral's clock enable
  *           - Peripheral's GPIO Configuration  
  * @param huart: UART handle pointer
  * @retval None
  */
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
  GPIO_InitTypeDef  GPIO_InitStruct;
  /*##-1- Enable peripherals and GPIO Clocks #################################*/
  /* Enable GPIO TX/RX clock */
  USARTx_TX_GPIO_CLK_ENABLE();
  USARTx_RX_GPIO_CLK_ENABLE();


  /* Enable USARTx clock */
  USARTx_CLK_ENABLE();
  
  /*##-2- Configure peripheral GPIO ##########################################*/
  /* UART TX GPIO pin configuration  */
  GPIO_InitStruct.Pin       = USARTx_TX_PIN;
  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull      = GPIO_PULLUP;
  GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Alternate = USARTx_TX_AF;

  HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);

  /* UART RX GPIO pin configuration  */
  GPIO_InitStruct.Pin = USARTx_RX_PIN;
  GPIO_InitStruct.Alternate = USARTx_RX_AF;

  HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);
}

/**
  * @brief UART MSP De-Initialization
  *        This function frees the hardware resources used in this example:
  *          - Disable the Peripheral's clock
  *          - Revert GPIO configuration to their default state
  * @param huart: UART handle pointer
  * @retval None
  */
void HAL_UART_MspDeInit(UART_HandleTypeDef *huart)
{
  /*##-1- Reset peripherals ##################################################*/
  USARTx_FORCE_RESET();
  USARTx_RELEASE_RESET();

  /*##-2- Disable peripherals and GPIO Clocks #################################*/
  /* De-Initialize USART1 Tx */
  HAL_GPIO_DeInit(USARTx_TX_GPIO_PORT, USARTx_TX_PIN);
  /* De-Initialize USART1 Rx */
  HAL_GPIO_DeInit(USARTx_RX_GPIO_PORT, USARTx_RX_PIN);
}

But the issue still remains the same. Kindly analyze the problem and let me know the fix.

Please note my mbed-os version is 5.

-Thanks

Hi Ahsan, Could you use command "mbed releases" to get tag information of mbed-os? Thanks.

posted by Desmond Chen 02 Jan 2019

Hi Desmond Chen, following is the info: mbed-os (#610e35ddc6d5, tags: mbed-os-5.10.0, mbed-os-5.10.0-rc3). Thanks

posted by Ahsan Wahla 02 Jan 2019

2 Answers

5 years, 3 months ago.

Do you have an RS232 level shifter on the receive line? RS232 is -5V to -15V for a 1 and +5V to +15V for a 0 The UART will expect +3.3V for a 1 and 0V for a 0

0x61 and 0x3D are the inverse of each other with a one bit shift. The bit shift could be caused by the start symbol not being correctly recognized due to the data being inverted.

Accepted Answer

I fear it's not the case. However I will double check and confirm in around 12 hours time. Thanks for the valuable suggestion

posted by Ahsan Wahla 03 Jan 2019

If you need to add something then you don't need a full receiver IC. A transistor, diode and couple of resistors will do the job or you can get simple level shiftier boards very cheap from places like ebay.

Normally I'd say always use a real RS232 IC and avoid the cheap simple boards like the plague, they don't generate the correct voltages and fall over at high data rates. The cost saving isn't worth the reliability risk. But you're receiving only so voltage output levels aren't an issue and you only need low speed. In this case just about anything that will invert the signal and give basic voltage limiting protection will work fine for you.

posted by Andy A 03 Jan 2019

Thanks for detailed information.

I checked using Oscilloscope and it seems that my sensor throwing the data as +5V for a 1 and 0V for a 0 or no data. However apparently STM32 api set RX pin as PULL up and I am not sure if it is any cause of concern here. I will look into it further and will share if I found anything worth sharing. Thanks

posted by Ahsan Wahla 03 Jan 2019

Logic level uarts should idle at a positive voltage, either +5 or +3.3.

If you are seeing 5V and 0V but idle is 0 then you need to invert the signal. Sometimes people use a cheap hack, rather than adding a real RS232 driver they output 0 when it should be -5. It's not complient with the RS232 specification but works most of the time for low speeds and short wires.

posted by Andy A 03 Jan 2019

Thanks Andy A. for your useful help. I am working in the proposed direction and will update once I have a working solution. Thanks

posted by Ahsan Wahla 05 Jan 2019

Issue is resolved after inverting the signal using 74LS04N IC. Thanks Andy A. and all others for your valuable suggestions.

posted by Ahsan Wahla 05 Jan 2019
5 years, 3 months ago.

Hi Ahsan,

There was an issue about STM32 UART1 when setting baudrate as 9600 https://github.com/ARMmbed/mbed-os/issues/5389.

Can you try using different baudrate like 115200 for experiment?

Thanks, Desmond

Please note, the sensor has fixed configuration so no change is possible. By the way, on the same port, Stdio is working perfectly at same buadrate so shouldn't this buadrate be fine? Please advice. Thanks

posted by Ahsan Wahla 03 Jan 2019