cancel
Showing results for 
Search instead for 
Did you mean: 

UART communication problem (incorrect received data and synch.)

danesh
Associate II
Posted on August 04, 2015 at 23:12

Hello all,

 

I am using a STM32F103 MCU and a FT232RQ USB controller which is connected to UART4 in my configuration. I use polling to read data from UART4 (later I will use interrupt as soon as I am sure that everything work fine). I read data from UART4 in the main ''while'' loop as below:

 

int main() {

  initF232RQ();

 

  while (1) {

    while (USART_GetFlagStatus(UART4, USART_FLAG_RXNE) == RESET);

    uint8_t ch = (uint8_t)USART_ReceiveData(UART4);

  }

}

 

and ''UART4'' is initialized in the function ''initF232RQ'' as below:

 

void initF232RQ() {

  USART_InitTypeDef USART_InitStruct;

 

  USART_InitStruct.USART_BaudRate            = 115200;

  USART_InitStruct.USART_WordLength          = USART_WordLength_8b;

  USART_InitStruct.USART_StopBits            = USART_StopBits_1;

  USART_InitStruct.USART_Parity              = USART_Parity_No;

  USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

  USART_InitStruct.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;

 

  USART_Init(UART4, &USART_InitStruct);

  USART_Cmd(UART4, ENABLE);

}

 

The code above seems to work fine when I use echo which means, send the received character in PuTTY, but the only problem in echo test, is that all upper case characters are sent as lower case characters. The other problem is that when I check the received value of the sent char, the value is totally different from the ASCII code of the sent character. For instance, when I send ''a'', the value ''3'' will be sent, or if I send ''b'' the value ''4'' will be sent to the MCU. and if I send ''w'', value ''223'' will be sent to the MCU.

 

I also tried to send a block of data from a Windows host machine, using the code:

 

::WriteFile(GetFileHandle(), pData, pWriteByteCount, &lNumberOfBytesWritten, lPtrAsyncStruct)

 

 

where:

 

''pData'' is an array of data, ''pWriteByteCount'' is the size of array in bytes, ''lNumberOfBytesWritten'' is the number of bytes written to the serial port, and ''lPtrAsynchStruct'' is a data structure used in the write function. In this case, when I send a block of data, using the code above at the MCU side, only one byte is always received and the rest of data seems to be lost. I tried to follow the examples for USART, but it seems that I have missed something. Can anybody help?

 

Regards,

 

Dan.

#know-your-tools
10 REPLIES 10
Posted on August 05, 2015 at 01:55

I think you need to look at the signal integrity with a scope, especially at the bit timing.

You could try configuring the PC side with 2 stop bits, as this will expand the inter-symbol delay, and perhaps permit better synchronization.

The fact it echos back, and you receive odd values if you look at them suggests whatever problem you have could be symmetrical in nature. Your USB adapter looks to be CMOS vs RS232, so I can't explain the data pattern issue with that.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
danesh
Associate II
Posted on August 05, 2015 at 16:18

Thanks for guidlines. I actually fixed the problem with overwritten data, by buffering all received data which were lost before during my code tracing at the MCU side. The problem that I had and still have is that the received data is totally different from the sent data. I have written a small program in C# at the host side to write some data on the serial port which is listed here:

namespace ConsoleApplication2

{

    class Program

    {

        static void Main(string[] args)

        {

            SerialPort _serialPort = new SerialPort();

            char[] ch = { 'a', 'a', 'a', 'a', 'a', 'a', 'a' };

            string str = new string(ch);

            _serialPort.PortName = ''COM32'';

            _serialPort.BaudRate = 9600;

            _serialPort.Parity = Parity.None;

            _serialPort.DataBits = 8;

            _serialPort.StopBits = StopBits.One;

            _serialPort.Handshake = Handshake.None;

            _serialPort.ReadTimeout = 500;

            _serialPort.WriteTimeout = 500;

            _serialPort.Open();

            _serialPort.Write(str);

        }

    }

}

Using this, I know exactly the properties of the data sent to the MCU. Then I have exactly same configuration at the MCU side, but the data is still incorrect. For instance, when I send 'a' from the host (PC) to the MCU, I get code ''3'' and when I send 'b' from the host (PC) I get code ''4'' at the MCU side, while I expect the ASCII codes to be sent to the MCU. Is it how it should be, or data should be processed at MCU side somehow?

Thanks in advance,

Dan.

Posted on August 05, 2015 at 17:34

This is where one uses an oscilloscope to understand what's happening. If you send an 'a' from the PC you should get an 'a' (0x61) at the STM32

Send 'U' characters and confirm the bit timing on the data sent by your USB adapter, and by the STM32. I'm assuming a direct wiring of the TX/RX pins between the two. If you have something else going on provide a schematic or diagram.

One the STM32 side you need to make sure the define for HSE_VALUE actually reflects the speed of the external crystal being used.

If you have a different USB-to-CMOS Serial adapter, one using a crystal, give that a try also.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
jpeacock
Associate II
Posted on August 05, 2015 at 19:33

This looks like a baud rate mismatch.  I see from your code the ST side runs at 115K while the PC side (and I assume this sets the FT rate also) is set at 9600.

  Jack Peacock

Posted on August 05, 2015 at 19:47

I'm lead to believe the two different posts were testing slightly different configurations, the first using Putty with the ''same'' settings.

The latter ''Using this, I know exactly the properties of the data sent to the MCU. Then I have exactly same configuration at the MCU side, but the data is still incorrect.''

There's clearly some disconnect between what the OP wants to happen, and what's transacting on the wire, all other things being equal, the scope decides.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
danesh
Associate II
Posted on August 07, 2015 at 16:52

I am not sure whether this is a timing problem or not. However, when I play around with the baudare values, both at PC and MCU sides, I simply get different results. I have attached the configuration I use which consists of a FT232R USB UART IC and STM32F103 as MCU, where FT232R is controlled using UART4 in MCU.  Should both parties i.e. PC and MCU have exactly same baudrate? I have tested with same baudrate with no success. At the same time, in this configuration, I think the baudrate is important *only* for communication between MCU-FT232R and also FT232R-PC, so it shouldn't be important that the baudrate be same, since FT232 is in between. Anyway, any tip/advice is highly appreciated. By the way, in my tests, number of stop bits, word length, and parity is exactly same in MCU and PC side.

Regards,

Dan.0690X000006033bQAA.jpg

Posted on August 07, 2015 at 17:05

Ok, if you're feeding 12 MHz into the STM32 have you changed HSE_VALUE to reflect that, and the configuration of the PLL?

The default assumption are 8 MHz, ie #define HSE_VALUE 8000000

The math to determine the baud rate as clock ticks is predicated on this.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
danesh
Associate II
Posted on August 07, 2015 at 17:11

Thanks a lot. Yes, I am feeding 12 MHz. But, would you please let me know how HSE should be change and what attribute of PLL should be changed to reflect 12 MHz input clock? I see that HSE_VALUE is readonly.

Thanks again,

Dan.

Posted on August 07, 2015 at 17:34

You'd typically pull library files that need to be board specific into your own project directory, remove the read-only attribute and modify them when necessary.

Feeding -DHSE_VALUE=12000000 on the compiler command line is one method, modifying stm32f1xx_conf.h to add #define HSE_VALUE 12000000 before the peripheral libraries are pulled in. For the PLL you're going to have to play games with the multiplier and dividers to get 72 MHz or whatever you want. This would be in system_stm32f1xx.c For 8 MHz you have (8 / 1) * 9 = 72, for 12 MHz you could have (12 / 1) * 6 = 72 On the F4 DISCO this happens, not sure I like the undefine methodology, but whatever

...
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_CONF_H
#define __STM32F4xx_CONF_H
#if defined (HSE_VALUE)
/* Redefine the HSE value; it's equal to 8 MHz on the STM32F401-DISCOVERY Kit */
#undef HSE_VALUE
#define HSE_VALUE ((uint32_t)8000000)
#endif /* HSE_VALUE */
/* Includes ------------------------------------------------------------------*/
/* Uncomment the line below to enable peripheral header file inclusion */
#include ''stm32f4xx_adc.h''
#include ''stm32f4xx_crc.h''
...
/* PLL configuration: PLLCLK = HSE * 6 = 72 MHz, where HSE = 12 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6);

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..