2020-01-21 09:00 AM
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!
2020-01-21 09:10 AM
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.
2020-01-21 09:36 AM
Thx for your answer.. but could you be a bit more specific? I am not sure how to adapt the code in your sense.
2020-01-21 11:44 AM
ok, you have 6 USART and each laser sends 4 bytes chunck
2020-01-21 11:46 AM
2 more questions:
2020-01-21 12:33 PM
Hi!
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.
2020-01-21 01:41 PM
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
2020-01-21 01:52 PM
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"
2020-01-21 01:53 PM
Hi thank you. Not sure if I understood correctly..
Is my code OK as it is?
I check if all 4 bytes from one laser are received.
Now I need to transmit it. How can I push it through a TX SW FIFO?
I am so sorry. I am very new at this and really would like to understand it correctly. But I havent done something like this before.
Also I need to send the ID so I can see from with laser the data are sent.
I am also not sure how to define the receiveBuffer (see „?“ in my code)
Thanks for your help! Appreciate it very much!
2020-01-21 02:27 PM
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).