Write in serial port

Hi. I want to know is there any way to mapping a struct in arduino to c. The C program is the receiver.

Arduino:

 typedef struct JoystickEstadoAtual{
  int movimento;
  int btn1;
  int btn2;
  int btn3;
  }JoystickEstadoAtual;


  JoystickEstadoAtual joystickEstadoAtual;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  joystickEstadoAtual.movimento = (byte*)1;
  joystickEstadoAtual.btn1 = (byte*)2;
  joystickEstadoAtual.btn2 = (byte*)3;
  joystickEstadoAtual.btn3 = (byte*)0;

}

void loop() {
  // put your main code here, to run repeatedly:
Serial.write((const uint8_t *)&joystickEstadoAtual, sizeof(joystickEstadoAtual));
}

C program:

#include <Windows.h>
#include <stdio.h>

typedef struct JoystickEstadoAtual {
	byte movimento;
	byte btn1;
	byte btn2;
	byte btn3;
}JoystickEstadoAtual;

JoystickEstadoAtual joystickEstadoAtual;

void openPort(HANDLE* hComm) {

	char  ComPortName[] = "\\\\.\\COM3";

	*hComm = CreateFile(ComPortName,                  // Name of the Port to be Opened
		GENERIC_READ | GENERIC_WRITE, // Read/Write Access
		0,                            // No Sharing, ports cant be shared
		NULL,                         // No Security
		OPEN_EXISTING,                // Open existing port only
		0,                            // Non Overlapped I/O
		NULL);                        // Null for Comm Devices

	if (*hComm == INVALID_HANDLE_VALUE) {
		printf("\n    Error! - Port %s can't be opened\n", ComPortName);
		system("exit");
	}
	else {
		printf("\n    Port %s Opened\n ", ComPortName);
	}
}


BOOL settings(HANDLE hComm) {

	BOOL Status = TRUE;

	/*------------------------------- Setting the Parameters for the SerialPort ------------------------------*/

	DCB dcbSerialParams = { 0 };                         // Initializing DCB structure
	dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

	Status = GetCommState(hComm, &dcbSerialParams);      //retreives  the current settings

	if (Status == FALSE) {
		printf("\n    Error! in GetCommState()");
		return Status;
	}

	dcbSerialParams.BaudRate = CBR_9600;      // Setting BaudRate = 9600
	dcbSerialParams.ByteSize = 8;             // Setting ByteSize = 8
	dcbSerialParams.StopBits = ONESTOPBIT;    // Setting StopBits = 1
	dcbSerialParams.Parity = NOPARITY;        // Setting Parity = None 

	Status = SetCommState(hComm, &dcbSerialParams);  //Configuring the port according to settings in DCB 

	if (Status == FALSE)
	{
		printf("\n    Error! in Setting DCB Structure");
		return Status;
	}
	else //If Successfull display the contents of the DCB Structure
	{
		printf("\n\n    Setting DCB Structure Successfull\n");
		printf("\n       Baudrate = %d", dcbSerialParams.BaudRate);
		printf("\n       ByteSize = %d", dcbSerialParams.ByteSize);
		printf("\n       StopBits = %d", dcbSerialParams.StopBits);
		printf("\n       Parity   = %d", dcbSerialParams.Parity);
	}

	/*------------------------------------ Setting Timeouts --------------------------------------------------*/

	COMMTIMEOUTS timeouts = { 0 };
	timeouts.ReadIntervalTimeout = 50;
	timeouts.ReadTotalTimeoutConstant = 50;
	timeouts.ReadTotalTimeoutMultiplier = 10;
	timeouts.WriteTotalTimeoutConstant = 50;
	timeouts.WriteTotalTimeoutMultiplier = 10;

	if (SetCommTimeouts(hComm, &timeouts) == FALSE) {
		printf("\n\n    Error! in Setting Time Outs");
		return Status;
	}
	else
		printf("\n\n    Setting Serial Port Timeouts Successfull");

	/*------------------------------------ Setting Receive Mask ----------------------------------------------*/

	Status = SetCommMask(hComm, EV_RXCHAR); //Configure Windows to Monitor the serial device for Character Reception

	if (Status == FALSE) {
		printf("\n\n    Error! in Setting CommMask");
		return Status;
	}
	else {
		printf("\n\n    Setting CommMask successfull");
	}

	return TRUE;



}




void closePort(HANDLE hComm) {
	CloseHandle(hComm);//Closing the Serial Port

}

void readPort(HANDLE hComm) {
	BOOL Status;
	DWORD NoBytesRead;                     // Bytes read by ReadFile()
	DWORD dwEventMask;                     // Event mask to trigger

	/*------------------------------------ Setting WaitComm() Event   ----------------------------------------*/

	
		Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received*/

	/*-------------------------- Program will Wait here till a Character is received ------------------------*/

		if (Status == FALSE)
		{
		}
		else //If  WaitCommEvent()==True Read the RXed data using ReadFile();
		{
			while (1) {
				Status = ReadFile(hComm, &joystickEstadoAtual, sizeof(joystickEstadoAtual), &NoBytesRead, NULL);

				printf("Movimento: %d\n", joystickEstadoAtual.movimento);
				printf("BTN 1: %d\n", joystickEstadoAtual.btn1);
				printf("BTN 2: %d\n", joystickEstadoAtual.btn2);
				printf("BTN 3: %d\n", joystickEstadoAtual.btn3);



			}
	}
}

void main(void)
{
	HANDLE hComm;                          // Handle to the Serial port  // Name of the Serial port(May Change) to be opened,
	BOOL  Status;                          // Status of the various operations           
	joystickEstadoAtual.movimento = 0;
	joystickEstadoAtual.btn1 = 0;
	joystickEstadoAtual.btn2 = 0;
	joystickEstadoAtual.btn3 = 1;


	openPort(&hComm); // Open Port

	Status = settings(hComm);  //Set configuration Port
	if (Status == FALSE) {
		printf("ERRO!");
	}

	else {
		
			readPort(hComm);

		
	}



	closePort(hComm);
	system("exit");



}//End of Main()

The problem is the receiver get what is to be in btn1, for example, it gets to movimento. The data is wrong! And I can’t do something like <1, 0, 0, 0> for example, and wait to find the first is <.

What is the size of 'byte' on your PC? I personally don't know. It would be much safer to make it an unsigned char. You could also do some debugging by printing out the sizes of each of your parameters on the arduino and PC and make sure they match (1 byte or 2 byte)

byte is pretty universally 8 bits. You would have to go back to the 70s or earlier to get something different.

The real problem with Serial communication is finding where the message begins. Once you do that then reading a struct is easy.

Usually it is better to make the Serial protocol human-readable so you can observe it in Serial Monitor or another terminal program.

If I use this and the IDE's serial monitor, the bytes look to be sent correctly:

typedef struct JoystickEstadoAtual
{
    int movimento;
    int btn1;
    int btn2;
    int btn3;
    
}JoystickEstadoAtual;


JoystickEstadoAtual 
    *JSA,
    joystickEstadoAtual;


void setup() 
{
    // put your setup code here, to run once:
    Serial.begin(9600);
    JSA = (JoystickEstadoAtual *)&joystickEstadoAtual;

    //send ASCII values so they should up readable on serial monitor for testing
    joystickEstadoAtual.movimento = 0x31;
    joystickEstadoAtual.btn1 = 0x32;
    joystickEstadoAtual.btn2 = 0x33;
    joystickEstadoAtual.btn3 = 0x30;

    Serial.write((uint8_t *)JSA, sizeof( joystickEstadoAtual ) );
  
}//setup

void loop() 
{
}//loop

At the Arduino side, why do you cast 0, 1, 2 and 3 to a byte pointer. It’s incorrect.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  joystickEstadoAtual.movimento = 1;
  joystickEstadoAtual.btn1 = 2;
  joystickEstadoAtual.btn2 = 3;
  joystickEstadoAtual.btn3 = 0;

}

Further I would start with sending one packet, not send continuously. So move the Serial.write to setup().

A first check in your PC code would be to see how many bytes you have received. If that’s not the size of your struct in the Arduino (8 bytes), don’t process and keep reading the serial port and adding to a buffer.
It could look like below (not tested)

void readPort(HANDLE hComm)
{
    BOOL Status;
    DWORD NoBytesRead;                      // Bytes read by ReadFile()
    DWORD dwEventMask;                      // Event mask to trigger

    byte buffer[32];                         // buffer to store received data
    DWORD bufIndex = 0;                     // where to store data in buffer

    /*------------------------------------ Setting WaitComm() Event   ----------------------------------------*/
    Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received*/

    /*-------------------------- Program will Wait here till a Character is received ------------------------*/

    if (Status == FALSE)
    {
    }
    else //If  WaitCommEvent()==True Read the RXed data using ReadFile();
    {
        while (1)
        {
            //Status = ReadFile(hComm, &joystickEstadoAtual, sizeof(joystickEstadoAtual), &NoBytesRead, NULL);
            Status = ReadFile(hComm, &buffer[bufIndex], sizeof(buffer), &NoBytesRead, NULL);
            
            if(Status == FALSE)
            {
                // handle the error
                printf("ReadFile returned false");
            }
            else
            {
              // show how many bytes came in
              printf("Received %02d bytes\n", NoBytesRead);
              // update the index
              bufIndex += NoBytesRead;
              printf("Total received %02d bytes\n", bufIndex);
              
              // the size of the struct in Arduino is 8 bytes; check if we have received all of them
              if(bufIndex >= 8)
              {
                // reset for next receive of packet
                bufIndex = 0;
                
                // print out the data
                for(int cnt = 0; cnt < 8; cnt++)
                {
                  printf("0x%02X ", buffer[cnt])
                }
                printf("\n==============\n")
              }
            }
            

            //printf("Movimento: %d\n", joystickEstadoAtual.movimento);
            //printf("BTN 1: %d\n", joystickEstadoAtual.btn1);
            //printf("BTN 2: %d\n", joystickEstadoAtual.btn2);
            //printf("BTN 3: %d\n", joystickEstadoAtual.btn3);
        }
    }
}

The output could look like

Received 3 bytes
Total received 3 bytes
Received 5 bytes
Total received 8 bytes

The next part of the output will (hopefully) either be

0x00 0x01 0x00 0x02 0x00 0x03 0x00 0x04
==============

or
0x01 0x00 0x02 0x00 0x03 0x00 0x04 0x00
==============

Next check what the size of your struct in the PC code is; that should match with the size of the struct at the Arduino side (8 bytes). Once it does, you can either copy or cast; below a copy

memcpy(&joystickEstadoAtual, buffer, sizeof(JoystickEstadoAtual));
printf("Movimento: %d\n", joystickEstadoAtual.movimento);
printf("BTN 1: %d\n", joystickEstadoAtual.btn1);
printf("BTN 2: %d\n", joystickEstadoAtual.btn2);
printf("BTN 3: %d\n", joystickEstadoAtual.btn3);

You might still have a problem with the endianess in which case the number for movimento might be 256 instead of 1.