我有一个gsm调制解调器,设置是: 1. BaudRate 9600 2.数据库8 3.没有平等 停止1 5.无流量控制 我的Os是Ubuntu。在发送AT命令后,我写了睡眠(2)秒来接收答案。但为什么反应太迟了?我该如何解决呢? 这是我读取数据的代码:
string PDUSMS::readstring(int fd)
{
int n = 0,
spot = 0;
char buf = '\0';
/* Whole response*/
char response[1024];
memset(response, '\0', sizeof response);
n=read(fd,&response,1024);
//---------------------------
if (n < 0) {
std::cout << "Error reading: " << strerror(errno) << std::endl;
}
else if (n == 0) {
std::cout << "Read nothing!" << std::endl;
}
else {
std::cout << "Response: " << response << std::endl;
}
string str(response);
return str;
//---------------------------------------------------
}
如何快速阅读。读取所有响应字符串? 这是我的所有代码:
int fd; /* File descriptor for the port */
/*
* 'open_port()' - Open serial port 1.
*
* Returns the file descriptor on success or -1 on error.
*/
int openport(void)
{
fd=open("/dev/ttyS1",O_RDWR|O_NOCTTY|O_NDELAY);
if (fd==-1)
{
perror("open_port: unable to open port\n");
return -1;
}
else
{
printf("open_port: succesfully open port /dev/ttyUSB0\n");
fcntl(fd,F_SETFL,0);
return 1;
}
}
//========================================================================
void closeport(void)
{
close(fd);
}
void configport(void)
{
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
/* Error Handling */
if ( tcgetattr ( fd, &tty ) != 0 ) {
std::cout << "Error " << errno << " from tcgetattr: " << strerror(errno) << std::endl;
}
/* Save old tty parameters */
tty_old = tty;
/* Set Baud Rate */
cfsetospeed (&tty, (speed_t)B9600);
cfsetispeed (&tty, (speed_t)B9600);
/* Setting other Port Stuff */
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] =0;// 1; // read doesn't block
tty.c_cc[VTIME] = 2;// 5; // 0.5 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
/* Make raw */
cfmakeraw(&tty);
/* Flush Port, then applies attributes */
tcflush( fd, TCIFLUSH );
if ( tcsetattr ( fd, TCSANOW, &tty ) != 0) {
std::cout << "Error " << errno << " from tcsetattr" << std::endl;
}
}
//------------------------------------------------------------
string PDUSMS::SendandReciveData(string s,int fd)
{
int i;
string o,e,t;
try
{
cout<<" we had sent:"<<s<<"\n";
SendString(s,fd);
sleep(1);
o=readstring(fd);
// for(int i=0;i<3;i++)
// if (o.find(s)!=-1)
// {
// sleep(1.5);
// o=readstring(fd);
// }
cout<< " we got :"<<o<<"\n";
i = StateStr(o, s); //remove source command from the beging of string
if (i >= 0) //-becasause the command return back to us
o = copy(o, s.length(), o.length() - s.length()); //return command to caller
}
catch(const std::exception&)
{
o = " ";
}
return o;
}
void PDUSMS::SendString(string s,int fd)
{
char buf[255];
strcpy(buf,s.c_str());
write(fd, buf, s.length());
// usleep(500);
}
string PDUSMS::readstring(int fd)
{
int n = 0,
spot = 0;
char buf = '\0';
/* Whole response*/
char response[1024];
memset(response, '\0', sizeof response);
n=read(fd,&response,1024);
//---------------------------
if (n < 0) {
std::cout << "Error reading: " << strerror(errno) << std::endl;
}
else if (n == 0) {
std::cout << "Read nothing!" << std::endl;
}
else {
std::cout << "Response: " << response << std::endl;
}
string str(response);
return str;
//---------------------------------------------------
}
bool PDUSMS::SendSMS(int fd,string Num,string Text,int MR,int CMR,int SMS_PART,int sms_id,int &sms_index,bool Delivery,bool MagicSMS,bool &Deliverd)
{
string c, o, id;
int i, l, Curr_PART, R_MR;
string SNum, SDate, STime, PDU_Data, SMSC_Num, RTime, RDate, num1;
ReceievedMessageKind PDU_Data_Type;
bool sent, deliv;
string Temp;
MagicSMS=false;
string result=" ";
result=SendandReciveData("AT+CSMP=49,167,0,0\r",fd);
result=SendandReciveData("AT+CNMI=2,2,0,1,0\r",fd);
c = "AT+CMGS="; // at commmand for s} SMS
o = EncodePDU(Num, Text, MR, CMR, SMS_PART, sms_id, Delivery, MagicSMS);
c = c + IntToStr(o.length()/ 2 - 1); //Adding length of Pdu to at command
c += "\r"; //adding <CR> to at comm &&
Temp = SendandReciveData(c,fd); //send at command to phone
o += (char)26; //add <CTRL-Z> to the PDU Text
Temp = SendandReciveData(o,fd); //S} Text To The Phone
}
这是我没有睡觉的输出:
open_port:成功打开我们发送的端口/ dev / ttyUSB0:响应:AT我们得到了:AT ATAT我们已发送:AT响应:
我们有 :
我们发送了:AT响应:我们得到了:O OO我们发送了:AT响应:K我们得到了:K KK我们已发送:AT响应:
我们有 :
我们发送了:AT响应:我们得到了:我们发送的AA:AT响应:我们得到了:T TT我们发送了:AT响应:我们得到了:我们发送了:AT响应:我们得到了:AA我们已发送:AT响应:我们得到了:T TT我们已经发送:AT Aesponse:Awe得到了:我们已发送:AT响应:我们得到了:T TT我们发送了:AT ATsponse:ATe得到了:我们发送了: AT回复:我们得到了:我们发送的AA:AT响应:我们得到了:我们已经发送了:AT响应:好的
我们得到了:好的
好
好的,我们发送了:AT + CSMP = 49,167,0,0回应:我们得到了:我们已发送:AT + CNMI = 2,2,0,1,0响应:
我们有 :
我们已发送:AT + CMGS = 20响应:好的
好的,我们得到了:好的
好的,我们已发送:0031010c918939881454270000AA06f3701bce2e03回复:我们得到:回复:
O响应:KA响应:T Aesponse:AT响应:T响应:响应:T响应:响应:T响应:响应:AT + CS响应:MP = 49响应:,167,响应:0,0响应:T + CN响应:MI = 2,响应:2,0,1响应:,0响应:+ CMGS响应:= 20响应:00310响应:10c91893响应:98响应:81454响应:2700响应:00AA0响应:6f370响应:1bce2回复:e03回复:OK回复:
回复:确定响应:
好的回应:
回复:好的
回复:好的
回复:确定响应:
好的回应:
回复:好的
回复:好的
回复:确定响应:
好的回应:
回复:好的
回复:好的
响应:
响应:响应:+ CUSD响应:: 0,“响应:Hazin响应:e SM响应:S:2响应:0响应:9 Ria响应:l。响应:ebar响应:asl响应:i响应:: 13623 Rial Shegeftzad响应:嗯sh响应:avid响应:!响应:响应:Ba s响应:homar响应:例如响应:i响应:ry c响应:o响应:de * 44响应:44 * 1#响应:tarh响应: ev回复:i回复:je kh回复:od r响应:响应:dar响应:y响应:aft k响应:oni响应:d响应:“,15响应:
回复:+ CM响应:G响应:S:21响应:8
O响应:K响应:响应:
响应:
回复:+ CUSD:回复:2
响应:
回复:+ CDS:回复:25
回复:0回复:006D回复:A回应:0C9回复:1回复:8939回复:8回复:8145回复:4回应:2751回复:1回复:16131回复:016回复:3回复:4151回复:1回复: 1613回复:1回复:0183回复:4回复:100回应:
输出似乎表明存在命令回声。要么在调制解调器处关闭回声,要么准备好每写入一个命令读取2行。
您具有非规范(又称原始)模式的串行端口设置。原始读取由字节计数和/或定时终止,这对于读取行是不可靠的。当调制解调器处于命令模式时,调制解调器将其响应作为线路发送。
因此,您的程序需要从调制解调器读取一行(这是规范输入)。 (a)将read()放在一个循环中,该循环连接输入直到接收到行终止符,或者(b)设置规范输入而不是raw。
为了使用非规范模式可靠地读取行,程序应该处理在返回缓冲区中间接收的行终止符的最坏情况(而不是接收到的最后一个字符的普通情况)。为了处理这个问题,必须在读取系统调用之间保持静态缓冲区以保持部分接收的行,并在“下一行”的行终止符之后保留输入。
static char response[1024] = {0};
static int offset = 0;
string PDUSMS::readline(int fd)
{
int n;
char line[1024];
char *nlp;
while ((nlp = strpbrk(&response[offset], "\n\r")) == NULL) {
n = read(fd, &response[offset], sizeof(response) - offset - 1);
if (n < 0) {
std::cout << "Error reading: " << strerror(errno) << std::endl;
continue;
}
offset += n;
response[offset] = '\0';
if (offset >= sizeof(response) - 1) {
nlp = &response[offset - 1];
break;
}
}
std::cout << "Response: " << response << std::endl;
/* extract a line from the buffer */
strncpy(line, response, nlp - response + 1);
line[nlp - response + 1] = '\0';
/* move remnant string to beginning */
strcpy(response, nlp + 1);
offset = strlen(response);
string str(line);
return str;
}
注意:代码未经测试,基本上是C.我不懂C ++。
根据termios的Linux手册页(3)
在规范模式中:
- 输入逐行提供。键入其中一个行分隔符(NL,EOL,EOL2;或行开头的EOF)时,输入行可用。除EOF外,行分隔符包含在read(2)返回的缓冲区中。
- 行编辑已启用(ERASE,KILL;如果设置了IEXTEN标志:WERASE,REPRINT,LNEXT)。 read(2)最多返回一行输入;如果read(2)请求的字节数少于当前输入行中可用的字节数,则只读取所请求的字节数,其余字符将可用于将来的读取(2)。
要在命令模式(而不是通用终端输入)中为调制解调器配置规范模式的串行端口,请在configport()中删除三个语句(带有注释):
tty.c_cc[VMIN] =0;// 1; // read doesn't block
tty.c_cc[VTIME] = 2;// 5; // 0.5 seconds read timeout
/* Make raw */
cfmakeraw(&tty);
(务必保留CREAD | CLOCAL设置。) 并插入新的陈述:
tty.c_iflag |= ICRNL | IGNBRK;
tty.c_iflag &= ~(IXON | IXOFF | IXANY | INLCR);
tty.c_lflag |= ICANON | ISIG | IEXTEN;
tty.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ECHOKE);
readtring()中的read()调用将返回一个完整的输入行(包括'\ n'字符)。如果调制解调器使用'\ n'和'\ r'终止其行,则要注意此配置将引入空行(因为每个'\ r'将转换为'\ n')。
请注意,当您的程序将调制解调器从命令模式切换到透明模式时,规范模式可能不合适。如果数据不是纯ASCII文本但包含二进制值,则程序应在调制解调器切换模式时将端口切换到原始模式。
有关参考指南,请参阅Serial Programming Guide for POSIX Operating Systems 和Setting Terminal Modes Properly。
关于AT命令的一些建议,在编写单行代码之前有用的知识:
所以,不要假设“立即”接收OK。它甚至可能需要几十秒!