【发布时间】:2021-09-02 16:13:48
【问题描述】:
我有一个 gsm 调制解调器,设置是:
- 波特率 9600
- 数据位 8
- 无奇偶校验
- 停止位 1
- 无流量控制
我的操作系统是 Ubuntu。发送 AT 命令后,我写了sleep(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 我们得到:AT ATAT 我们已发送:AT 响应:
我们得到了:
我们已发送:AT 响应:O 我们得到:O OO 我们已发送:AT 响应:K 我们收到了:K KK 我们已发送:AT 响应:
我们得到了:
我们已发送:AT 响应:A 我们得到:A AA 我们已发送:AT 响应:T 我们得到:T TT 我们已经发送:AT 响应:我们得到:我们已经发送:AT 回应:A 我们得到:A AA 我们已经发送:AT 回应:T 我们得到:T TT 我们 已发送:AT Aesponse:Awe got :A 我们已发送:AT Response:T we got :T TT 我们已发送:AT ATsponse: ATe got : we have sent:AT 响应: A 我们得到:A AA 我们已发送:AT 响应:T 我们得到:T 我们已发送:AT 响应:好的
我们得到了:好的
好的
好的,我们已经发送:AT+CSMP=49,167,0,0 响应:我们得到:我们有 发送:AT+CNMI=2,2,0,1,0 响应:
我们得到了:
我们已经发送:AT+CMGS=20 响应:OK
好的,我们得到了:好的
好的,我们已经发送:0031010c918939881454270000AA06f3701bce2e03 响应: 我们得到了:响应:
O 响应:K A AT 响应:T 响应:AT 响应:T AT 响应: ATsponse: T 响应: A ATsponse: T ATsponse: 响应: AT+CS 响应:MP=49 响应:,167,响应:0,0 响应:T+CN 响应: MI=2,响应:2,0,1 AT 响应:,0 响应:+CMGS 响应:=20 回复:00310 回复:10c91893 回复:98 回复:81454 响应:2700 响应:00AA0 响应:6f370 响应:1bce2 响应:e03 响应:OK 响应:
响应:OK 响应:
OK 响应:
响应:好的
响应:好的
响应:OK 响应:
OK 响应:
响应:好的
响应:好的
响应:OK 响应:
OK 响应:
响应:好的
响应:好的
回复:
回应:回应: +CUSD 响应::0," 响应:Hazin 响应:e SM 响应:S:2 响应:0 响应:9 Ria 响应:l. Et 响应:ebar 响应: asl 响应:i 响应::13623 里亚尔。 Shegeftzad 回应:嗯 sh 回应:狂热 回应:!响应: 响应: Ba s 响应: homar 响应:e g 响应:i 响应:ry c 响应:o 响应:de*44 响应:44*1# 响应:tarh 响应:e v 响应:i 响应:je kh 响应:od r 响应:a 响应: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秒?如果根本没有睡眠会发生什么(假设您使用阻塞读取)?
-
您发送的是哪个 AT 命令?你的串口有什么超时?睡眠在哪里? (因为它没有出现在您发布的代码中)
-
@sawdust 。是的,抱歉太慢了。当我评论睡眠时(2)。当我向我的方法发送“AT+CMGS=..”时。首先写入它,然后休眠,然后读取端口并返回,然后我发送另一个 AT 命令。但它响应第一种方法等等。并且响应有延迟..什么是阻塞读取?
-
@Mats Petersson:这些 AT 命令发送 PDU 短信:“AT+CSMP”、“AT+CNMI”、“AT+CMGS”和 pdu 格式..这是我的超时端口:tty。 c_cc[VMIN] =0;// 1; // 读取不会阻塞 tty.c_cc[VTIME] = 2;//2 秒。并且睡眠是在读方法之前的写方法之后。
-
您已经为非规范(又名原始)模式设置了串行端口。原始读取由字节计数和/或计时终止,这对于读取一行是不可靠的。但是您实际上需要从调制解调器中读取一行(这是规范输入)。由于明显的命令回显,可能会读取 2 行。要么设置为规范输入而不是原始输入,要么在 readstring() 中将 read() 放在一个循环中,该循环连接输入直到收到行终止符。要么关闭调制解调器上的回显,要么准备每个写入的命令读取 2 行。
标签: c++ serial-port gsm