gpt4 book ai didi

c++ - 收到 GSM 调制解调器响应太迟

转载 作者:行者123 更新时间:2023-11-28 05:58:25 24 4
gpt4 key购买 nike

我有一个 gsm 调制解调器,设置为:

  1. 波特率 9600
  2. 数据位 8
  3. 无奇偶校验
  4. 停止位 1
  5. 无流量控制

我的操作系统是 Ubuntu。发送 AT 命令后,我写了 sleep(2) 秒来接收答案。但是为什么 react 迟了呢?我该如何解决?
这是我读取数据的代码:

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

}

这是我没有 sleep 的输出:

open_port: succesfully open port /dev/ttyUSB0 we had sent:AT Response: AT we got :AT ATAT we had sent:AT Response:

we got :

we had sent:AT Response: O we got :O OO we had sent:AT Response: K we got :K KK we had sent:AT Response:

we got :

we had sent:AT Response: A we got :A AA we had sent:AT Response: T we got :T TT we had sent:AT Response: we got : we had sent:AT Response: A we got :A AA we had sent:AT Response: T we got :T TT we had sent:AT Aesponse: Awe got : A we had sent:AT Response: T we got :T TT we had sent:AT ATsponse: ATe got : we had sent:AT Response: A we got :A AA we had sent:AT Response: T we got :T we had sent:AT Response: OK

we got : OK

OK

OK we had sent:AT+CSMP=49,167,0,0 Response: we got : we had sent:AT+CNMI=2,2,0,1,0 Response:

we got :

we had sent:AT+CMGS=20 Response: OK

OK we got :OK

OK we had sent:0031010c918939881454270000AA06f3701bce2e03 Response: we got : Response:

O Response: K A ATsponse: T Aesponse: AT Response: T ATsponse: ATsponse: T Response: A ATsponse: T ATsponse: Response: AT+CS Response: MP=49 Response: ,167, Aesponse: 0,0 Response: T+CN Response: MI=2, Response: 2,0,1 ATsponse: ,0 Response: +CMGS Response: =20 Response: 00310 Response: 10c91893 Response: 98 Response: 81454 Response: 2700 Response: 00AA0 Response: 6f370 Response: 1bce2 Response: e03 Response: OK Response:

Response: OK Response:

OK Response:

Response: OK

Response: OK

Response: OK Response:

OK Response:

Response: OK

Response: OK

Response: OK Response:

OK Response:

Response: OK

Response: OK

Response:

Response: Response: +CUSD Response: : 0," Response: Hazin Response: e SM Response: S: 2 Response: 0 Response: 9 Ria Response: l. Et Response: ebar Response: asl Response: i Response: : 13623 Rial. Shegeftzad Response: eh sh Response: avid Response: ! Response: Response: Ba s Response: homar Response: e g Response: i Response: ry c Response: o Response: de*44 Response: 44*1# Response: tarh Response: e v Response: i Response: je kh Response: od r Response: a Response: dar Response: y Response: aft k Response: oni Response: d Response: ",15 Response:

回应: +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) 设置规范输入而不是原始输入。#原始模式

为了使用非规范模式可靠地读取行,程序应该应对在返回缓冲区中间接收到行终止符的最坏情况(而不是接收到最后一个字符的微不足道的情况) .要处理此问题,必须在读取系统调用之间维护静态缓冲区以保存部分接收的行,并在“下”行的行终止符之后保留输入。

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(3)

的 Linux 手册页

In canonical mode:

  • Input is made available line by line. An input line is available when one of the line delimiters is typed (NL, EOL, EOL2; or EOF at the startof line). Except in the case of EOF, the line delimiter is included in the buffer returned by read(2).
  • Line editing is enabled (ERASE, KILL; and if the IEXTEN flag is set: WERASE, REPRINT, LNEXT). A read(2) returns at most one line of input; if the read(2) requested fewer bytes than are available in the current line of input, then only as many bytes as requested are read, and the remaining characters will be available for a future read(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);

readstring() 中的 read() 调用将返回完整的输入行(包括 '\n' 字符)。如果调制解调器以 '\n' 和 '\r' 结束其行,请注意此配置将引入一个空行(因为每个 '\r' 将被转换为 '\n')。

请注意,当您的程序将调制解调器从命令模式切换到透明模式时,规范模式可能不合适。如果数据不是纯 ASCII 文本而是包含二进制值,则程序应在调制解调器切换模式时将端口切换到原始模式。


有关引用指南,请参阅 Serial Programming Guide for POSIX Operating Systems
Setting Terminal Modes Properly .

关于c++ - 收到 GSM 调制解调器响应太迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33730117/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com