Serial communication in C using Loopback on cable - c

I'm trying to create a simple Serial communication in C. I'm having some problems when receiving the data. I appears that the buffer size is not correct, or the data is not being retrieved from the Serial.
This is how I have created the code:
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#define BUFFERLENGTH 256
int main () {
HANDLE comm;
BOOL wComm;
char buf[] = "abcd1234 \r\n";
DWORD dwNoBytesToWrite = sizeof(buf);
DWORD dwNoBytesWritten = 0;
BOOL Read_Status;
DWORD dwEventMask;
char SerialBuffer[BUFFERLENGTH+1];
char finalStr[BUFFERLENGTH+1] = "";
DWORD NoBytesRead;
int i = 0;
comm = CreateFileA("\\\\.\\COM7",
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING,// Open existing port only
0, // Non Overlapped I/O
NULL);
if (comm == INVALID_HANDLE_VALUE)
printf("Error in opening serial port");
else
printf("opening serial port successful");
// set short timeouts on the comm port.
timeouts.ReadIntervalTimeout = 1;
timeouts.ReadTotalTimeoutMultiplier = 1;
timeouts.ReadTotalTimeoutConstant = 1;
timeouts.WriteTotalTimeoutMultiplier = 1;
timeouts.WriteTotalTimeoutConstant = 1;
if (!SetCommTimeouts(comm, &timeouts))
printf("setting port time-outs.");
//Config
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Write_Status = GetCommState(comm, &dcbSerialParams); //retreives the current settings
if (Write_Status == FALSE) {
printf("\n Error! in GetCommState()");
CloseHandle(comm);
return 1;
}
dcbSerialParams.BaudRate = CBR_57600; // Setting BaudRate = 9600
dcbSerialParams.ByteSize = 8; // Setting ByteSize = 8
//dcbSerialParams.
dcbSerialParams.StopBits = ONESTOPBIT; // Setting StopBits = 1
dcbSerialParams.Parity = ODDPARITY; // Setting Parity = None
// Write Serial
wComm = WriteFile(
comm,
buf,
dwNoBytesToWrite,
&dwNoBytesWritten,
NULL
);
if (!wComm)
{
printf("Problem writing to comm");
}
// MASK
Read_Status = SetCommMask(comm, EV_RXCHAR);
if (Read_Status == FALSE)
printf("\n\nError! in Setting CommMask");
else
printf("\n\nSetting CommMask successfull");
// WAITING DATA
printf("\n\nWaiting for Data Reception");
Read_Status = WaitCommEvent(comm, &dwEventMask, NULL);
if (Read_Status == FALSE)
{
printf("\n Error! in Setting WaitCommEvent()");
}
else
{
//fflush(stdin);
printf("\n\nCharacters Received\n");
do
{
if (ReadFile(comm, SerialBuffer, BUFFERLENGTH, &NoBytesRead, NULL))
{
printf("%c", SerialBuffer[i]);
strcat(finalStr, SerialBuffer[i]);
i++;
}
} while (NoBytesRead > 0);
}
CloseHandle(comm);
return 0;
}
Here is what I'm receiving as the response:

Related

Closing the handle for a serial port device takes too long, how to make it faster?

I've created a button that sends bytes to turn on LEDs for multiple similar devices. What I have found out is that if I don't close the handle I get instantaneous speed which is exactly what I need, but of course, if I don't close it I can't use it anymore meaning the button only works once. If I do close the handle it works, but much slower to the point where I can see the LEDs turn on one by one. How to go about this?
Here's the code for the sendBytes function, the code for the GUI is unnecessary because I get the same speed with a barebones C console program.
int sendBytes(char* command, char* COM) {
HANDLE hSerial2;
BOOL Write_Status;
DCB dcbSerialParams = { 0 }; // Initializing DCB structure
hSerial2 = CreateFileA(COM,
GENERIC_READ | GENERIC_WRITE,
0, // must be opened with exclusive-access
NULL, // no security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
0, // not overlapped I/O
NULL // hTemplate must be NULL for comm devices
);
printf("opening serial port successful");
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Write_Status = GetCommState(hSerial2, &dcbSerialParams); //retreives the current settings
if (Write_Status == FALSE) {
printf("\n Error! in GetCommState()");
CloseHandle(hSerial2);
return 1;
}
dcbSerialParams.BaudRate = CBR_57600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
Write_Status = SetCommState(hSerial2, &dcbSerialParams); //Configuring the port according to settings in DCB
if (Write_Status == FALSE)
{
printf("\n Error! in Setting DCB Structure");
CloseHandle(hSerial2);
return 1;
}
// Set COM port timeout settings
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (SetCommTimeouts(hSerial2, &timeouts) == 0)
{
// printf("Error setting timeouts\n");
CloseHandle(hSerial2);
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(hSerial2, send, dNoOFBytestoWrite,
&dNoOfBytesWritten, NULL))
{
printf("Error writing text to %s\n", COM);
}
else
{
printf("\n %d bytes written to %s\n", dNoOfBytesWritten, COM);
}
CloseHandle(hSerial2);//Closing the Serial Port
printf("\n ==========================================\n");
return 0;
}
I managed to find a solution, it's fairly simple.
All I did was create a HANDLE variable for each device, initialized them with the corresponding COM port and passed that HANDLE to a slightly modified sendBytes function so it doesn't have to close and create a new one each time it's called when you press the button.
The problem now is that reading bytes is slow, here's the code:
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 = 256;
BOOL Read_Status; // Status of the various operations
DWORD dwEventMask; // Event mask to trigger
char SerialBuffer[256]; // 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");
if (!ReadFile(hSerial, SerialBuffer, maxChars, &NoBytesRead, NULL))
{
printf("wrong character");
return 1;
}
printf("noBytes: %d\n", NoBytesRead);
/*------------Printing the RXed String to Console----------------------*/
int j = 0;
char readArray[256];
while (SerialBuffer[j] != '\r') {
printf("%c", SerialBuffer[j]);
readArray[j] = SerialBuffer[j];
j++;
}
readArray[j++] = '\0';
}
}
}

Reading incoming serial data with windows using C

I am using the code found here to receive data from an ATmega microcontroller to my PC. The code "USB2SERIAL_Read_W32.c" handles the Windows COM ports and receives serial data, which it then prints to the console.
I tried to modify the code to run continuously, i.e. to wait for data, print them when it receives characters, and then return to waiting for new data.
Here you can see the code, with my interventions.
#include <Windows.h>
#include <stdio.h>
void main(void)
{
HANDLE hComm; // Handle to the Serial port
char ComPortName[] = "\\\\.\\COM9"; // Name of the Serial port(May Change) to be opened,
BOOL Status; // Status of the various operations
DWORD dwEventMask; // Event mask to trigger
char TempChar; // Temperory Character
char SerialBuffer[256]; // Buffer Containing Rxed Data
DWORD NoBytesRead; // Bytes read by ReadFile()
int i = 0;
int counter=0;
printf("\n\n +==========================================+");
printf("\n | Serial Port Reception (Win32 API) |");
printf("\n +==========================================+\n");
/*---------------------------------- Opening the Serial Port -------------------------------------------*/
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);
else
printf("\n Port %s Opened\n ", ComPortName);
/*------------------------------- 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()");
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");
}
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 = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
if (SetCommTimeouts(hComm, &timeouts) == FALSE)
printf("\n\n Error! in Setting Time Outs");
else
printf("\n\n Setting Serial Port Timeouts Successfull");
/*------------------------------------ Setting Receive Mask ----------------------------------------------*/
dwEventMask=EV_RXCHAR;
Status = SetCommMask(hComm, dwEventMask); //Configure Windows to Monitor the serial device for Character Reception
if (Status == FALSE)
printf("\n\n Error! in Setting CommMask");
else
printf("\n\n Setting CommMask successfull");
/*------------------------------------ Setting WaitComm() Event ----------------------------------------*/
while(1){
int j =0;
i=0;
for(j=0;j<sizeof(SerialBuffer);j++){ //Clear SerialBuffer
SerialBuffer[j]=0;
}
printf("\n\n Waiting for Data Reception");
Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received
/*-------------------------- Program will Wait here till a Character is received ------------------------*/
if (Status == FALSE){
printf("\n Error! in Setting WaitCommEvent()");
}
else //If WaitCommEvent()==True Read the RXed data using ReadFile();
{
printf("\n\n Characters Received");
do{
Status = ReadFile(hComm, &TempChar, sizeof(TempChar), &NoBytesRead, NULL);
if(Status==TRUE){
if(NoBytesRead>0){
SerialBuffer[i] = TempChar;
}
i++;
}
else
printf("\n Error! in Setting ReadFile()");
}while (NoBytesRead);
/*------------Printing the RXed String to Console----------------------*/
printf("\n\n ");
for (j = 0; j < strlen(SerialBuffer); j++)
printf("%c", SerialBuffer[j]);
}
//CloseHandle(hComm);//Closing the Serial Port
printf("\n +==========================================+\n");
}
}//End of Main()
The changes I did were to add the while(1) loop, clear the buffer at the start of each loop, commented out the closing of the port handler, changed the timeouts as mentioned in the "Timeouts" section in this microsoft tutorial and few more minor tweaks and cosmetics.
The problem is that for some reason, whenever I receive the string "1234", firstly the expected event is triggered, printing the received characters, and then another event is triggered for some reason, with no characters waiting, as you can see in the following picture:
To sum up, why is the unexpected event triggered and how can I solve it?
EDIT: I haven't managed to find the solution yet, however I am posting a workaround that I found (perhaps it can help someone to spot the initial problem). If I set the Comm Mask to zero, and reset it to EV_RXCHAR in each loop iteration, it seems to work as expected; That is, when I reach the WaitCommEvent line for the second time, it is not automatically triggered as before. The bad thing is that I cannot explain why it works now, and I believe that it should be working correctly in the first place as well. So any help would be greatly appreciated. Here is the code with the workaround, which sets the CommMask to zero and back to EV_RXCHAR:
#include <Windows.h>
#include <stdio.h>
void main(void){
printf("Hello!\n");
DWORD dwCommEvent;
DWORD dwRead;
DWORD lpEvtMask;
char chRead;
char ComPortName[] = "\\\\.\\COM9"; // Name of the Serial port(May Change) to be opened,
int i=0;
HANDLE hComm;
hComm = CreateFile( ComPortName,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0);
if (hComm == INVALID_HANDLE_VALUE)
printf("Error opening port.\n");
//////////////////////////////////////////////////////
DCB dcb;
FillMemory(&dcb, sizeof(dcb), 0);
if (!GetCommState(hComm, &dcb)) // get current DCB
printf("Error GetCommState.\n");
// Update DCB rate.
dcb.BaudRate = CBR_9600 ;
dcb.ByteSize = 8; // Setting ByteSize = 8
dcb.StopBits = ONESTOPBIT; // Setting StopBits = 1
dcb.Parity = NOPARITY; // Setting Parity = None
dcb.DCBlength = sizeof(dcb);
// Set new state.
if (!SetCommState(hComm, &dcb))
printf("Error SetCommState.\n");
// Error in SetCommState. Possibly a problem with the communications
// port handle or a problem with the DCB structure itself.
/////////////////////////////////////////////////////////////////////
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(hComm, &timeouts))
printf("Error timeouts.\n");
if(!PurgeComm(hComm,PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT))
printf("Error PurgeComm.\n");
////////////////////////////////////////
for ( ; ; ) {
if (!SetCommMask(hComm, 0))
printf("Error CommMask.\n");
if (!SetCommMask(hComm, EV_RXCHAR))
printf("Error CommMask.\n");
printf("Waiting for characters.. \n\n");
if (WaitCommEvent(hComm, &dwCommEvent, NULL)) {
do {
if (ReadFile(hComm, &chRead, 1, &dwRead, NULL)){
if(dwRead!=0)
printf("Character Received: %c\n",chRead);
}
else{
printf("ErrorReadFile.\n");
break;
}
}while (dwRead);
}
else{
printf("Error WaitCommEvent.\n");
break;
}
printf("=========================\n");
}
}

Using PThread in Serial Programming in Windows

I am a noob in serial programming and I am trying to build a com port sniffer to sniff bytes between two ports by using pthreads. I am using com0com emulator for the com ports. The emulator creates COM ports in connected pairs. At first, I wanted to sniff using this scenario:
Application1<--->COM3<--->Sniffer<--->COM4<--->Application2
However, I am unable to read what goes on between the two ports even when I set the ports in the code to non-exclusive mode before the running the application, also, the applications are unable to access the ports (error is "Access Denied").
I tried to this scenario:
Application1<--->COM3<--->COM4<--->Sniffer<--->COM5<--->COM4<--->Application2
With this, code is able to read COM4 and COM5 while the applications take COM3 and COM4. In this scenario, I am able to see the bytes and write in one direction with one thread. But when I try to use two threads to ensure bi-directional communication, it fails at the first read.
Code for the second scenario:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <pthread.h>
void setupPort(HANDLE * handle, char * portName);
void * readFromPort(void * handles);
void writeToPort(HANDLE * handle, char data[]);
typedef struct
{
HANDLE from;
HANDLE to;
} bi_ports;
int main()
{
HANDLE first_port, second_port;
char * first_port_name = "COM4";
char * second_port_name = "COM5";
bi_ports *ports_first, *ports_second;
pthread_t firstToSecondThread, secondToFirstThread;
setupPort(&first_port, first_port_name);
setupPort(&second_port, second_port_name);
ports_first = (bi_ports *) malloc(sizeof(bi_ports));
ports_second = (bi_ports *) malloc(sizeof(bi_ports));
ports_first->from = first_port;
ports_first->to = second_port;
ports_second->from = second_port;
ports_second->to = first_port;
pthread_create(&firstToSecondThread, NULL, readFromPort, (void *) ports_first);
pthread_create(&secondToFirstThread, NULL, readFromPort, (void *) ports_second);
pthread_join(firstToSecondThread, NULL);
pthread_join(secondToFirstThread,NULL);
return 0;
}
void setupPort(HANDLE * handle, char * portName)
{
BOOL status;
*handle = CreateFile(portName, //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING,// Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (handle == INVALID_HANDLE_VALUE)
{
printf("\n%s could not be opened\n", portName);
}
else
{
printf("\n%s successfully opened.\n", portName);
}
DCB dcbSerialParams = { 0 }; // Initializing DCB structure
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
status = GetCommState(*handle, &dcbSerialParams); //retreives the current settings
if (status == FALSE)
printf("\n Error! in GetCommState()");
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(*handle, &dcbSerialParams); //Configuring the port according to settings in DCB
if (status == FALSE)
{
printf("\n Error! in Setting DCB Structure");
}
else //If Successful display the contents of the DCB Structure
{
printf("\n\n Setting DCB Structure Successful\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(*handle, &timeouts) == FALSE)
printf("\n\n Error! in Setting Time Outs");
else
printf("\n\n Setting Serial Port Timeouts Successful");
/*------------------------------------ Setting Receive Mask ----------------------------------------------*/
status = SetCommMask(*handle, EV_RXCHAR); //Configure Windows to Monitor the serial device for Character Reception
if (status == FALSE)
printf("\n\n Error! in Setting CommMask");
else
printf("\n\n Setting CommMask successful");
}
void * readFromPort(void * handles)
{
bi_ports* ports;
ports = (bi_ports*) handles;
HANDLE handleFrom;
HANDLE handleTo;
handleFrom = ports->from;
handleTo = ports->to;
BOOL status;
DWORD dwEventMask; // Event mask to trigger
char TempChar; // Temporary Character
char SerialBuffer[256]; // Buffer Containing Rxed Data
DWORD NoBytesRead; // Bytes read by ReadFile()
int i = 0;
DWORD dNoOFBytestoWrite;
DWORD dNoOfBytesWritten = 0; // No of bytes written to the port
/*------------------------------------ Setting WaitComm() Event ----------------------------------------*/
while(TRUE)
{
printf("\n\n Waiting for Data Reception");
status = TRUE;//WaitCommEvent(handleFrom, &dwEventMask, NULL); //Wait for the character to be received
/*-------------------------- Program will Wait here till a Character is received ------------------------*/
if (status == FALSE)
{
printf("\n Error! in Setting WaitCommEvent()");
}
else //If WaitCommEvent()==True Read the RXed data using ReadFile();
{
printf("\n\n Characters Received\n");
do
{
status = ReadFile(handleFrom, &TempChar, sizeof(TempChar), &NoBytesRead, NULL);
SerialBuffer[i] = TempChar;
i++;
}
while (NoBytesRead > 0);
/*------------Printing the RXed String to Console----------------------*/
if(NoBytesRead > 0){
printf("\n\n ");
int j =0;
for (j = 0; j < i-1; j++) // j < i-1 to remove the dupliated last character
{
printf("%02X", (unsigned int)(unsigned char)SerialBuffer[j]);
}
dNoOFBytestoWrite = sizeof(SerialBuffer);
status = WriteFile(handleTo, // Handle to the Serialport
SerialBuffer, // Data to be written to the port
dNoOFBytestoWrite, // No of bytes to write into the port
&dNoOfBytesWritten, // No of bytes written to the port
NULL);
if (status == TRUE)
{
printf("\n\n %X - Written to port", (unsigned int)(unsigned char)SerialBuffer);
}
else
{
printf("\n\n Error %d in Writing to Serial Port",GetLastError());
}
//CloseHandle(handleTo);
i=0;
}
}
//CloseHandle(handleFrom);//Closing the Serial Port
printf("\n +==========================================+\n");
}
}

Sending AT commands to USR modem in C

I was wondering if any of you know what I'm doing wrong here? So I have this program in C, that sends AT commands to a modem. These commands have been tested on hyperterminal and work fine, but when sendind them through the modem I get, first, and "OK" for the first "AT" command, which is good, but then, upon sending the next command, the modem answers with "AT+CC"...which I have no idea what it means. Any help is appreciated.
Source:
void sendSMS(const char* port, const char* number, const char* baud)
{
HANDLE hComm;
DCB dcb;
BOOL fSuccess;
hComm = CreateFile(port, //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
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("ERROR: Cannot open serial port\r\n");
return;
}
else
printf("STATUS: Serial port opened\r\n");
// Configure PORT
// Initialize the DCB structure.
SecureZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
// Build on the current configuration by first retrieving all current
// settings.
fSuccess = GetCommState(hComm, &dcb);
if (!fSuccess)
{
// Handle the error.
printf("GetCommState failed with error %d.\n", GetLastError());
return;
}
// Fill in some DCB values and set the com state:
// 57,600 bps, 8 data bits, no parity, and 1 stop bit.
dcb.BaudRate = atoi(baud); // baud rate
dcb.ByteSize = 8; // data size, xmit and rcv
dcb.Parity = NOPARITY; // parity bit
dcb.StopBits = ONESTOPBIT; // stop bit
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fOutX = FALSE;
fSuccess = SetCommState(hComm, &dcb);
if (!fSuccess)
{
// Handle the error.
printf("SetCommState failed with error %d.\n", GetLastError());
return;
}
// Get the comm config again.
fSuccess = GetCommState(hComm, &dcb);
if (!fSuccess)
{
// Handle the error.
printf("GetCommState failed with error %d.\n", GetLastError());
return;
}
// End Config
sendATCommands(hComm, number, "This is NOT a test.");
CloseHandle(hComm);//Closing the Serial Port
}
void sendATCommands(HANDLE hComm, const char* number, const char message[])
{
char str[256];
if (!writeToPort(hComm, "AT\r\n")) //Hello modem
return;
if (!readFromPort(hComm)) // Must be OK
return;
if (!writeToPort(hComm, "AT+CMGF=1\r\n")) //Modem, prepare to send text messages
return;
if (!readFromPort(hComm)) // Must be OK again
return;
memset(str, 0, 256);
strcpy_s(str, "AT+CMGS=\"");
strcat_s(str, 256, number);
strcat_s(str, 256, "\"\r\n");
if (!writeToPort(hComm, str)) //Modem, here's the number to send the message to
return;
if (!readFromPort(hComm)) // Must be ">"
return;
memset(str, 0, 256);
strcpy_s(str, message);
strcat_s(str, 256, "^Z");
if (!writeToPort(hComm, str)) //Modem, communicate this to the number I gave you.
return;
if (!readFromPort(hComm)) // Must be CMGS: ##
return;
}
int writeToPort(HANDLE hComm, const char lpBuffer[])
{
DWORD dNoOFBytestoWrite; // No of bytes to write into the port
DWORD dNoOfBytesWritten = 0; // No of bytes written to the port
dNoOFBytestoWrite = sizeof(lpBuffer);
int Status = WriteFile(hComm, // Handle to the Serial port
lpBuffer, // Data to be written to the port
dNoOFBytestoWrite, //No of bytes to write
&dNoOfBytesWritten, //Bytes written
NULL);
if (Status == FALSE)
{
printf("ERROR: Cannot write to serial port\r\n");
}
else
printf("STATUS: Command %s \n written to port.\r\n", lpBuffer);
return Status;
}
int readFromPort(HANDLE hComm)
{
char TempChar; //Temporary character used for reading
char SerialBuffer[256];//Buffer for storing Rxed Data
DWORD NoBytesRead = 0;
int i = 0;
int status;
memset(SerialBuffer, 0, 256);
printf("STATUS: Waiting response...\r\n");
do
{
status = ReadFile(hComm, //Handle of the Serial port
&TempChar, //Temporary character
sizeof(TempChar),//Size of TempChar
&NoBytesRead, //Number of bytes read
NULL);
if (!status)
{
printf("ERROR: Cannot read from serial port\r\n");
break;
}
SerialBuffer[i] = TempChar;// Store Tempchar into buffer
i++;
}
while (NoBytesRead > 0);
if (status)
printf("PORT RESPONSE: %s \r\n", SerialBuffer);
return status;
}

UART using C in Windows

I'm trying to establish a UART interface between an external Microcontroller and Windows using C.
I'm using the following code to set up the UART Parameters and then send in a character to the designated COM port.
I'm successful in sending a character. But How do I receive one back ? The code is as follows:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <string.h>
HANDLE hSerial;
int main()
{
// OPEN SERIAL PORT AND SET INITAL UART PARAMETERS
//=================================================
DCB dcbSerialParams = {0}; COMMTIMEOUTS timeouts = {0};
fprintf(stderr, "Opening serial port...");
hSerial = CreateFile("\\\\.\\COM3", GENERIC_READ|GENERIC_WRITE, 0, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hSerial == INVALID_HANDLE_VALUE){fprintf(stderr, "Error\n");return 1;}
else {fprintf(stderr, "OK\n");}
// Set device parameters (115200 baud, 1 start bit, 1 stop bit, no parity)
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (GetCommState(hSerial, &dcbSerialParams) == 0){fprintf(stderr, "Error getting device state\n");CloseHandle(hSerial);return 1;}
dcbSerialParams.BaudRate = CBR_57600; dcbSerialParams.ByteSize = 8; dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY;
if(SetCommState(hSerial, &dcbSerialParams) == 0){fprintf(stderr, "Error setting device parameters\n");CloseHandle(hSerial);return 1;}
// Set COM port timeout settings
timeouts.ReadIntervalTimeout = 50; timeouts.ReadTotalTimeoutConstant = 50; timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50; timeouts.WriteTotalTimeoutMultiplier = 10;
if(SetCommTimeouts(hSerial, &timeouts) == 0){fprintf(stderr, "Error setting timeouts\n"); CloseHandle(hSerial); return 1;}
// SETUP AND SEND DATA FROM UART
//==============================
int VarNum=8;
char str[15];
sprintf(str,"%ld",VarNum);
DWORD bytes_written, total_bytes_written = 0;
fprintf(stderr, "Sending bytes...");
if(!WriteFile(hSerial,str, strlen(str), &bytes_written, NULL))
{
fprintf(stderr, "Error\n");
CloseHandle(hSerial);
return 1;
}
fprintf(stderr, "%d bytes written\n", bytes_written);
// CLOSE SERIAL PORT AND EXIT MAIN FUNCTION
//=========================================
fprintf(stderr, "Closing serial port...");
if (CloseHandle(hSerial) == 0){fprintf(stderr, "Error\n"); return 1;}
fprintf(stderr, "OK\n");return 0;
}
You can use ReadFile() for that:
BOOL bOk = ReadFile(hSerial, buffer, sizeof(buffer) - 1, &bytesRead, NULL);
if (bOk && (bytesRead > 0)) {
buffer[bytesRead] = '\0';
}
When reading from a serial port, ReadFile() should block until there is more data, or a timeout occurs. (this should be done in a seperate thread (in a loop), or maybe by using ReadFileEx() for asynchronous operation).
When reading from a communications device, the behavior of ReadFile is
governed by the current communication time-outs as set and retrieved
using the SetCommTimeouts and GetCommTimeouts functions. Unpredictable
results can occur if you fail to set the time-out values.
Also checkout SetCommState() and PurgeComm().

Resources