USB to Serial (to and fro) communication using C# and C language - c#
This is the 1st time am posting my query. I am in need of help. Any help is appreciated.
As i agree that i have given my prob as long story. But am sorry i am not getting how to make it short and my intention is give complete information regarding my prob.
Problem :
I have to communicate between two laptops using USB-to-Serial adapter on windows platform. I have written 2 programs one for sending and another for receiving. Programs were written in both C and C# programming languages.
Using C language :
I am able to successfully communicate using C-Programs mentioned below. But the problem is speed. It takes around 1 hour(60min) for just to pass 150MB. Anyone plz help me in improving the performance of this programs or you may suggest me other approaches which is robust and give high performance. I also mention some comments along with programs for self understanding.
Sender File on laptop with serial port :
#include <stdio.h>
#include <bios.h>
#include <conio.h>
#define COM1 0
#define DATA_READY 0x100
#define TRUE 1
#define FALSE 0
#define SETTINGS ( 0xE0 | 0x03 | 0x00 | 0x00)
int main(void)
{
int in, out, status, DONE = FALSE,i=0;
char c;
FILE *fp,*fp1;
unsigned long count = 0,shiftcount = 0;
clrscr();
fp = fopen("C:/TC/pic.jpg","rb"); //opened for reading actual content
fp1 = fopen("C:/TC/pic.jpg","rb"); //opened for reading the size of file
fseek(fp1,0L,2);
count = ftell(fp1) + 1; // file size
bioscom(0, SETTINGS, COM1); // initializing the port
printf("No. of Characters = %lu\n",count);
// since bioscom function can send or receive only 8bits at a time, am sending file size in
4 rounds so that we can send at max of 4GB file.
bioscom(1,count,COM1); // sneding 1st lower 8bits
bioscom(1,count>>8,COM1); // sending 2nd set of lower 8bits
bioscom(1,count>>16,COM1); // sending 3rd set of lower 8bits
bioscom(1,count>>24,COM1); // sending upper 8 bits
cprintf("... BIOSCOM [ESC] to exit ...\n");
while (!DONE)
{
status = bioscom(3, 0, COM1);// get the status of port
//printf("%d",status);
if (status & DATA_READY) //checks if data is ready
{
out = bioscom(2, 0, COM1); // receives the ack
if(!feof(fp))
{
c = fgetc(fp); //read character by character from file
bioscom(1,c,COM1);//send character to receiver
putch(c);//display
}
}
//to interrupt
if (kbhit())
{
if ((in = getch()) == '\x1B')
DONE = TRUE;
}
}
fclose(fp);
return 0;
}
Receiving file on laptop with USB port :
#include <stdio.h>
#include <bios.h>
#include <conio.h>
#define COM4 3
#define DATA_READY 0x100
#define TRUE 1
#define FALSE 0
#define SETTINGS ( 0xE0 | 0x03 | 0x00 | 0x00)
int main(void)
{
int in, out, status;
char c;
FILE *fp;
unsigned long shiftcount1=0,shiftcount2=0,shiftcount3=0,shiftcount4=0;
unsigned long count = 0, DONE = 1;
clrscr();
fp = fopen("C:/TC/pic1.jpg","wb");// file opened for writing
bioscom(0, SETTINGS, COM4);//initialize tyhe port
cprintf("... BIOSCOM [ESC] to exit ...\n");
//receives all the 32 bits of file size sent from sender
shiftcount1 = bioscom(2,0,COM4);
shiftcount2 = bioscom(2,0,COM4);
shiftcount3 = bioscom(2,0,COM4);
shiftcount4 = bioscom(2,0,COM4);
//send an ack
bioscom(1,'x',COM4);
count = shiftcount1 | (shiftcount2<<8) | (shiftcount3<<16) | (shiftcount4<<24);
printf("shift4 = %lu\tshift3 = %lu\tshift2 = %lu\tshift1 = %lu\n",shiftcount4,shiftcount3,shiftcount2,shiftcount1);
printf("File Size = %lu\n",count);
//loop till the size of the file
while (DONE < count)
{
status = bioscom(3, 0, COM4);// check the status
// printf("%d",status);
if (status & DATA_READY)//check for data ready at the port
{
out = bioscom(2, 0, COM4);//receive the data
DONE++;
fputc(out,fp);
putch(out);
bioscom(1,'x',COM4);//send an ack
}
if (kbhit())
{
if ((in = getch()) == '\x1B')
break;
}
}
fclose(fp);
return 0;
}
Sender file on laptop with USB port:
#include <stdio.h>
#include <bios.h>
#include <conio.h>
#include<dos.h>
#include<stdlib.h>
#include<time.h>
#define RTS 0x02
#define COM1 0
#define COM4 3
#define CURRCOM COM4
#define DATA_READY 0x100
#define TRUE 1
#define FALSE 0
#define SETTINGS ( 0xE0 | 0x03 | 0x00 | 0x00)
int main(void)
{
int in, out, status, DONE = FALSE,nextfile = 1;
char c;
FILE *fp,*fp1;
unsigned long count = 0,shiftcount = 0;
clock_t start,end;
start = clock();
clrscr();
fp = fopen("C:/TC/pic.jpg","rb");
fp1 = fopen("C:/TC/pic.jpg","rb");
fseek(fp1,0L,2);
count = ftell(fp1) + 1;
bioscom(0, SETTINGS, CURRCOM);
/* while(!feof(fp1))
{
c = fgetc(fp1);
count++;
} */
printf("No. of Cheracters = %lu\n",count);
bioscom(1,count,CURRCOM);
bioscom(1,count>>8,CURRCOM);
bioscom(1,count>>16,CURRCOM);
bioscom(1,count>>24,CURRCOM);
cprintf("\n... BIOSCOM [ESC] to exit ...\n");
while (!DONE)
{
status = bioscom(3, 0, CURRCOM);
if (status & DATA_READY)
{
out = bioscom(2,0,CURRCOM);
if(!feof(fp))
{
c = fgetc(fp);
bioscom(1,c,CURRCOM);
putch(c);
}
}
if (kbhit())
{
if ((in = getch()) == '\x1B')
DONE = TRUE;
}
}
fclose(fp);
end = clock();
printf("\nTotal time = %d\n",(end - start)/CLK_TCK);
return 0;
}
Receiver file on laptop with serial port :
#include <stdio.h>
#include <bios.h>
#include <conio.h>
#include<time.h>
#define COM1 0
#define DATA_READY 0x100
#define TRUE 1
#define FALSE 0
#define SETTINGS ( 0xE0 | 0x03 | 0x00 | 0x00)
int main(void)
{
int in, out, status;
char c;
FILE *fp;
int y = 0,esc;
unsigned long count=0,shiftcount1 = 0,shiftcount2 = 0,shiftcount3 = 0,shiftcount4 = 0, DONE = 1;
clock_t start,end;
start = clock();
clrscr();
fp = fopen("C:/TC/pic1.jpg","wb");
bioscom(0, SETTINGS, COM1);
cprintf("... BIOSCOM [ESC] to exit ...\n");
shiftcount1 = bioscom(2,0,COM1);
shiftcount2 = bioscom(2,0,COM1);
shiftcount3 = bioscom(2,0,COM1);
shiftcount4 = bioscom(2,0,COM1);
bioscom(1,'x',COM1);
count = shiftcount1 | (shiftcount2<<8) | (shiftcount3<<16) | (shiftcount4<<24);
printf("shift4 = %lu\tshift3 = %lu\tshift2 = %lu\t shift1 = %lu\n",shiftcount4,shiftcount3,shiftcount2,shiftcount1);
printf("file size = %lu\n",count);
while (DONE < count)
{
status = bioscom(3, 0, COM1);
//printf("%d",status);
if (status & DATA_READY)
{
out = bioscom(2, 0, COM1);
DONE++;
fputc(out,fp);
putch(out);
bioscom(1,'x',COM1);
}
if (kbhit())
{
if ((in = getch()) == '\x1B')
break;
}
}
fclose(fp);
end = clock();
printf("\nTotal time = %f\n",(end - start)/CLK_TCK);
return 0;
}
The above 4 programs behaves as, sender send a character and receives an ack for every character. I have followed this approach, bcoz other approaches were not working fine (in the sense the complete data is not sent, the amount of data sent is not judgeable, bcoz it will different every tym). when i used this approach it worked fine.
Using C# language :
Below two programs are written in C# using visual studio. I have used SerilaPort class , its properties and methods for communication. Using this, am able to communicate text and xml files on both the sides successfully.Also image files with .jpg extention, can be transferred from USB to serial end withot any loss of data(successful transmission), but if i transfer from serial to usb end, am able receive image with some data loss, even with the data loss am able to see the image.
Sender file on laptop with serial port :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.IO;
using System.Threading;
namespace Communication
{
class Program
{
static void Main(string[] args)
{
string name;
string message;
StringComparer stringComparer = StringComparer.OrdinalIgnoreCase;
//Thread readThread = new Thread(Read);
FileStream fs = new FileStream("C:/text.xml", FileMode.Open);
//StreamReader sr = new StreamReader(fs);
BinaryReader br = new BinaryReader(fs);
// Create a new SerialPort object with default settings.
SerialPort _serialPort = new SerialPort();
// Allow the user to set the appropriate properties.
_serialPort.PortName = "COM1";
_serialPort.BaudRate = 115200;
_serialPort.Parity = Parity.None;
_serialPort.DataBits = 8;
_serialPort.StopBits = StopBits.One;
_serialPort.Handshake = Handshake.None;
// Set the read/write timeouts
_serialPort.ReadTimeout = 500;
_serialPort.WriteTimeout = 500;
_serialPort.Open();
bool _continue = true;
//readThread.Start();
int len = (int)fs.Length;
char[] data = new char[len+1];
br.Read(data, 0, len);
for (int i = 0; i < len+1; i++)
{
_serialPort.Write(data, i, 1);
//Console.Write(data,i,1);
}
br.Close();
fs.Close();
_serialPort.Close();
}
}
}
Receiver file on laptop with USB port :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.IO;
using System.Threading;
using System.Collections;
namespace Communication
{
class Program
{
static void Main(string[] args)
{
SerialComm comm = new SerialComm();
comm.Init();
comm.ReadSerial();
comm.WriteToFile();
comm.ResClose();
Console.ReadKey();
}
}
class SerialComm
{
FileStream fs = null;
BinaryWriter file = null;
ArrayList al = null;
public Boolean Init()
{
if (fs == null)
{
fs = new FileStream("C:/text1.txt", FileMode.OpenOrCreate);
}
if (file == null)
{
file = new BinaryWriter(fs);
}
if (al == null)
{
al = new ArrayList();
}
return true;
}
public void ResClose()
{
file.Close();
fs.Close();
}
public Boolean ReadSerial()
{
SerialPort port;
StreamWriter sw;
ConsoleKeyInfo ck;
port = new SerialPort();
port.PortName = "COM4";
port.BaudRate = 115200;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.Handshake = Handshake.None;
port.Open();
port.BaseStream.Flush();
port.DiscardInBuffer();
int c = 1;
while (c != 0)
{
c = port.ReadByte();
al.Add((byte)c);
}
return true;
}
public void WriteToFile()
{
int i = 0;
byte[] message = al.ToArray(typeof(byte)) as byte[];
file.Write(message, 0, message.Length - 1);
}
}
}
Please help me.
Thanks in advance.
Transmission speed:
Serial ports are simple, not fast. I am assuming that you are using 230kbps which is already more than many hardware can handle. Compression is only thing that might help, but compressing already compressed data (like .mp3) won't help much.
Data loss:
Serial ports are simple, not robust. Data loss is common, and only thing you can do about it is to have protocol to detect errors on incoming frames, and have ability to retry send if there is an error.
Conclusion:
Use TCP/IP instead.
Way too long a question. I've found only one actual question, and that's the performance bit.
Just use Ethernet or WiFi. "Serial port" (you probably mean RS-232) speeds are low. 0.1 Mbit/second is considered fast by RS-232 standards. You clock 1200 Mbit/3600 seconds, which is 0.3 Mbit/second. That is ultra-fast. I'm in fact surprised that you achieve that, your C# program is explicitly setting the speed to 0.1 Mbit/second.
Related
Serial port communication issue from c# to c application
I am writing a c#application which communicates with a device c application. I am trying to write data from the c# application to c application over the serial port and vice versa. I am trying to write some sample data using the following code. C# using PORT = System.IO.Port.SerialPort; PORT p = new PORT("COM4", 9600, System.IO.Ports.Parity.None, 8, System.IO.Ports.StopBits.One); string data="HELLO"; //String to byte[] conversion byte[] byt_buff = new byte[data.Length]; byt_buff = Encoding.ASCII.GetBytes(data); p.Open(); p.DiscardOutBuffer(); p.Write(byt_buff, 0, byt_buff.Length); p.Close(); The c application running on the device has the following code. C #include<stdio.h> #include <poll.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include<stdint.h> #include<string.h> #define USB_DEV_NODE "usb.dat" #define MAX_SIZE 20 int main() { int fd; int ret_poll; int ret_read; struct pollfd pollfd; char buf[MAX_SIZE]; int i = 0; pollfd.events = POLLIN; fd = open(USB_DEV_NODE, O_RDWR | O_NOCTTY); pollfd.fd = fd; while (1) { ret_poll = poll( &pollfd, 1, -1); if( ret_poll == -1 ) { printf("Gpio_poll poll failed\r\n"); close(fd); }else{ if (pollfd.revents & POLLIN ) { ret_read = read(fd, buf, MAX_SIZE); buf[ret_read]=0; if(ret_read > 0) { for(i=0;i<ret_read ; i++) { printf("BUF[%d]=%c\n",i,buf[i]); } } } } } return 0; } But I am failing to receive the data written as byte[],No data is recieved. Instead if I write data as a string using p.WriteLine("HELLO"); it will be recieved. Please help.
C#: Waiting for specific character sent from RS485
In my app I am sending data to microcontroller. I send data, microcontroller do program, and send character ("K"). My application should wait for this character.After receiving this char, it should send data again. I got problem with receiving this character. Is function BytesToRead right to reading character? My program always fall when it reach this my function wait static void wait() { SerialPort COMport = new SerialPort(); int znak; COMport.PortName = "COM6"; // COMport.BaudRate = 1200; COMport.DataBits = 8; COMport.Parity = Parity.None; COMport.StopBits = StopBits.One; COMport.Open(); do { znak = COMport.BytesToRead; } while (znak != 75); // ASCII K = 75 COMport.Close(); return; }
The BytesToRead property of the COMport returns the number of characters that have been received by the COMport so your loop will continue until there are exactly 75 characters read. Take a look at the documentation for the SerialPort class. It will show you a good example of how to read/write characters from/to your COMport.
Why not just use while(COMport.ReadChar() != 'K') { /* Do Stuff */ }?
c# named pipe two way communcation
I have two programs written in c++ and c#.I want to establish a two way communication using named-pipe between them. The C# client program can be connected to the named-pipe created by c++ server program.But nothing received in both ends. Here is the c++ part (Server): #include <iostream> #include <windows.h> #include <stdlib.h> #define UNICODE using namespace std; HANDLE hnamedPipe = INVALID_HANDLE_VALUE; BOOL Finished =false; HANDLE hThread = NULL; unsigned long __stdcall CS_RcvThr(void * pParam) ; int main(int argc, char **argv) { hnamedPipe = CreateNamedPipe( "\\\\.\\pipe\\vikeyP", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE| PIPE_READMODE_MESSAGE| PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL); if(hnamedPipe == INVALID_HANDLE_VALUE) { cout << "Failed" << endl; } while (true) { cout<< "Waiting for client"<< endl; if(!ConnectNamedPipe(hnamedPipe,NULL)) { if(ERROR_PIPE_CONNECTED != GetLastError()) { cout << "FAIL"<< endl; } } else { cout<<"Connected!"<<endl; hThread = CreateThread( NULL, 0, &CS_RcvThr, NULL, 0, NULL); if(hThread) cout<<"read thread created"<<endl; else cout<<"cant crat rd thed\n"; break; } } while(1) { cout<<"lst loop"<<endl; //Send over the message char chResponse[] = "hello\n"; DWORD cbResponse,cbWritten; cbResponse = sizeof(chResponse); if (!WriteFile( hnamedPipe, chResponse, cbResponse, &cbWritten, NULL)) { wprintf(L"failiure w/err 0x%08lx\n",GetLastError); } cout<<"Sent bytes :)" << endl; Sleep(10); } } unsigned long __stdcall CS_RcvThr(void * pParam) { BOOL fSuccess; char chBuf[100]; DWORD dwBytesToWrite = (DWORD)strlen(chBuf); DWORD cbRead; int i; while (1) { fSuccess =ReadFile( hnamedPipe,chBuf,dwBytesToWrite,&cbRead, NULL); if (fSuccess) { printf("C++ App: Received %d Bytes : ",cbRead); for(i=0;i<cbRead;i++) printf("%c",chBuf[i]); printf("\n"); } if (! fSuccess && GetLastError() != ERROR_MORE_DATA) { printf("Can't Read\n"); if(Finished) break; } } } Here is the C# part (Client): private Thread vikeyClientThread; public void ThreadStartClient() { Console.WriteLine("Thread client started ID ={0} name = {1} " , Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.Name); using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "vikeyP")) { // The connect function will indefinately wait for the pipe to become available // If that is not acceptable specify a maximum waiting time (in ms) Console.WriteLine("Connecting to ViKEY server..."); pipeStream.Connect(); Console.WriteLine("Connected :)"); //Write from client to server StreamWriter sw = new StreamWriter(pipeStream); while (true) { //Read server reply StreamReader sr = new StreamReader(pipeStream); string temp = ""; sw.WriteLine(System.DateTime.Now); byte[] c = new byte[200]; temp = sr.ReadLine(); pipeStream.Read(c, 0, c.Length); Console.WriteLine("RX =:{0}", Encoding.UTF8.GetString(c, 0, c.Length)); Thread.Sleep(500); } } Console.WriteLine("Vikey pipe Closed"); Console.WriteLine("Thread with ID ={0} name = {1} is closed.", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.Name); }
You've set the server side up as a message type vs byte type. If you want to read an arbitrary number of bytes, you'll need to use a byte type named pipe. You're wrapping the stream in 2 objects one StreamReader and one StreamWriter. Don't do that, just use a Stream. You're trying to read by line, don't do that either. Instead send the number of bytes to read followed by the bytes. On the client side you'll read the byte count then create a buffer big enough then read. If it's text data you then would use an encoder (probably ASCII) to translate it back into a C# string. Your while(true) should instead detect when the server has closed the pipe. You should probably look into using an asynchronous named pipe.
Getting Callerid from serial port with Conexant USB CX93010 modem?
I have a C# code but it doesn't takes a CallerID from dial up modem connected to USB port when I connect line to phone. It gets CallerID but in program run and in reading line I have just RING nothing else. This is my code: public partial class Form1 : XtraForm { public Form1() { InitializeComponent(); } SerialPort sp ; private void simpleButton1_Click(object sender, EventArgs e) { sp = new SerialPort(textEdit1.Text); sp.NewLine = "\r\n"; sp.Parity = Parity.None; sp.DataBits = 8; sp.StopBits = StopBits.One; sp.DtrEnable = true; sp.WriteBufferSize = 1024; sp.Open(); sp.WriteLine("AT+VCID=1"); sp.RtsEnable = true; timer1.Start(); } void sp_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { sp.Close(); } private void timer1_Tick(object sender, EventArgs e) { memoEdit1.Text += "\n" + sp.ReadExisting(); } private void simpleButton2_Click(object sender, EventArgs e) { sp.Close(); }
Conexant USB CX93010 ACF Modem don't have FSK protocol
When your modem supports caller id then make use of AT+CLIP=1. This will cause unsolicited +CLIP messages to be displayed when the modem is called. The +CLIP unsolicited messages are usually formulated as follows: +CLIP: <number>,<type>,,,,<cli validity> Where <number> is a string containing the number in a format defined by <type>. <type> of address octet which for example for international numbers is 145. <cli validity> determines whether the number was withheld etc.
I'm posting the code below based on some testing I was doing with the Conexant USB CX93010. The code below is in C (rather than C#) and runs on Linux (rather than Windows). But it should provide a good baseline for a C# program. The code is based on another Stack Overflow answer written by Sawdust, and it has test results from the program. You can also find a comprehensive AT command set for Conexant modems at http://www.arcelect.com. It is dated from 2001, but it has more AT commands for the modems than I found elsewhere on the web. Here is the code. #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <termios.h> #include <unistd.h> #define DISPLAY_STRING 1 int set_interface_attribs(int fd, int speed) { struct termios tty; if (tcgetattr(fd, &tty) < 0) { printf("Error from tcgetattr: %s\n", strerror(errno)); return -1; } cfmakeraw (&tty); cfsetospeed(&tty, (speed_t)speed); cfsetispeed(&tty, (speed_t)speed); if (tcsetattr(fd, TCSANOW, &tty) != 0) { printf("Error from tcsetattr: %s\n", strerror(errno)); return -1; } return 0; } void write_command(int fd, const void* cmd, size_t len) { if (len == ~(size_t)0) len = strlen((const char*)cmd); printf("Send %d: %s\n", (int)len, (const char*)cmd); int wlen = write(fd, cmd, len); if (wlen != len) { printf("Error from write: %d, %d\n", wlen, errno); } tcdrain(fd); /* delay for output */ } void read_response(int fd) { char buf[256]; int rlen = read(fd, buf, sizeof(buf) - 1); if (rlen > 0) { #ifdef DISPLAY_STRING buf[rlen] = 0; printf("Read %d: \"%s\"\n", rlen, buf); #else /* display hex */ unsigned char *p; printf("Read %d:", rlen); for (p = buf; rlen-- > 0; p++) printf(" 0x%x", *p); printf("\n"); #endif } else if (rlen < 0) { printf("Error from read: %d: %s\n", rlen, strerror(errno)); } else { /* rlen == 0 */ printf("Timeout from read\n"); } } int main(int argc, char* argv[]) { int fd; const char portname[] = "/dev/ttyACM0"; fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { printf("Error opening %s: %s\n", portname, strerror(errno)); return -1; } /*baudrate 115200, 8 bits, no parity, 1 stop bit */ set_interface_attribs(fd, B115200); write_command(fd, "ATZ\r", 4); /* Reset */ read_response(fd); write_command(fd, "ATE0\r", -1); /* Echo off */ read_response(fd); write_command(fd, "AT+VCID=?\r", -1); /* Query CallerID caps */ read_response(fd); write_command(fd, "AT+CLIP=?\r", -1); /* Query CallerID caps */ read_response(fd); write_command(fd, "AT+VCID=1\r", -1); /* Set CallerID */ read_response(fd); printf("Entering loop, CTRL+C to break...\n\n"); while (1) { read_response(fd); } return 0; } Here are the test results using a cell phone. I changed the name and phone number; other wise it is the exact output of the program. $ sudo ./modem.exe Send 4: ATZ Read 6: " OK " Send 5: ATE0 Read 11: "ATE0 OK " Send 10: AT+VCID=? Read 15: " (0-2) OK " Send 10: AT+CLIP=? Read 9: " ERROR " Send 10: AT+VCID=1 Read 6: " OK " Entering loop, CTRL+C to break... Read 8: " RING " Read 67: " DATE = 0214 TIME = 2116 NMBR = 2025551212 NAME = JANE DOE " Read 8: " RING " Read 67: " DATE = 0214 TIME = 2116 NMBR = 2025551212 NAME = JANE DOE " Read 8: " RING " Read 8: " RING " Read 8: " RING " Also, you can send an AT+GSR to get the real modem revision instead of what Windows provides (which appears to be a little inaccurate): Send 7: AT+GMR Read 44: "AT+GMR +GMR: CX93001-EIS_V0.2013-V92 OK"
You must set Country of Installation to B5 by AT+GCI=B5 I got it after a three weeks of investigations (It may defer in your country it can be 00 or B4 or B5 but B5 for works for most of land lines): Then enable CID reporting by AT+VCID=1 or AT+VCID=2 as it said in manual: And then it works flawlessly: And this is my working code based on yours: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace CIDResolver { public partial class Form1 : Form { public Form1() { InitializeComponent(); } SerialPort sp; private void Connect_click(object sender, EventArgs e) { sp = new SerialPort(textEdit1.Text); sp.BaudRate = 11500; sp.NewLine = "\r\n"; sp.Open(); sp.WriteLine("AT+GCI=B5"); // can be 00 or B4 or B5 sp.WriteLine("AT+VCID=1"); sp.DataReceived += new SerialDataReceivedEventHandler((object _s, SerialDataReceivedEventArgs _e) => { string newData = sp.ReadExisting(); consoleOut.Invoke((MethodInvoker)delegate { // Running on the UI thread consoleOut.Text += newData+ "\r\n"; }); }); } private void disConnectBtn_Click(object sender, EventArgs e) { sp.Close(); } private void Form1_FormClosed_1(object sender, FormClosedEventArgs e) { sp.Close(); } } }
Convert serial port application from C# to C in visual studio (ERROR_INVALID_PARAMETER) 87
I am trying to write an app in C to communication with a device through a COM port. I am able to send data using Docklight (hyper terminal like program) with the following settings and I can verify that I am receiving it through Itronix LogicPort Logic Analyzer. Baud rate:9600 Parity:None Byte Size:8 Stop bits:1 I am having 2 problems with my C program: 1) sometimes CreateFile returns INVALID_HANDLE_VALUE and the other problem I can't seem to get by is that GetCommState() SetCommState() SetCommTimeouts() always return ERROR_INVALID_PARAMETER 87 (0x57) Since I couldn't get past this problem, I tried a program in C# and that works just fine, but my program must be in C to communicate with the rest of my code. This program also communicates with other programs in C through sockets. in Device Manager the device I want to talk to is listed as COM6 under Ports(COM & LPT) any help would be appreciated! Below is the code for both programs: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO.Ports; namespace WindowsFormsApplication1 { public partial class Form1 : Form { byte[] TxBuffer = new byte[20]; SerialPort CommPort = new SerialPort("COM6", 9600, Parity.None, 8, StopBits.One); public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { CommPort.Open(); TxBuffer[0] = (byte)'|'; TxBuffer[1] = 0; TxBuffer[2] = 0; TxBuffer[3] = 0; TxBuffer[4] = 1; TxBuffer[5] = 100; TxBuffer[6] = 1; TxBuffer[7] = 6; TxBuffer[8] = (byte)'|'; TxBuffer[9] = 1; } private void button1_Click(object sender, EventArgs e) { CommPort.Write(TxBuffer, 0, 10); } } } and the C code is: somewhere struct serial_dev { HANDLE hSerial; }; struct serial_dev sdev; //global //somewhere in main if (init_serial(&sdev, com_file) == -1) return -1; write_ser(&sdev, buffer, buf_size); close_serial(&sdev); // in serial.c int init_serial(struct serial_dev *sdev, char *port_name) { DCB dcbSerialParams; COMMTIMEOUTS timeouts; int error = 0; memset(&dcbSerialParams, 0, sizeof(dcbSerialParams)); memset(&timeouts, 0, sizeof(timeouts)); sdev->hSerial = CreateFile("COM6", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (sdev->hSerial == INVALID_HANDLE_VALUE) { error = GetLastError(); close_serial(sdev); fprintf(stderr, "error: could not open serial port (error:%d)\n", error); return -1; } memset(&dcbSerialParams, 0, sizeof(dcbSerialParams)); dcbSerialParams.DCBlength = sizeof(dcbSerialParams); if (!GetCommState(sdev->hSerial, &dcbSerialParams)) { close_serial(sdev); error = GetLastError(); fprintf(stderr, "error: could not get serial port state (%d)\n", error); return -1; } dcbSerialParams.BaudRate = CBR_9600; dcbSerialParams.ByteSize = 8; dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; if (!SetCommState(sdev->hSerial, &dcbSerialParams)) { close_serial(sdev); error = GetLastError(); fprintf(stderr, "error: could not set serial port state (%d)\n", error); return -1; } timeouts.ReadIntervalTimeout = 50; timeouts.ReadTotalTimeoutConstant = 200; timeouts.ReadTotalTimeoutMultiplier = 10; timeouts.WriteTotalTimeoutConstant = 50; timeouts.WriteTotalTimeoutMultiplier = 10; if (!SetCommTimeouts(sdev->hSerial, &timeouts)) { close_serial(sdev); error = GetLastError(); fprintf(stderr, "error: could not set serial port timeouts (%d)\n", error); return -1; } return 0; } void close_serial(struct serial_dev *sdev) { CloseHandle(sdev->hSerial); } int write_ser(struct serial_dev *sdev, void *buf, size_t len) { DWORD written; BOOL success; success = WriteFile(sdev->hSerial, buf, len, &written, NULL); if(!success || written == 0) { printf("error writing to serial\n"); return -1; } printf("writing to serial OK!\n"); return written; }
guys I figured it out... I removed the "UNICODE" and "_UNICODE" preprocessor macros from my project settings and set it to "Not Set" found answer here: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/1a77c595-10a5-4f14-8512-c67535c53a08/