ESP8266 Client connexion via a webscoket (no library, only AT commands) - websocket

I am working on websocket implementation on client side using AT commands.
I've taken this as a baseline and read this.
Hardware : ESP8266+arduino uno.
Code :
String cmd = "AT+CIPSTART=\"TCP\",\""; cmd += SERVER_IP; cmd += "\",81"; //Start a TCP connection. to server SERVER_IP on port 81
if (!sendCommand(cmd, "OK", CONTINUE))
return;
delay(2000);
if (!sendCommand("AT+CIPSTATUS", "OK", CONTINUE))// Check for TCP Connection status.
return;
cmd = "GET 192.168.43.228:81 HTTP/1.1\r\n";
cmd += "Host: 192.168.43.228:81\r\n";
cmd += "Upgrade: websocket\r\n";
cmd += "Connection: Upgrade\r\n\r\n";
if (!sendCommand("AT+CIPSEND=" + String(cmd.length()), ">", CONTINUE)) {
sendCommand("AT+CIPCLOSE", "", CONTINUE);
Serial.println("Connection timeout.");
return;
}
sendCommand(cmd, "OK", CONTINUE);// Send data to server.
delay(1000);
readResponseData("");
Log on arduino side :
ESP8266 Demo
AT+RST
OK
bBֆ#⸮Sc⸮⸮⸮ȤS⸮⸮⸮ɥ⸮⸮⸮⸮H⸮
[System Ready
, Vendo:⸮ݹ⸮⸮⸮ɹcom]
AT+GMR
0018000902
OK
AT+CWMODE?
+CWMODE:1
OK
AT+CWMODE=1
no change
AT+CWMODE=1
no change
AT+CIPMUX=0
OK
AT+CWJAP="AndroidAP","xxxx"
OK
Connected to WiFi.
AT+CWJAP="AndroidAP","xxxxx"
OK
AT+CWSAP=?
no this fun
AT+CIFSR
192.168.43.29
OK
Module is ready.
AT+CIPSTART="TCP","192.168.43.228",81
OK
Linked
AT+CIPSTATUS
STATUS:3
+CIPSTATUS:0,"TCP","192.168.43.228",81,0
OK
AT+CIPSEND=100
>
GET 192.168.43.228:81 HTTP/1.1
Host: 192.168.43.228:81
Upgradewrong syntax
ERROR
SEND OK
OK
Unlink
Server side :
WiFi connected
IP address:
192.168.43.228
Server available at ws://192.168.43.228:81
Accepted new web sockets client at index 0
--
...and nothing else from the server which is supposed sending a message as soon as it accepts the websocket.
Please give me some insight :)

I found one solution.
In fact I was not aware about all the details of RFC4566
After a successful handshake, you need to be inline with the frame requirement. It is not just as raw text :)
For a limited use case (i.e. length<125) here is the overview of the solution:
char str[] = "Hello";
char buf[125];
bool toMask = true;
uint8_t extra = toMask ? 6 : 2;
buildFrame(str, buf, WS_OPCODE_TEXT, toMask);
ESP8266SendData(0, buf, str.length() + extra);
I've tested this to get:
void buildFrame(char *str, uint8_t *ret, uint8_t opcode, bool maskon) {
uint8_t mask[4];
int size = strlen(str);
// Opcode; final fragment
ret[0] = opcode | WS_FIN;
ret[1] = (uint8_t) (size) | (maskon == true ? WS_MASK : 0);
if (maskon) {
mask[0] = random(0, 256);
mask[1] = random(0, 256);
mask[2] = random(0, 256);
mask[3] = random(0, 256);
for (int i = 2; i < 4 + 2; ++i) {
ret[i] = mask[i - 2];
}
for (int i = 6; i < size + 6; i++) {
ret[i] = str[i - 6] ^ mask[(i - 6) % 4];
}
}
else {
for (int i = 2; i < size + 2; ++i) {
ret[i] = (uint8_t) str[i - 2];
}
}
}
For frame decoding :
uint8_t extractPayload(String buffer, String& payload) {
// here only payloads whose size < 125
bool FIN = buffer[0] & WS_FIN;
uint8_t opcode = buffer[0] & ~WS_FIN;
bool hasMask = buffer[1] & WS_MASK;
uint8_t len = buffer[1] & ~WS_MASK;
uint8_t mask[4];
if (hasMask) {
mask[0] = buffer[2];
mask[1] = buffer[3];
mask[2] = buffer[4];
mask[3] = buffer[5];
for (int i = 6; i < len + 6; i++) {
payload += (char) (buffer[i] ^ mask[(i - 6) % 4]);
}
}
else {
payload = buffer.substring(2);
}
Serial.print("FIN = "); Serial.println(FIN, HEX);
Serial.print("Opcode = "); Serial.println(opcode, HEX);
Serial.print("Mask = "); Serial.println(hasMask, HEX);
Serial.print("Payload length = "); Serial.println(len, HEX);
return opcode;
}

Related

ESP32 Task watchdog got triggered using ESP IDF

We need to read ADC module over I2C continuously 20 times to get stable values of ADC.
We have created a task for it, but code stop working in couple of min showing below error.
E (1925655) task_wdt: Task watchdog got triggered. The following tasks did not r
eset the watchdog in time:
E (1925655) task_wdt: - IDLE (CPU 0)
E (1925655) task_wdt: Tasks currently running:
E (1925655) task_wdt: CPU 0: esp_timer
We are not getting any exact solution for our error. Below is the task espfor reference.
void Hal_Read_Average_Voltage_For_TLA202x (void *pvParameters)
{
float read_value = 0, bigger_value = 0, voltage = 0;
while(1)
{
Hal_TLA2024_Re_Initialize ();
{
for (int count1 = 0; count1 < 20; count1++)
{
voltage = readVoltage (); //Performs I2C register read
if (voltage > bigger_value)
{
bigger_value = voltage;
}
vTaskDelay (1);
}
read_value += bigger_value;
bigger_value = 0;
}
ESP_LOGE(TAG, "ADC Highest Value = %f\n", (read_value));
read_value = 0;
bigger_value = 0;
voltage = 0;
vTaskDelay (300 / portTICK_PERIOD_MS);
}
}
float readVoltage (void)
{
int16_t raw_voltage;
uint16_t u16TempRead = 0;
uint8_t u8TempRead[2] = { 0, 0 };
uint8_t u8TempAddress = TLA202x_DATA_REG;
Hal_I2C_Read_Register (TLA202x_I2CADDR_DEFAULT, u8TempAddress, u8TempRead, 2, 1);
u16TempRead = u8TempRead[1] | (u8TempRead[0] << 8);
raw_voltage = u16TempRead;
// this will read the sign bit correctly, but shifting will move the bit out
// of the msbit
if (raw_voltage & 0x8000)
{
raw_voltage >>= 4;
raw_voltage |= 0x8000;
}
else
{
raw_voltage >>= 4;
}
switch (current_range)
{
case TLA202x_RANGE_6_144_V:
voltage = raw_voltage *= 3;
break;
case TLA202x_RANGE_4_096_V:
voltage = raw_voltage *= 2;
break;
case TLA202x_RANGE_2_048_V:
voltage = raw_voltage *= 1;
break;
case TLA202x_RANGE_1_024_V:
voltage = raw_voltage *= 0.5;
break;
case TLA202x_RANGE_0_512_V:
voltage = raw_voltage *= 0.25;
break;
case TLA202x_RANGE_0_256_V:
voltage = raw_voltage *= 0.125;
break;
}
voltage /= 1000.0; // mV =>V
return voltage;
}
void Hal_I2C_Read_Register (uint32_t slave_address, int register_address, uint8_t read_data_buffer[],
uint8_t read_buffer_length, uint8_t write_buffer_length)
{
i2c_cmd_handle_t cmd;
DATA_READ: cmd = i2c_cmd_link_create ();
i2c_master_start (cmd);
if (register_address != -1)
{
i2c_master_write_byte (cmd, slave_address << 1 | I2C_MASTER_WRITE,
ACK_CHECK_EN);
i2c_master_write_byte (cmd, register_address, ACK_CHECK_EN);
i2c_master_start (cmd);
}
i2c_master_write_byte (cmd, slave_address << 1 | I2C_MASTER_READ,
ACK_CHECK_EN);
if (read_buffer_length > 1)
{
i2c_master_read (cmd, read_data_buffer, read_buffer_length - 1, ACK_VAL);
}
i2c_master_read_byte (cmd, read_data_buffer + read_buffer_length - 1,
NACK_VAL);
i2c_master_stop (cmd);
esp_err_t ret = i2c_master_cmd_begin (I2C_NUM_0, cmd, 1000/ portTICK_RATE_MS);
i2c_cmd_link_delete (cmd);
if (ret == ESP_OK)
{
}
else if (ret == ESP_ERR_TIMEOUT)
{
// ESP_LOGW(TAG, "Bus is busy");
}
else
{
ESP_LOGW(TAG, "Read failed %d", ret);
goto DATA_READ;
}
}
We are having 2 more thread running on same priority.
If we remove the for loop in the above thread then there is no WDT error.
Updated ESP-IDF version to 4.4 and it solved this issue.

Is it normal for winapi to take around 70ms to read from serial port?

The true time it takes from when I send the first bit to a serial port to when I receive the last bit it pings back I measured to be 6ms but ReadFile takes around 70-80ms. I'm wondering if this is expected, is this just Windows or is it my code at fault? Here's the function to send and read from the serial port, in my main I have declared and initialized the HANDLE and called that function.
int sendBytes(char* command, char* COM, HANDLE hSerial, int read) {
BOOL Write_Status;
DCB dcbSerialParams = { 0 }; // Initializing DCB structure
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Write_Status = GetCommState(hSerial, &dcbSerialParams); //retreives the current settings
if (Write_Status == FALSE) {
printf("\n Error! in GetCommState()");
CloseHandle(hSerial);
return 1;
}
dcbSerialParams.BaudRate = CBR_57600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
Write_Status = SetCommState(hSerial, &dcbSerialParams); //Configuring the port according to settings in DCB
if (Write_Status == FALSE)
{
CloseHandle(hSerial);
return 1;
}
///*----------------------------- Writing a Character to Serial Port----------------------------------------*/
int length = strlen(command);
char send[20];
strcpy(send, command);
send[length + 1] = 13;
send[length + 2] = 10;
DWORD dNoOFBytestoWrite; // No of bytes to write into the port
DWORD dNoOfBytesWritten = 0; // No of bytes written to the port
dNoOFBytestoWrite = length + 2; // Calculating the no of bytes to write into the port
if (!WriteFile(hSerial, send, dNoOFBytestoWrite, &dNoOfBytesWritten, NULL))
printf("Error writing text to %s\n", COM);
if (read) {
int maxChars = 100;
BOOL Read_Status; // Status of the various operations
DWORD dwEventMask; // Event mask to trigger
char SerialBuffer[100]; // Buffer Containing Rxed Data
DWORD NoBytesRead; // Bytes read by ReadFile()
///*------------------------------------ Setting Receive Mask ----------------------------------------------*/
Read_Status = SetCommMask(hSerial, EV_RXCHAR); //Configure Windows to Monitor the serial device for Character Reception
if (Read_Status == FALSE)
printf("\n\n Error! in Setting CommMask");
// else
// printf("\n\n Setting CommMask successfull");
///*------------------------------------ Setting WaitComm() Event ----------------------------------------*/
// printf("\n\n Waiting for Data Reception");
Read_Status = WaitCommEvent(hSerial, &dwEventMask, NULL); //Wait for the character to be received
// /*-------------------------- Program will Wait here till a Character is received ------------------------*/
if (Read_Status == FALSE)
{
printf("\n Error! in Setting WaitCommEvent()");
}
else //If WaitCommEvent()==True Read the RXed data using ReadFile();
{
// printf("\n\n Characters Received \t");
clock_t begin = clock();
if (!ReadFile(hSerial, SerialBuffer, 24, &NoBytesRead, NULL))
{
printf("wrong character");
return 1;
}
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("time : %f\n",time_spent);
}
}
}
This is not how you measure timing with sub-second precision:
clock_t begin = clock();
// stuff
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
This is how you measure timing:
LARGE_INTEGER before, after, frequency;
QueryPerformanceCounter(&before);
// stuff
QueryPerformanceCounter(&after);
QueryPerformanceFrequency(&frequency);
double time_spent = (after.QuadPart - before.QuadPart) / (double)frequency.QuadPart;
CLOCKS_PER_SEC is imprecise, and then clock() can be even worse, often as bad as the scheduler quantum which is typically 10ms or 15ms.

W5100 is sending garbage

I try to implement a web interface with a W5100 Ethernet Controller and an XMega, but my browser prints out this weird result:
Please take a look at my code:
SPIM_Config_t Config_SPIM = {
.Device = &SPIC,
.Mode = SPI_MODE_0,
.Prescaler = SPI_PRESCALER_64,
};
W5100_Config_t Config_Ethernet = {
.Submask = {255, 255, 0, 0},
.IP = {169, 254, 133, 121},
.Gateway = {169, 154, 133, 129},
.MAC = {0x00, 0x00, 0x00, 0x00, 0x00, 0xAA}
};
uint8_t Rx_Buffer[2048];
uint8_t Tx_Buffer[2048];
const char HTTP[] = "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n"
"<html>\r\n"
"<body>\r\n"
"<title>Title</title>\r\n"
"<p>Hello world</p>\r\n"
"</body>\r\n"
"</html>\r\n";
int main(void)
{
W5100_Init(&Config_SPIM, &Config_Ethernet);
while(1)
{
W5100_Status_t Status;
W5100_GetState(0, &Status);
switch(Status)
{
case W5100_SOCK_CLOSED:
{
if(W5100_Open(0, W5100_PROT_TCP, 80, W5100_MEM_2K, W5100_MEM_2K, 65535) == W5100_NO_ERROR)
{
W5100_Listen(0, ETHERNET_TIMEOUT);
}
break;
}
case W5100_SOCK_ESTABLISHED:
{
uint16_t Rx_Bytes;
if(W5100_GetBytes(0, &Rx_Bytes) == W5100_NO_ERROR)
{
if(Rx_Bytes)
{
W5100_Receive(0, Rx_Buffer, Rx_Bytes);
strcpy((char*)Tx_Buffer, HTTP);
W5100_Send(0, Tx_Buffer, strlen((char*)HTTP), ETHERNET_TIMEOUT);
}
else
{
}
}
W5100_Disconnect(0, ETHERNET_TIMEOUT);
break;
}
case W5100_SOCK_FIN_WAIT:
case W5100_SOCK_CLOSING:
case W5100_SOCK_TIME_WAIT:
case W5100_SOCK_CLOSE_WAIT:
case W5100_SOCK_LAST_ACK:
{
W5100_Close(0, ETHERNET_TIMEOUT);
break;
}
}
}
}
I think the error is somewhere in my W5100_Send function and it seems that the Controller is sending the content of different memory locations, but I can´t figure out the error. The code based on the datasheet of the Ethernet Controller:
W5100_ErrorCode_t W5100_Send(uint8_t Socket, uint8_t* Buffer, uint16_t Length, uint32_t Timeout)
{
uint8_t Temp[2];
uint8_t Mask;
uint16_t SocketBase;
uint16_t Offset;
uint16_t Free;
uint16_t SocketMemory;
uint32_t Timeout_Temp = Timeout;
if(!_W5100_IsInitialized)
{
return W5100_NOT_INITIALIZED;
}
else if((Socket > 0x04) || (Buffer == NULL) || (Length == 0x00))
{
return W5100_INVALID_PARAM;
}
// Get the memory mask for address calculation
W5100_ReadRegister(W5100_REGISTER_TMSR, &Mask);
Mask &= (0x03 << (Socket << 0x01));
// Check for invalid memory by comparing the memory mask for the given socket and the socket index
if(((Socket > 0) && (Mask == 3)) || ((Socket > 1) && (Mask == 2)))
{
return W5100_INVALID_PARAM;
}
SocketBase = W5100_SOCKET_ADDR(Socket);
SocketMemory = W5100_SOCKET_MEM_OFFSET << Mask;
// Wait while the buffer is full
do
{
// Get the free bytes
W5100_ReadRegister(SocketBase + W5100_OFFSET_TX_FSR0, &Temp[0]);
W5100_ReadRegister(SocketBase + W5100_OFFSET_TX_FSR1, &Temp[1]);
Free = ((uint16_t)(Temp[0] << 0x08)) | Temp[1];
if(Timeout_Temp-- == 0x00)
{
W5100_Disconnect(Socket, Timeout);
return W5100_TIMEOUT;
}
_delay_ms(1);
}while(Free < Length);
// Get the write pointer address
W5100_ReadRegister(SocketBase + W5100_OFFSET_TX_WR0, &Temp[0]);
W5100_ReadRegister(SocketBase + W5100_OFFSET_TX_WR1, &Temp[1]);
Offset = (((uint16_t)(Temp[0] << 0x08)) | Temp[1]) & W5100_TX_MEM_MASK;
// Check for an overflow
if(Offset + Length > SocketMemory)
{
uint16_t Upper;
uint16_t Left;
Upper = SocketMemory - Offset;
Left = Length - Upper;
W5100_WriteMemory(W5100_TX_BUFFER_BASE + (SocketMemory * Socket) + Offset, Buffer, Upper);
W5100_WriteMemory(W5100_TX_BUFFER_BASE + (SocketMemory * Socket), Buffer, Left);
}
else
{
W5100_WriteMemory(W5100_TX_BUFFER_BASE + (SocketMemory * Socket) + Offset, Buffer, Length);
}
W5100_WriteRegister(SocketBase + W5100_OFFSET_TX_WR0, Offset >> 0x08);
W5100_WriteRegister(SocketBase + W5100_OFFSET_TX_WR1, Offset & 0xFF);
return W5100_ExecuteCommand(Socket, W5100_CMD_SEND, Timeout);
}
You should fully rewrite your W5100_Send, because it is full of issues.
For example, calculation of Mask value has no sense.
The cycle which is waiting for Free value always delays at least 1 ms, even when good value obtained from the beginning. Also, when timed out, it breaks, even if received Free value is good.
Offset value is damaged by & operation:
Offset = (((uint16_t)(Temp[0] << 0x08)) | Temp[1]) & W5100_TX_MEM_MASK;
This value is never increased by the written data size, and the damaged value is written back to W5100_OFFSET_TX_WR1:W5100_OFFSET_TX_WR0
The wrapping data writing has an error:
W5100_WriteMemory(W5100_TX_BUFFER_BASE + (SocketMemory * Socket) + Offset, Buffer, Upper);
W5100_WriteMemory(W5100_TX_BUFFER_BASE + (SocketMemory * Socket), Buffer, Left);
You're copying to both the parts from the start of Buffer. In the second line it should be &Buffer[Upper]
Etc etc...
First you need to determine size of sockets. I encourage you to set up the socket sizes from the beginning, thus avoiding offset and size calculation on the runtime.
But if you want to determine the socket size dynamically, then you can do it as follows:
uint16_t SocketBufAddr = W5100_TX_BUFFER_BASE; // Start of the socket memory block
SocketMemory = 0; // Size of the socket memory block
W5100_ReadRegister(W5100_REGISTER_TMSR, &Mask);
for (uint8_t i = 0 ; i <= Socket ; i++) {
SocketBufAddr += SocketMemory; // Increase the offset by the previous socket size
SocketMemory = 1024 << ((Mask >> (i * 2)) & 3);
}
now, the writing process should be something like this:
// Get the write pointer address
W5100_ReadRegister(SocketBase + W5100_OFFSET_TX_WR0, &Temp[0]);
W5100_ReadRegister(SocketBase + W5100_OFFSET_TX_WR1, &Temp[1]);
uint16_t WrPointer = (((uint16_t)(Temp[0] << 0x08)) | Temp[1]); // no & operation! It is the 16-bit pointer!!!
Offset = WrPointer & (SocketMemory - 1); // Offset inside the socket memory block. SocketMemory is always = 2^n
// Check for an overflow
if(Offset + Length > SocketMemory)
{
uint16_t Upper;
uint16_t Left;
Upper = SocketMemory - Offset ;
Left = Length - Upper;
W5100_WriteMemory(SocketBufAddr + Offset, Buffer, Upper);
W5100_WriteMemory(SocketBufAddr, &Buffer[Upper], Left);
}
else
{
W5100_WriteMemory(SocketBufAddr + Offset, Buffer, Length);
}
WrPointer += Length; // Increase full 16-bit pointer value
// Write the new pointer back
W5100_WriteRegister(SocketBase + W5100_OFFSET_TX_WR0, WrPointer >> 0x08);
W5100_WriteRegister(SocketBase + W5100_OFFSET_TX_WR1, WrPointer & 0xFF);
return W5100_ExecuteCommand(Socket, W5100_CMD_SEND, Timeout);

IR Receiver RC5 with Pic12F1572

I am building an IR Receiver with PIC12F1572 with receiver module TSOP2438
My objective of this project is to receive a data by remote control and send it to PC via UART..
I have done the code and I am testing it I can send the normal value through the UART but Somewhereis wrong so that I can not receive the hex values regarding the commands of remote control
Can anyone see my code and tell where I am goping wrong?
Here is my code
void main(void)
{
OSCILLATOR_Initialize(); // 0x78 for Fosc = 16Mhz
PIN_MANAGER_Initialize(); //All port pins Digital and input
EUSART_Initialize();
INTCONbits.IOCIF = 0; // Interrupt on-change Flag
INTCONbits.PEIE = 1; //SEt Peripheral Interrupt
INTCONbits.GIE = 1; //Set Global Interrupt
//while(!OSCSTATbits.HFIOFS); //Check here or wait here to OSC stable/ 0.5% accuracy
TRISAbits.TRISA2 = 1; //Configure R1 as input
// uint16_t Input_buffer [20];
EUSART_Write(0x40); // 0x40 = # some flag
while(1)
{
count = 0;
//while((IR_PIN)); //IR_PIN receives an IR signal its output pin goes from logic 1 to logic 0
//which causes the microcontroller to start reading the IR signal using the function. decode()
EUSART_Write(0x41);
//while(IR_PIN);
if(Decode()) //check if RC5 decoding- new data is arrived
{
EUSART_Write(0x42);
toggle_bit = bit_test(IR_Code, 11);
address = (IR_Code >> 6) & 0x1F;
command = IR_Code & 0x3F;
EUSART_Write(toggle_bit);
EUSART_Write(address);
EUSART_Write(command);
EUSART_Write(0x43);
}
}
}
/*----------*/
uint8_t Measure_space()
{
TMR0_Initialize();
while(IR_PIN && (count < 2000))
count = TMR0_ReadTimer(); //Read timer value and store it in count value
if((count > 1999) || (count < 700))
return 0; //0 = If width is out of range
if(count > 1200)
return 1; //1 = If width is long
else
return 2; //2 = If the width is short
}
uint8_t Decode()
{
uint8_t i = 0, check;
mid1:
check = Measure_Pulse();
if(check == 0)
return FALSE;
bit_set(IR_Code, 13 - i);
i++;
if(i > 13)
return TRUE;
if(check == 1)
goto mid0;
else
goto start1;
mid0:
check = Measure_space();
if((check == 0) && (i != 13))
return FALSE;
bit_clear(IR_Code, 13 - i);
i++;
if(i > 13) return TRUE;
if(check == 1)
goto mid1;
else
goto start0;
start1:
check = Measure_space();
if(check != 2)
return FALSE;
goto mid1;
start0:
check = Measure_Pulse();
if(check != 2)
return FALSE;
goto mid0;
}
I think this is because you are sending Hex value without converting to string. If you want to print this Hex value in PC terminal, First you have to convert it to ASCII string.

Not getting ack after sending xmodem frame

I have a device connected to serial port and waiting for a file to be transmited using xmodem protocol.
I have tried constructing a message using in xmodem format and sending it, however I'm not getting the expected ACK for the transfer.
Bellow are the relevant bits of code:
Format of XMODEM message:
struct xmodem_packet
{
uint8_t start;
uint8_t block;
uint8_t block_neg;
uint8_t payload[128];
uint16_t crc;
};
Opening and configuring port:
HANDLE portHandler = CreateFile(L"COM9", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
DCB config = { 0 };
COMMTIMEOUTS timeout = { 0 };
// Configure
config.DCBlength = sizeof(config);
GetCommState(portHandler, &config);
config.BaudRate = CBR_115200;
config.ByteSize = 8;
config.StopBits = ONESTOPBIT;
config.Parity = NOPARITY;
SetCommState(portHandler, &config);
timeout.ReadIntervalTimeout = 50;
timeout.ReadTotalTimeoutConstant = 50;
timeout.ReadTotalTimeoutMultiplier = 50;
timeout.WriteTotalTimeoutConstant = 50;
timeout.WriteTotalTimeoutMultiplier = 10;
SetCommTimeouts(portHandler, &timeout);
Prepare module for XMODEM transfer:
DWORD toRead = 1;
DWORD wasWriten = 0;
DWORD wasRead = 0;
char responce = 0;
WriteFile(portHandler, "set load xmodem\n", 3+4+6+3, &wasWriten, NULL);
WriteFile(portHandler, "\n", 2, &wasWriten, NULL); // Doesn't work without this
Construct XMODEM frame
xmodem_frame frame;
frame.start = SOH;
frame.block = 0;
frame.block_neg = 0;
memcpy(frame.payload, "test_data", 128);
swap16(crc16(frame.payload, sizeof(frame.payload)));
Send frame and look for ACK:
WriteFile(portHandler, &frame, sizeof(frame), &wasWriten, NULL);
ReadFile(portHandler, &responce, toRead, &wasRead, NULL);
if (responce == 6)
std::cout << "ACK was recieved";
else
std::cout << "ACK wasn't recieved";
I was expecting to get an ACK, however "ACK wasn't recieved" is always printed.

Resources