The library i used is from Teunis van Beelen’s website www.teuniz.net
For my application, i wanted to communicate with SIM900 GSM module which was connected to my PC running Ubuntu OS. The SIM900 GSM module was connected to the PC using a CP2102 USB-UART bridge.
Do remember that you need to select the right port code in the Array of ports in the library. If you dont find your port number listed there, you can add it by removing a existing entry, or even add a new one.
For me the /dev/ttyUSB5 port entry was not present so i added it below in RS232.c, because my USB converter was enumerated as /dev/ttyUSB5. You can find yours and modify the array.
In the demo code below you can see that i am sending the index value of the comports array list corresponding to my Port name.
Thank you Teunis van Beelen 🙂
{code lang:c title:"RS232.c" lines:false hidden:false} #include "rs232.h" #if defined(__linux__) || defined(__FreeBSD__) /* Linux & FreeBSD */ int Cport[38], error; struct termios new_port_settings, old_port_settings[38]; char comports[38][16]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2","/dev/ttyS3","/dev/ttyS4","/dev/ttyS5", "/dev/ttyS6","/dev/ttyS7","/dev/ttyS8","/dev/ttyS9","/dev/ttyS10","/dev/ttyS11", "/dev/ttyS12","/dev/ttyS13","/dev/ttyS14","/dev/ttyS15","/dev/ttyUSB0", "/dev/ttyUSB1","/dev/ttyUSB2","/dev/ttyUSB3","/dev/ttyUSB4","/dev/ttyUSB5", "/dev/ttyAMA0","/dev/ttyAMA1","/dev/ttyACM0","/dev/ttyACM1", "/dev/rfcomm0","/dev/rfcomm1","/dev/ircomm0","/dev/ircomm1", "/dev/cuau0","/dev/cuau1","/dev/cuau2","/dev/cuau3", "/dev/cuaU0","/dev/cuaU1","/dev/cuaU2","/dev/cuaU3"}; int RS232_OpenComport(int comport_number, int baudrate, const char *mode) { int baudr, status; if((comport_number>37)||(comport_number<0)) { printf("illegal comport number\n"); return(1); } switch(baudrate) { case 50 : baudr = B50; break; case 75 : baudr = B75; break; case 110 : baudr = B110; break; case 134 : baudr = B134; break; case 150 : baudr = B150; break; case 200 : baudr = B200; break; case 300 : baudr = B300; break; case 600 : baudr = B600; break; case 1200 : baudr = B1200; break; case 1800 : baudr = B1800; break; case 2400 : baudr = B2400; break; case 4800 : baudr = B4800; break; case 9600 : baudr = B9600; break; case 19200 : baudr = B19200; break; case 38400 : baudr = B38400; break; case 57600 : baudr = B57600; break; case 115200 : baudr = B115200; break; case 230400 : baudr = B230400; break; case 460800 : baudr = B460800; break; case 500000 : baudr = B500000; break; case 576000 : baudr = B576000; break; case 921600 : baudr = B921600; break; case 1000000 : baudr = B1000000; break; case 1152000 : baudr = B1152000; break; case 1500000 : baudr = B1500000; break; case 2000000 : baudr = B2000000; break; case 2500000 : baudr = B2500000; break; case 3000000 : baudr = B3000000; break; case 3500000 : baudr = B3500000; break; case 4000000 : baudr = B4000000; break; default : printf("invalid baudrate\n"); return(1); break; } int cbits=CS8, cpar=0, ipar=IGNPAR, bstop=0; if(strlen(mode) != 3) { printf("invalid mode \"%s\"\n", mode); return(1); } switch(mode[0]) { case '8': cbits = CS8; break; case '7': cbits = CS7; break; case '6': cbits = CS6; break; case '5': cbits = CS5; break; default : printf("invalid number of data-bits '%c'\n", mode[0]); return(1); break; } switch(mode[1]) { case 'N': case 'n': cpar = 0; ipar = IGNPAR; break; case 'E': case 'e': cpar = PARENB; ipar = INPCK; break; case 'O': case 'o': cpar = (PARENB | PARODD); ipar = INPCK; break; default : printf("invalid parity '%c'\n", mode[1]); return(1); break; } switch(mode[2]) { case '1': bstop = 0; break; case '2': bstop = CSTOPB; break; default : printf("invalid number of stop bits '%c'\n", mode[2]); return(1); break; } /* http://pubs.opengroup.org/onlinepubs/7908799/xsh/termios.h.html http://man7.org/linux/man-pages/man3/termios.3.html */ Cport[comport_number] = open(comports[comport_number], O_RDWR | O_NOCTTY | O_NDELAY); if(Cport[comport_number]==-1) { perror("unable to open comport "); return(1); } error = tcgetattr(Cport[comport_number], old_port_settings + comport_number); if(error==-1) { close(Cport[comport_number]); perror("unable to read portsettings "); return(1); } memset(&new_port_settings, 0, sizeof(new_port_settings)); /* clear the new struct */ new_port_settings.c_cflag = cbits | cpar | bstop | CLOCAL | CREAD; new_port_settings.c_iflag = ipar; new_port_settings.c_oflag = 0; new_port_settings.c_lflag = 0; new_port_settings.c_cc[VMIN] = 0; /* block untill n bytes are received */ new_port_settings.c_cc[VTIME] = 0; /* block untill a timer expires (n * 100 mSec.) */ cfsetispeed(&new_port_settings, baudr); cfsetospeed(&new_port_settings, baudr); error = tcsetattr(Cport[comport_number], TCSANOW, &new_port_settings); if(error==-1) { close(Cport[comport_number]); perror("unable to adjust portsettings "); return(1); } if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1) { perror("unable to get portstatus"); return(1); } status |= TIOCM_DTR; /* turn on DTR */ status |= TIOCM_RTS; /* turn on RTS */ if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1) { perror("unable to set portstatus"); return(1); } return(0); } int RS232_PollComport(int comport_number, unsigned char *buf, int size) { int n; n = read(Cport[comport_number], buf, size); return(n); } int RS232_SendByte(int comport_number, unsigned char byte) { int n; printf("%c",byte); n = write(Cport[comport_number], &byte, 1); if(n<0) return(1); return(0); } int RS232_SendBuf(int comport_number, unsigned char *buf, int size) { return(write(Cport[comport_number], buf, size)); } void RS232_CloseComport(int comport_number) { int status; if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1) { perror("unable to get portstatus"); } status &= ~TIOCM_DTR; /* turn off DTR */ status &= ~TIOCM_RTS; /* turn off RTS */ if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1) { perror("unable to set portstatus"); } tcsetattr(Cport[comport_number], TCSANOW, old_port_settings + comport_number); close(Cport[comport_number]); } /* Constant Description TIOCM_LE DSR (data set ready/line enable) TIOCM_DTR DTR (data terminal ready) TIO CM_RTS RTS (request to send) TIOCM_ST Secondary TXD (transmit) TIOCM_SR Secondary RXD (receive) TIOCM_CTS CTS (clear to send) TIOCM_CAR DCD (data carrier detect) TIOCM_CD see TIOCM_CAR TIOCM_RNG RNG (ring) TIOCM_RI see TIOCM_RNG TIOCM_DSR DSR (data set ready) http://man7.org/linux/man-pages/man4/tty_ioctl.4.html */ int RS232_IsDCDEnabled(int comport_number) { int status; ioctl(Cport[comport_number], TIOCMGET, &status); if(status&TIOCM_CAR) return(1); else return(0); } int RS232_IsCTSEnabled(int comport_number) { int status; ioctl(Cport[comport_number], TIOCMGET, &status); if(status&TIOCM_CTS) return(1); else return(0); } int RS232_IsDSREnabled(int comport_number) { int status; ioctl(Cport[comport_number], TIOCMGET, &status); if(status&TIOCM_DSR) return(1); else return(0); } void RS232_enableDTR(int comport_number) { int status; if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1) { perror("unable to get portstatus"); } status |= TIOCM_DTR; /* turn on DTR */ if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1) { perror("unable to set portstatus"); } } void RS232_disableDTR(int comport_number) { int status; if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1) { perror("unable to get portstatus"); } status &= ~TIOCM_DTR; /* turn off DTR */ if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1) { perror("unable to set portstatus"); } } void RS232_enableRTS(int comport_number) { int status; if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1) { perror("unable to get portstatus"); } status |= TIOCM_RTS; /* turn on RTS */ if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1) { perror("unable to set portstatus"); } } void RS232_disableRTS(int comport_number) { int status; if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1) { perror("unable to get portstatus"); } status &= ~TIOCM_RTS; /* turn off RTS */ if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1) { perror("unable to set portstatus"); } } #else /* windows */ HANDLE Cport[16]; char comports[16][10]={"\\\\.\\COM1", "\\\\.\\COM2", "\\\\.\\COM3", "\\\\.\\COM4", "\\\\.\\COM5", "\\\\.\\COM6", "\\\\.\\COM7", "\\\\.\\COM8", "\\\\.\\COM9", "\\\\.\\COM10", "\\\\.\\COM11", "\\\\.\\COM12", "\\\\.\\COM13", "\\\\.\\COM14", "\\\\.\\COM15", "\\\\.\\COM16"}; char mode_str[128]; int RS232_OpenComport(int comport_number, int baudrate, const char *mode) { if((comport_number>15)||(comport_number<0)) { printf("illegal comport number\n"); return(1); } switch(baudrate) { case 110 : strcpy(mode_str, "baud=110"); break; case 300 : strcpy(mode_str, "baud=300"); break; case 600 : strcpy(mode_str, "baud=600"); break; case 1200 : strcpy(mode_str, "baud=1200"); break; case 2400 : strcpy(mode_str, "baud=2400"); break; case 4800 : strcpy(mode_str, "baud=4800"); break; case 9600 : strcpy(mode_str, "baud=9600"); break; case 19200 : strcpy(mode_str, "baud=19200"); break; case 38400 : strcpy(mode_str, "baud=38400"); break; case 57600 : strcpy(mode_str, "baud=57600"); break; case 115200 : strcpy(mode_str, "baud=115200"); break; case 128000 : strcpy(mode_str, "baud=128000"); break; case 256000 : strcpy(mode_str, "baud=256000"); break; case 500000 : strcpy(mode_str, "baud=500000"); break; case 1000000 : strcpy(mode_str, "baud=1000000"); break; default : printf("invalid baudrate\n"); return(1); break; } if(strlen(mode) != 3) { printf("invalid mode \"%s\"\n", mode); return(1); } switch(mode[0]) { case '8': strcat(mode_str, " data=8"); break; case '7': strcat(mode_str, " data=7"); break; case '6': strcat(mode_str, " data=6"); break; case '5': strcat(mode_str, " data=5"); break; default : printf("invalid number of data-bits '%c'\n", mode[0]); return(1); break; } switch(mode[1]) { case 'N': case 'n': strcat(mode_str, " parity=n"); break; case 'E': case 'e': strcat(mode_str, " parity=e"); break; case 'O': case 'o': strcat(mode_str, " parity=o"); break; default : printf("invalid parity '%c'\n", mode[1]); return(1); break; } switch(mode[2]) { case '1': strcat(mode_str, " stop=1"); break; case '2': strcat(mode_str, " stop=2"); break; default : printf("invalid number of stop bits '%c'\n", mode[2]); return(1); break; } strcat(mode_str, " dtr=on rts=on"); /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa363145%28v=vs.85%29.aspx http://technet.microsoft.com/en-us/library/cc732236.aspx */ Cport[comport_number] = CreateFileA(comports[comport_number], GENERIC_READ|GENERIC_WRITE, 0, /* no share */ NULL, /* no security */ OPEN_EXISTING, 0, /* no threads */ NULL); /* no templates */ if(Cport[comport_number]==INVALID_HANDLE_VALUE) { printf("unable to open comport\n"); return(1); } DCB port_settings; memset(&port_settings, 0, sizeof(port_settings)); /* clear the new struct */ port_settings.DCBlength = sizeof(port_settings); if(!BuildCommDCBA(mode_str, &port_settings)) { printf("unable to set comport dcb settings\n"); CloseHandle(Cport[comport_number]); return(1); } if(!SetCommState(Cport[comport_number], &port_settings)) { printf("unable to set comport cfg settings\n"); CloseHandle(Cport[comport_number]); return(1); } COMMTIMEOUTS Cptimeouts; Cptimeouts.ReadIntervalTimeout = MAXDWORD; Cptimeouts.ReadTotalTimeoutMultiplier = 0; Cptimeouts.ReadTotalTimeoutConstant = 0; Cptimeouts.WriteTotalTimeoutMultiplier = 0; Cptimeouts.WriteTotalTimeoutConstant = 0; if(!SetCommTimeouts(Cport[comport_number], &Cptimeouts)) { printf("unable to set comport time-out settings\n"); CloseHandle(Cport[comport_number]); return(1); } return(0); } int RS232_PollComport(int comport_number, unsigned char *buf, int size) { int n; /* added the void pointer cast, otherwise gcc will complain about */ /* "warning: dereferencing type-punned pointer will break strict aliasing rules" */ ReadFile(Cport[comport_number], buf, size, (LPDWORD)((void *)&n), NULL); return(n); } int RS232_SendByte(int comport_number, unsigned char byte) { int n; WriteFile(Cport[comport_number], &byte, 1, (LPDWORD)((void *)&n), NULL); printf("%c",byte); if(n<0) return(1); return(0); } int RS232_SendBuf(int comport_number, unsigned char *buf, int size) { int n; if(WriteFile(Cport[comport_number], buf, size, (LPDWORD)((void *)&n), NULL)) { return(n); } printf("%s",buf); return(-1); } void RS232_CloseComport(int comport_number) { CloseHandle(Cport[comport_number]); } /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa363258%28v=vs.85%29.aspx */ int RS232_IsDCDEnabled(int comport_number) { int status; GetCommModemStatus(Cport[comport_number], (LPDWORD)((void *)&status)); if(status&MS_RLSD_ON) return(1); else return(0); } int RS232_IsCTSEnabled(int comport_number) { int status; GetCommMod emStatus(Cport[comport_number], (LPDWORD)((void *)&status)); if(status&MS_CTS_ON) return(1); else return(0); } int RS232_IsDSREnabled(int comport_number) { int status; GetCommModemStatus(Cport[comport_number], (LPDWORD)((void *)&status)); if(status&MS_DSR_ON) return(1); else return(0); } void RS232_enableDTR(int comport_number) { EscapeCommFunction(Cport[comport_number], SETDTR); } void RS232_disableDTR(int comport_number) { EscapeCommFunction(Cport[comport_number], CLRDTR); } void RS232_enableRTS(int comport_number) { EscapeCommFunction(Cport[comport_number], SETRTS); } void RS232_disableRTS(int comport_number) { EscapeCommFunction(Cport[comport_number], CLRRTS); } #endif void RS232_cputs(int comport_number, const char *text) /* sends a string to serial port */ { while(*text != 0) RS232_SendByte(comport_number, *(text++)); } {/code}
{code lang:c title:"RS232.h" lines:false hidden:false} #ifndef rs232_INCLUDED #define rs232_INCLUDED #ifdef __cplusplus extern "C" { #endif #include <stdio.h>
#include <string.h> #if defined(__linux__) || defined(__FreeBSD__) #include <termios.h> #include <sys/ioctl.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <limits.h> #else #include <windows.h> #endif int RS232_OpenComport(int, int, const char *); int RS232_PollComport(int, unsigned char *, int); int RS232_SendBy te(int, unsigned char); int RS232_SendBuf(int, unsigned char *, int); void RS232_CloseComport(int); void RS232_cputs(int, const char *); int RS232_IsDCDEnabled(int); int RS232_IsCTSEnabled(int); int RS232_IsDSREnabled(int); void RS232_enableDTR(int); void RS232_disableDTR(int); void RS232_enableRTS(int); void RS232_disableRTS(int); #ifdef __cplusplus } /* extern "C" */ #endif #endif {/code}
{code lang:c title:"Demo code showing how to use the library" lines:false hidden:false} #include <stdlib.h> #include <stdio.h> #ifdef _WIN32 #include <Windows.h> #else #include <unistd.h> #endif #include "rs232.h" /******************************************************************************* * Funtion name : MapForward * * * * Description : This function performs forward mapping and returns pointer * * to the start of the found data or else returns NULL pointer * * * * Arguments : 1) Poshorter to the data in which mapping is to be made * * 2) Length of the data in which mapping is to be made * * 3) Poshorter to the data points to be mapped * * 4) Length of the data points to be mapped * * * * Returns : Pointer in which result is returned * *******************************************************************************/ unsigned char * MapForward ( unsigned char *pMapData, unsigned short MapDataLength, unsigned char *pMapPoints, unsigned short MapPointsLength ) { unsigned short DataIndex; unsigned short MapPointIndex; for(DataIndex = 0; DataIndex < MapDataLength - MapPointsLength + 1; DataIndex++) { for(MapPointIndex = 0; MapPointIndex < MapPointsLength; MapPointIndex++) { if( pMapData[DataIndex + MapPointIndex] != pMapPoints[MapPointIndex]) { goto PICK_NEXT_FMAPDATA; } } return(& pMapData[DataIndex]); PICK_NEXT_FMAPDATA:; } return(NULL); } int ReadComport(int cport_nr,unsigned char *buf,int size,useconds_t count) //size=6000 { int n; n=0; usleep(count); while(1) { n = RS232_PollComport(cport_nr, buf, size); if(n > 0) { buf[n] = 0; /* always put a "null" at the end of a string! */ //for(i=0; i < n; i++) //{ //if(buf[i] < 32) /* replace unreadable control-codes by dots */ //{ // buf[i] = '.'; //} //} printf("%s\n", (char *)buf); break; } } return n; } void Resetbufer(unsigned char *buf,int size) { int i; for(i=0;i<size;i++) { buf[i] = '0'; } } /* char comports[38][16]={"/dev/ttyS0","/dev/ttyS1=2","/dev/ttyS2","/dev/ttyS3","/dev/ttyS4","/dev/ttyS5", "/dev/ttyS6","/dev/ttyS7","/dev/ttyS8","/dev/ttyS9","/dev/ttyS10","/dev/ttyS11", "/dev/ttyS12","/dev/ttyS13","/dev/ttyS14","/dev/ttyS15","/dev/ttyUSB0=16", "/dev/ttyUSB1=17","/dev/ttyUSB2=18","/dev/ttyUSB3=19","/dev/ttyUSB4=20","/dev/ttyUSB5=21", "/dev/ttyAMA0","/dev/ttyAMA1","/dev/ttyACM0","/dev/ttyACM1", "/dev/rfcomm0","/dev/rfcomm1","/dev/ircomm0","/dev/ircomm1", "/dev/cuau0","/dev/cuau1","/dev/cuau2","/dev/cuau3", "/dev/cuaU0","/dev/cuaU1","/dev/cuaU2","/dev/cuaU3"}; */ int main() { int cport_nr=21, /* /dev/ttyUSB5 Look above to get the port code. () */ bdrate=9600; /* 9600 baud */ const unsigned char OKToken[]={"OK"}; //unsigned char URL[]={"http://www.marsinnovations.in/upload.php"}; unsigned char URL[]={"http://posttestserver.com/post.php"}; unsigned char FILENAME[]={"data.txt"}; // File to be sent char mode[]={'8','N','1',0}, str[512]; unsigned char buf[6000]; int buf_SIZE=sizeof(buf); int fsize; char string[10000]; FILE *f = fopen((const char*)FILENAME, "rb"); if (f != NULL) { fseek(f, 0, SEEK_END); fsize = ftell(f); fseek(f, 0, SEEK_SET); //char *string = malloc(fsize + 1); fread(string, fsize, 1, f); fclose(f); string[fsize] = 0; printf("%s",string); } else { printf("Doesnt exist"); } if(RS232_OpenComport(cport_nr, bdrate, mode)) { printf("Can not open comport\n"); return(0); } restart: //In my case i am using a SIM900 GSM modem to communicate using serial port,
// using Linux & a CP2102 USB-UART brudge
// Send AT command to GSM modem.
RS232_cputs(cport_nr, "AT\r\n");
// Clear the buffer i am using for reading data into.
Resetbufer(buf,sizeof(buf)); // Read the data received in the serial port buffer.
ReadComport(cport_nr,buf,6000,500000); // Check if "OK" string is present in the received data
if(MapForward(buf,buf_SIZE,(unsigned char*)OKToken,2) == NULL) goto exit; // You can send individual bytes to the serial/COM port using this function
RS232_SendByte(cport_nr,0x1A); // 0x1A is a hex equivalent of Ctrl^Z key press SUCCESS: printf("SUCCESS"); return(0); exit: printf("FAILED"); return(0); } {/code}
Hoping this helps someone 🙂