Skip to main content
Cpete.838
Associate
January 21, 2020
Question

Receive Data from UART's

  • January 21, 2020
  • 13 replies
  • 2982 views

Hi there

I have a question..

I have 6 Laser Sensors and I want to receive the data via 6 Uarts and then send all data via the 7th Uart. Every laser sends 4 Byte of data. Start byte starts with 1.

My questions are:

how can I make a array of buffers? I need a receive buffer for every laser.

I can distinguish the uarts with:

UART_HandleTypeDef* huart[6]={&huart1,&huart2,&huart3,&huart4,&huart5,&huart6};

but how can I do it with the different buffers?

Second question:

How do I finally transmit the data via the 7th uart?

Now what I have now:

/* Private variables ---------------------------------------------------------*

UART_HandleTypeDef huart1;

UART_HandleTypeDef huart2;

UART_HandleTypeDef huart3;

UART_HandleTypeDef huart4;

UART_HandleTypeDef huart5;

UART_HandleTypeDef huart6;

UART_HandleTypeDef huart7;

UART_HandleTypeDef huart8;

/* USER CODE BEGIN PV */

UART_HandleTypeDef* huart[6]={&huart1,&huart2,&huart3,&huart4,&huart5,&huart6};

#define LASER_COUNT 6

uint8_t transmitBuffer[4]; // every laser sends 4 byte of data

uint8_t receiveBuffer[4]; //

uint8_t rxSensor[LASER_COUNT][4]; // data from 6 lasers with 4 bytes each

uint8_t rxSensorIdx[LASER_COUNT]; // ID from which laser data are

bool rxSensorDone[LASER_COUNT]; // are all 4 byte received?

int idx;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_USART1_UART_Init(void);

static void MX_USART2_UART_Init(void);

static void MX_USART3_UART_Init(void);

static void MX_USART4_UART_Init(void);

static void MX_USART5_UART_Init(void);

static void MX_USART6_UART_Init(void);

static void MX_USART7_UART_Init(void);

static void MX_USART8_UART_Init(void);

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

for(int i=0;i<=5;i++){          //which laser is sending?

if(huart==&huart[i]){

idx=i;

break;

}

};

if(!rxSensorDone[idx]){         //

if(receiveBuffer[idx] == 0x80){

rxSensorIdx[idx] = 0;

}

rxSensor[idx][rxSensorIdx[idx]] = ??

rxSensorIdx[idx]++;

if(rxSensorIdx[idx] == 4){

rxSensorDone[idx]=true;

rxSensorIdx[idx] = 0;

}

}

HAL_UART_Receive_IT(&huart[idx], &receiveBuffer[idx], 1);

};

/* USER CODE END 0 */

/**

 * @brief The application entry point.

 * @retval int

 */

int main(void)

{

 /* USER CODE BEGIN 1 */

 /* USER CODE END 1 */

  

 /* MCU Configuration--------------------------------------------------------*/

 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

 HAL_Init();

 /* USER CODE BEGIN Init */

 /* USER CODE END Init */

 /* Configure the system clock */

 SystemClock_Config();

 /* USER CODE BEGIN SysInit */

 /* USER CODE END SysInit */

 /* Initialize all configured peripherals */

 MX_GPIO_Init();

 MX_USART1_UART_Init();

 MX_USART2_UART_Init();

 MX_USART3_UART_Init();

 MX_USART4_UART_Init();

 MX_USART5_UART_Init();

 MX_USART6_UART_Init();

 MX_USART7_UART_Init();

 MX_USART8_UART_Init();

 /* USER CODE BEGIN 2 */

  

*/

 // Start receiving the data via USART

 HAL_UART_Receive_IT(&huart1, receiveBuffer, 1);

 HAL_UART_Receive_IT(&huart2, receiveBuffer, 1);

 HAL_UART_Receive_IT(&huart3, receiveBuffer, 1);

 HAL_UART_Receive_IT(&huart4, receiveBuffer, 1);

 HAL_UART_Receive_IT(&huart5, receiveBuffer, 1);

 HAL_UART_Receive_IT(&huart6, receiveBuffer, 1);

 HAL_UART_Receive_IT(&huart7, receiveBuffer, 1);

 // Transmit data via USART // 

 /* USER CODE END 2 */

 /* Infinite loop */

 /* USER CODE BEGIN WHILE */

 while (1)

 {

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

 }

 /* USER CODE END 3 */

}

thanks so much for your help!

This topic has been closed for replies.

13 replies

Tesla DeLorean
Guru
January 21, 2020

Thought about using structures?

Probably want to encapsulate and sync the data out of the 7th UART

Have some method to sync or resync incoming data.

The HAL_UART_Transmit_IT() callback could presumably manage sending new data being added to its buffer from the other sources.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Cpete.838
Cpete.838Author
Associate
January 21, 2020

Thx for your answer.. but could you be a bit more specific? I am not sure how to adapt the code in your sense.

S.Ma
Principal
January 21, 2020

ok, you have 6 USART and each laser sends 4 bytes chunck

  • how often each USART receive a chunk at which baud rate?
  • what is the outgoing USART baudrate?
  • Are each 4 bytes block spaced with pause? If sent continuously, can you figure out which one is the first of 4 ? (synchronize)
S.Ma
Principal
January 21, 2020

2 more questions:

  • Are each laser sending a feeback data chunk based on a trigger pulse sent by the MCU?
  • Which MCU are you considering?

Cpete.838
Cpete.838Author
Associate
January 21, 2020

Hi!

I have these sensors: https://www.baumer.com/de/en/product-overview/distance-measurement/optical-distance-sensors-/miniaturized-laser-sensors/long-range-/oadm-13s7480-s35a/p/medias/__secure__/m_oadm13s7480s35a.pdf?mediaPK=8799800721438

So yes, I now the first Byte contains Bit 7 = 1 as marker for the start of the dataset. Byte 2,3,4 start with 0.

Standard Baud Laser: 38400

I have the https://www.st.com/en/evaluation-tools/nucleo-f091rc.html

So yes I need 6 Uarts for the 6 Lasers and then send them via the 7th Uart.

S.Ma
Principal
January 21, 2020

The code maybe a bit tricky to be rugged.

For each incoming uart, start with per byte interrupt scheme, and when a valid 4 byte packet is decoded, push it to a TX SW FIFO going to the transmitting UART (with interrupt). This to avoid interleaving incoming packets wrongly.

If you prefer to deinterleave the usarts on the PC side, you can convert an 8 bit incoming char into a double char where the first byte is the source nb

0x01 0x82 0x04 0x90 0x01 0x23 0x01 0x33 0x04 0x44 0x04 0x67 0x01 0x5A 0x04 0x6A

Laser 0x01 = 0x82 0x23 0x33 0x5A

Laser 0x04 = 0x90 0x44 0x67 0x6A

JoniS
Senior
January 21, 2020

Almost certainly will need circular buffer for each uart, or the risk of missing bytes will become really high.​

Quick look at the datasheet shows that once you enable the sensor it will output data continuously, ​so 6 sources outputting data at "random" times, no matter how efficient code one could write some data losses will happen at some point if one tries to instantly push the data out of one uart in "real time"

S.Ma
Principal
January 21, 2020

The code is KO as it is, it would require additional editing.

First, each incoming USART should have its unique buffer (say at least 16 bytes) + unique index

Second, you need for each USART the callback function when one byte is received, to store it on the buffer and detect when valid 4 byte sequence is ready.

Once the 4 byte sequence is ready, you push it to the transmit buffer cyclic buffer with the header ID upfront and you reset the incoming buffer index.

Search for SW FIFO implementations such as https://github.com/MaJerle/ringbuff

The transmit USART should too have interrupt when ready to transmit if the fifo is not empty.

Also remember that the average TX baudrate can sustain the 6 incoming average baudrate (or the TX FIFO will overflow).

Cpete.838
Cpete.838Author
Associate
January 21, 2020

Ok. Well I though I could save some lines of code if I distinguish the different sensor data with this:

UART_HandleTypeDef* huart[6]={&huart1,&huart2,&huart3,&huart4,&huart5,&huart6};

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

Do I need more of these Callbacks?

And yes I know I need a receive buffer for all UARTs. That is what I wanted to do in the last line of my the Callback:

HAL_UART_Receive_IT(&huart[idx], &receiveBuffer[idx], 1);

I wanted to use &reveiceBuffer[idx].

Same as &huart[idx], which I achieved with this: UART_HandleTypeDef* huart[6]={&huart1,&huart2,&huart3,&huart4,&huart5,&huart6};.

I hope you understand what I mean - its maybe a bit confusing. :)

Why do I need 16 bytes buffer when data is only 4 bytes? Maybe 4 bytes for data and 1 byte for index?

Cpete.838
Cpete.838Author
Associate
January 22, 2020

sorry posted it twice.

Cpete.838
Cpete.838Author
Associate
January 22, 2020

OK I wrote some more code.

The idea is that in the while-Loop I check if all 4 Bytes are received. Then I copy the receiveBuffer and transmit the copied version. So that nothing gets lost or overwritten?

Is this possible so?

And:

What exactly do I Need to write in the void TxCpltCallback(UART_HandleTypeDef *huart)?

And where/how can I put the header from the sensor?

/* Private variables ---------------------------------------------------------*/

UART_HandleTypeDef huart1;

UART_HandleTypeDef huart2;

UART_HandleTypeDef huart3;

UART_HandleTypeDef huart4;

UART_HandleTypeDef huart5;

UART_HandleTypeDef huart6;

UART_HandleTypeDef huart7;

UART_HandleTypeDef huart8;

/* USER CODE BEGIN PV */

UART_HandleTypeDef* huart[6]={&huart1,&huart2,&huart3,&huart4,&huart5,&huart6};

#define LASER_COUNT 6

//uint8_t transmitBuffer[4];

uint8_t receiveBuffer1[4];

uint8_t receiveBuffer2[4];

uint8_t receiveBuffer3[4];

uint8_t receiveBuffer4[4];

uint8_t receiveBuffer5[4];

uint8_t receiveBuffer6[4];

uint8_t receiveBufferCopy1[4];

uint8_t receiveBufferCopy2[4];

uint8_t receiveBufferCopy3[4];

uint8_t receiveBufferCopy4[4];

uint8_t receiveBufferCopy5[4];

uint8_t receiveBufferCopy6[4];

uint8_t *receiveBuffer[6]= {&receiveBuffer1[4], &receiveBuffer2[4], &receiveBuffer3[4], &receiveBuffer4[4], &receiveBuffer5[4], &receiveBuffer6[4]};

uint8_t *receiveBufferCopy[6]= {&receiveBufferCopy1[4], &receiveBufferCopy2[4], &receiveBufferCopy3[4], &receiveBufferCopy4[4], &receiveBufferCopy5[4], &receiveBufferCopy6[4]};

uint8_t rxSensor[LASER_COUNT][4];

uint8_t rxSensorIdx[LASER_COUNT];

bool rxSensorDone[LASER_COUNT];

int idx;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_USART1_UART_Init(void);

static void MX_USART2_UART_Init(void);

static void MX_USART3_UART_Init(void);

static void MX_USART4_UART_Init(void);

static void MX_USART5_UART_Init(void);

static void MX_USART6_UART_Init(void);

static void MX_USART7_UART_Init(void);

static void MX_USART8_UART_Init(void);

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

void RxCpltCallback(UART_HandleTypeDef *huart, uint8_t *receiveBuffer)

{

 for(int i=0;i<=5;i++){

  if(huart==&huart[i]){

   idx=i;

   break;

  }

 };

 if(!rxSensorDone[idx]){

  if(receiveBuffer[idx] == 0x80){

   rxSensorIdx[idx] = 0;

   }

 rxSensor[idx][rxSensorIdx[idx]] = receiveBuffer[idx];

 rxSensorIdx[idx]++;

 if(rxSensorIdx[idx] == 4){

  rxSensorDone[idx]=true;

  rxSensorIdx[idx] = 0;

 }

 }

 HAL_UART_Receive_IT(&huart[idx], &receiveBuffer[idx], 1);

};

void TxCpltCallback(UART_HandleTypeDef *huart)

{

}

int main(void)

{

 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

 HAL_Init();

 /* Configure the system clock */

 SystemClock_Config();

 /* Initialize all configured peripherals */

 MX_GPIO_Init();

 MX_USART1_UART_Init();

 MX_USART2_UART_Init();

 MX_USART3_UART_Init();

 MX_USART4_UART_Init();

 MX_USART5_UART_Init();

 MX_USART6_UART_Init();

 MX_USART7_UART_Init();

 MX_USART8_UART_Init();

 // Start receiving the data via USART

 HAL_UART_Receive_IT(&huart[idx], &receiveBuffer[idx], 1);

 while (1)

 {

  for(int k=0;k<5;k++){

   if(rxSensorDone[k]==true){

    receiveBuffer[k]=receiveBufferCopy[k];

    HAL_UART_Transmit_IT(&huart7, &receiveBufferCopy[k], 1);

    rxSensorDone[k]=false;

   }

  };

 }

}

Piranha
Principal III
January 25, 2020

> What exactly do I Need to write in the void TxCpltCallback(UART_HandleTypeDef *huart)?

So you have done absolutely nothing, except for a few clicks in CubeMX and generating that useless bloatware, and know you are asking for a "little help" - others doing essentially all of your project instead of you. No? Then here is a precise instruction:

  1. Use "Code Snippet" button.
  2. Learn using arrays, multidimensional arrays, structures, etc. and C language in general.
  3. Learn MCU register programming and driver development.
  4. Make actually working UART driver, not a non-working crap like HAL drivers are.
  5. Make your UART driver to be usable with multiple instances.
  6. Design the communication synchronization principles for your multiple laser usage scenario.
  7. Profit!