How to get UART characters continuously?

53 views
asked May 22 in Embedded Wizard Studio by Gazi

Hello,

I want to be able to get characters from UART continuously.

I have started with the DeviceIntegration example and have followed the instructions given in the thread https://ask.embedded-wizard.de/433/how-to-send-string-from-usart-and-show-it-textviewer-in-the-gui?show=433#q433.
I have been trying to understand how the UART communication is implemented in Embedded Wizard. I have carefully checked the ew_bsp_console.c file, where the function EwBspConsoleGetCharacter() is implemented. Following the instructions of the aforementioned thread, I was able to get characters from UART, however I could read only single characters. If I send "ABC", I read only the "A". So, the question I have is how can I make sure to read all the UART characters, without losing any of them?

Thanks a ot for the support.

Bests,

Gazi

1 Answer

0 votes
answered May 23 by Tim Zierer

Hi Gazi,

I assume you want to use EwBspConsoleGetCharacter() outside of the Embedded Wizard scope. 

In that case you need to buffer the characters first and after a dedicated number of received characters, you can process the buffer in one piece. This is a common way to process characters received via an UART interface and is called FIFO buffering. The simplest solution is to define a buffer in form of a character array (e.g. size of 256) and count the received characters. Each character should then be stored in one index of the array. Typically the press on the enter key gives the command to process the buffer, respectively the content in it.

Here I've found a good explanation of this (external content).

Best regards,

Tim

commented May 23 by Gazi

Hi Tim,

Thanks a lot for the reply.

I am not sure if the scope of use is outside Embedded Wizard, because I do not really know the limits of the scope. However, here I am attaching the code which I am using:

int DeviceDriver_ProcessData( void ){

int needUpdate = 0;

#ifdef _ApplicationDeviceClass_
	if ( IsHardButtonDown )
		ButtonCounter++;
	else
		ButtonCounter = 0;

	if ( DeviceObject == 0 )
		return 0;

    #ifdef _ApplicationDeviceClass__UpdateHardButtonCounter_
	    ApplicationDeviceClass__UpdateHardButtonCounter( DeviceObject, (XInt32)ButtonCounter );
    #endif

	if ( IsHardButtonPressed ){
        #ifdef _ApplicationDeviceClass__TriggerHardButtonEvent_
		    ApplicationDeviceClass__TriggerHardButtonEvent( DeviceObject );
        #endif
		IsHardButtonPressed = 0;
		needUpdate = 1;
	}

	char ch = EwBspConsoleGetCharacter();
	if ( ( ( ch >= 'A' ) && ( ch <= 'Z' ) ) || ( ( ch >= 'a' ) && ( ch <= 'z' ) ) || ( ( ch >= '0' ) && ( ch <= '9' ) ) || ( ch == ' ' ) )
	{
		EwPrint("%c\n",ch);
		ApplicationDeviceClass__UpdateTerminalString( DeviceObject, (XChar)ch );
		needUpdate = 1;
	}
#endif

return needUpdate;
}

This is the function DeviceDrivers_ProcessData which is regularly called by the EwProcess() function inside the ewmain.c. As you may notice, I have only added the last lines which start with "char ch = EwBspConsoleGetCharacter()". Thes rest of the code is the one generated by Embedded Wizard using the example DeviceIntegration. I believe it is still within the scope of the Embedded Wizard,.

Anyway, I have 2 questions related to the code above:

1. I managed to get single characters in the beginning, but now it is suddenly not working anymore. It does not react to input from the HTerm which I am using to send data via UART. Do you have any idea why it does not read the characters?

2. The second question is related to the user button in the STM32F429 Discovery board. It is the blue button on the board and the one which is checked whether it is pressed or not by the function above. The input from the button works fine, however there is a strange behavior which I do not understand. Any time I press the button, the function EwBspConsoleGetCharacter() returns the space (' ') character. Is it supposed to do so? I looked at what the EwBspConsoleGetCharacter()does and it indeed uses the HAL_UART_Receive() function, which reads the received characters from the USART1 which is initialized in the ew_bsp_console.c file as follows: 

       #define USARTx_TX_PIN                            GPIO_PIN_9
       #define USARTx_TX_GPIO_PORT             GPIOA
       #define USARTx_RX_PIN                           GPIO_PIN_10 

The user button on the other side is connected to pin PA0, which is none of the USART1 pins. Why does the EwBspConsoleGetCharacter() return a valid character then when the button is pressed?

I am also attaching the project, so that you can check it on your own as well.

https://ask.embedded-wizard.de/?qa=blob&qa_blobid=7361981857356375701

Thank you very much for the support. I apologize for the long explanation, but I hope it tells clearly what my problem is.

Bests,

Gazi

commented May 26 by Tim Zierer

Hi Gazi,

yes, that what you want to do, is within the Embedded Wizard scope. First it has seemed that you want to use the EwBspConsoleGetCharacter() in any other part of your own custom code.

To 1.

I’m am using TeraTerm which is really comfortable and almost never crashes a stable connection. Unfortunately this topic is often as you have explained. Some console application aren't able to establish and hold an useable UART connection to your board and nobody really knows why… Anyway could you please try to use another console application (e.g. TeraTerm or Putty) to ensure that this does not cause the problem.

To 2.

The solution for this behaviour is quite simple. Could you please set an initialisation value for ‘uint8_t ret’ in EwBspConsoleGetCharacter(), for example ‘0’. Then the button press won’t trigger the USART task anymore.

unsigned char EwBspConsoleGetCharacter( void )

{

  uint8_t ret = 0;

  HAL_UART_Receive( &UART_Handle, &ret, 1, 10 );

  return ret;

}

It seems that the HAL_UART_Receive() function always gives back an ‘ ‘ in case the ret value is not initialized. Please be aware that this in general is an ST solution and we usually use the HAL functions as they are.

Best regards,

Tim

commented May 26 by Gazi

Hi Tim,

Thanks for the reply. I did the changes you suggested and it works fine now, as far as the button is concerned. However, I have a question related to receiving several characters at once.

1. Even though I save the characters in a buffer (as you suggested) and then process the buffer all at once, I am not able to receive all the characters I send. Sometimes I get one character and sometimes 2. For example, if I send "12345" I get sometemis just "1" and sometimes "12". I haven't been able to find the patternd there. I am attaching the project and the DeviceDrivers.c file so that you can give a try yourself if possible.

Project: https://ask.embedded-wizard.de/?qa=blob&qa_blobid=16131058407847032910

DeviceDrivers.c: https://ask.embedded-wizard.de/?qa=blob&qa_blobid=17255804197998578341

I have only added 2 blocks to the DeviceDriver.c:

Lines 79 - 81:

char UARTbuffer[100];
int transmitionStarted = 0;
int position = 0;

Lines 316 - 334:

char ch = EwBspConsoleGetCharacter();
if ( ( ( ch >= 'A' ) && ( ch <= 'Z' ) ) || ( ( ch >= 'a' ) && ( ch <= 'z' ) ) || ( ( ch >= '0' ) && ( ch <= '9' ) ) || ( ch == ' ' ) )
{
	if(transmitionStarted == 0){
	    transmitionStarted = 1;
    }
    UARTbuffer[position] = ch;
	position++;
}
else{
	if (transmitionStarted == 1){
		DeviceObject->TerminalString = EwNewStringAnsi(UARTbuffer);
		ApplicationDeviceClass__UpdateTerminalString( DeviceObject );
		position = 0;
		transmitionStarted = 0;
		needUpdate = 1;
		memset(UARTbuffer,'\0',sizeof(UARTbuffer));
	}
};

I suspect that there is something related to the baudrate of the UART and the rate at which embedded Wizard calls the function DeviceDrivers_ProcessData(). From what I have seen, it looks like Embedded Wizard is all the time polling for any received character. If this is the case then it might miss the characters from UART since it is handling other jobs, such as refreshing the screen for instance. This is just my guess. Can you please help me in getting all the UART characters?

2. If what I said about polling is true, then one way might be to implement UART using interrupts. However, since I do not know the very details how all the functions are connected to each other, I did not succeed on implementing this. Is it possible to do it by interrupts or does it interfere with important tasks that embedded wizard handles?

3. Another way is to use the DMA. This is a even trickier because as far as I understand, it is used for the screen refreshing. If I am wrong and you think that implementing the UART reading by DMA is the solution, can you please help me a bit with it?

Thanks a lot for the support.

I am looking forward to your response.

Bests,

Gazi

commented May 27 by Tim Zierer

Hi Gazi,

To 1.:

As we already have figured out, that what you want to do is definitely within the Embedded Wizard scope. With scope I mean, where you want to realize the processing of the received UART characters. As first it has looked that you want to use ‘EwBspConsoleGetCharacter()’ for another application instead of in an Embedded Wizard GUI.

With following code lines you’ve already realized the UART buffering with Chora code and there is no need to buffer it again. I would suggest to code all additional processings within your Embedded Wizard project.

 

The implementation of 'UpdateTerminalString( char aChar )' is (just for demo purposes) quite simple:

/* keep the last 9 characters of the string and add the new one */
pure TerminalString = TerminalString.right( 9 ) + aChar;

/* notify all associated property observers... */ 
notifyobservers ^TerminalString;

 

By the way, on my disco board I’m running exactly your recently attached DeviceDriver example (just with the fix that I’ve mention in the post before) and I do receive all characters after each other without missing one. So, please try that too and you probably will get what you need.

 

To 2.:

You definitely don’t need to implement an additional interrupt for the UART routine. The method ‘DeviceDriver_ProcessData()’ is called each time when the main loop is processed. This code part is independent to the screen refresh. This means this part is called several thousand (or hundred thousand) times per second and normally all characters will be received reliably.

 

 

To 3.:

That’s way to complicated to receiving UART characters… let’s try the easy way first :P

 

Best regards,

Tim

commented May 27 by Gazi
Hi Tim,

1. So you are saying that you are running the exact same project and DeviceDrivers.c file that I attached in the last comment and you get all the characters without missing anyone?

In the last project I attached I had changed the UpdateTerminalString() function, compared to the code you have attached in the previous comment.

And of course, with the change to initialize the "uint8_t ret = 0", in the 'EwBspConsoleGetCharacter()' function.

If you are getting all the characters, it would be very strange for me, because I have already measured the UART TX signal of the HTerm that I am using and the HTerm indeed sends all the signals. So there must be something on the side of the STM that is not working well. However, just to clearify, when I send many characters I want to send them all one after the other, without pausing inbetween. So I send an array of characters in one command, not first send one, then another one, then another one, and so on. Just wanted to make sure that we are testing the same thing.

Thanks a lot.

Bests,

Gazi
commented 5 days ago by Tim Zierer

Hi Gazi,

exactly, I've started with a new Embedded Wizard Build Environment for STM32F429-Discovery, did the changes related to this thread and the already mentioned fix from above. With your attached Embedded Wizard UI project for the GUI code it works totally fine.

I’ve uploaded the changed files/folders here, could you please use these files to compare the differences?

Best regards,

Tim

Embedded Wizard Website | Privacy Policy | Imprint

...