在使用AT指令给4G模块发信息的时候,我们需要借助到Linux中busybox的microcom工具,该工具用来实现与串口之间的通信,那怎么自己实现编程跟4G模块发信息,以及接收信息把想要的信息放入结构体呢?
编程思想:
在/dev下找到4G模块的设备描述符,然后按照“Linux一切皆文件”的思想,打开这个设备,初始化串口配置后,用write发送AT的指令给4G模块通信,然后用read接收,再把接收到想要的数据分割出来放到结构体里面去。
1.在/dev下找到4G模块的设备描述符,我的是/dev/ttyACM2
2.打开这个设备
gg_G4_INFO->deviceFd = open(gg_G4_INFO->deviceName,O_RDWR | O_NOCTTY | O_NONBLOCK);
if(gg_G4_INFO->deviceFd < 0)
{
printf("Open %s failed,fd=%d\n",gg_G4_INFO->deviceName,gg_G4_INFO->deviceFd);
goto EXIT;
}
if((retval = fcntl(gg_G4_INFO->deviceFd,F_SETFL,0)) < 0)
{
printf("%s,Fcntl check faile.\n",__func__);
goto EXIT;
}
}
3.初始化串口
一些函数介绍:
为了便于通过程序来获得和修改终端参数,Linux还提供了tcgetattr函数和tcsetattr函数。tcgetattr用于获取终端的相关参数,而tcsetattr函数用于设置终端参数。
<termios.h>
1.tcgetattr函数:
函数原型:int tcgetattr(int fd, struct termios *termios_p);
功能:
tcgetattr函数用于获取与终端相关的参数。参数fd为终端的文件描述符,返回的结果保存在termios 结构体中
其成员:
tcflag_t c_iflag;
tcflag_t c_oflag;
tcflag_t c_cflag;
tcflag_t c_lflag;
cc_t c_cc[NCCS];
返回值:成功返回 0,失败返回 -1
2.tcsetattr函数:
函数原型:int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);
功能:
tcsetattr函数用于设置终端参数。函数在成功的时候返回0,失败的时候返回-1,并设置errno的值。
参数fd为打开的终端文件描述符,参数optional_actions用于控制修改起作用的时间,而结构体termios_p中保存了要修改的参数。optional_actions可以取如下的值。
TCSANOW:不等数据传输完毕就立即改变属性。
TCSADRAIN:等待所有数据传输结束才改变属性。
TCSAFLUSH:等待所有数据传输结束,清空输入输出缓冲区才改变属性。
错误信息:
EBADF:非法的文件描述符。
EINTR:tcsetattr函数调用被信号中断。
EINVAL:参数optional_actions使用了非法值,或参数termios中使用了非法值。
ENOTTY:非终端的文件描述符。
3.strerror()函数
原型:char * strerror(int errnum);
函数说明:strerror()用来依参数errnum 的错误代码来查询其错误原因的描述字符串, 然后将该字符串指针返回.
返回值:返回描述错误原因的字符串指针.
功能:获取指向错误消息字符串的指针
4.isatty()函数
功能:检查设备类型,判断文件描述词是否为终端机
头文件:<io.h>
原型:int isatty(int handle);
参数:int handle 为要检查的设备文件句柄
返回值:如果参数desc所代表的文件描述词为一终端机则返回1,否则返回0
int decive_init(G4_INFO **g_G4_INFO)
{
G4_INFO *gg_G4_INFO = *g_G4_INFO;
if(!gg_G4_INFO )
{
printf("gg_G4_INFO is NULL\n");
goto EXIT;
}
int retval;
char baudrate[32] = {0};
struct termios NewTermios;
memset(&NewTermios,0,sizeof(struct termios));
memset(&(gg_G4_INFO->OldTermios),0,sizeof(struct termios));
if(tcgetattr(gg_G4_INFO->deviceFd,&(gg_G4_INFO->OldTermios)))
{
printf("%s,Get termios to OldTermios failure:%s\n",__func__,strerror(errno));
return -2;
}
if(tcgetattr(gg_G4_INFO->deviceFd,&NewTermios))
{
printf("%s,Get termios to NewTermios failure:%s\n",__func__,strerror(errno));
return -3;
}
NewTermios.c_cflag |= CLOCAL;
NewTermios.c_cflag |= CREAD;
NewTermios.c_cflag &= ~CSIZE;
NewTermios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
NewTermios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
NewTermios.c_oflag &= ~(OPOST);
if(gg_G4_INFO->BaudRate)
{
sprintf(baudrate,"B%d",gg_G4_INFO->BaudRate);
cfsetispeed(&NewTermios,(int)baudrate);
cfsetospeed(&NewTermios,(int)baudrate);
}
else
{
cfsetispeed(&NewTermios,B115200);
cfsetospeed(&NewTermios,B115200);
}
switch(gg_G4_INFO->DataBits)
{
case '5':
NewTermios.c_cflag |= CS5;
break;
case '6':
NewTermios.c_cflag |= CS6;
break;
case '7':
NewTermios.c_cflag |= CS7;
break;
case '8':
NewTermios.c_cflag |= CS8;
break;
default:
NewTermios.c_cflag |= CS8;
break;
}
switch(gg_G4_INFO->Parity)
{
case 'n':
case 'N':
NewTermios.c_cflag &= ~PARENB;
NewTermios.c_iflag &= ~INPCK;
break;
case 'e':
case 'E':
NewTermios.c_cflag |= PARENB;
NewTermios.c_cflag &= ~PARODD;
NewTermios.c_iflag |= INPCK;
break;
case 'o':
case 'O':
NewTermios.c_cflag |= PARENB;
NewTermios.c_cflag |= PARODD;
NewTermios.c_iflag |= INPCK;
case 's':
case 'S':
NewTermios.c_cflag &= ~PARENB;
NewTermios.c_cflag &= ~CSTOPB;
default:
NewTermios.c_cflag &= ~PARENB;
NewTermios.c_iflag &= ~INPCK;
break;
}
switch(gg_G4_INFO->StopBits)
{
case '1':
NewTermios.c_cflag &= ~CSTOPB;
break;
case '2':
NewTermios.c_cflag |= CSTOPB;
break;
default:
NewTermios.c_cflag &= ~CSTOPB;
break;
}
NewTermios.c_cc[VTIME] = 0;
NewTermios.c_cc[VMIN] = 0;
gg_G4_INFO->mSend_Len = 128;
if(tcflush(gg_G4_INFO->deviceFd,TCIFLUSH))
{
printf("%s,Failed to clear the cache:%s\n",__func__,strerror(errno));
return -4;
}
if(tcsetattr(gg_G4_INFO->deviceFd,TCSANOW,&NewTermios) != 0)
{
printf("%s,tcsetattr failure:%s\n",__func__,strerror(errno));
return -5;
}
printf("decive_init Successfully......\n");
return 0;
}
4.用write和send发送和接收
fd_set rfd, wfd, efd;
while(1)
{
printf("FD_ISSET4\n");
sleep(2);
if(g_G4_INFO->deviceFd < 0)
{
printf("G4Handler again begin\n");
G4Handler(&g_G4_INFO);
printf("G4Handler again end\n");
if(g_G4_INFO->deviceFd < 0)
{
continue;
}
else
{
printf("G4Handler init again success\n");
}
}
FD_ZERO(&rfd);
FD_ZERO(&wfd);
FD_ZERO(&efd);
FD_SET(g_G4_INFO->deviceFd, &rfd);
FD_SET(g_G4_INFO->deviceFd, &wfd);
FD_SET(g_G4_INFO->deviceFd, &efd);
iRet = select((g_G4_INFO->deviceFd)+1,&rfd,&wfd,&efd,NULL);
if(iRet > 0)
{
if(FD_ISSET(g_G4_INFO->deviceFd,&rfd))
{
nrecv = 0;
nrecv = recvFromDevice(&g_G4_INFO);
if(nrecv < 0)
{
printf("recvFromDevice error\n");
printf("trying\n");
flag = 1;
continue;
}
else
{
printf("recv success\n");
}
}
else if(FD_ISSET(g_G4_INFO->deviceFd,&wfd))
{
if( sendToDevice(&g_G4_INFO) == -1)
{
printf("send error\n");
printf("trying...\n");
flag = 1;
continue;
}
else
{
printf("send trying success continue\n");
}
}
}
else
{
perror("select error\n");
goto EXIT;
}
}
EXIT:
if(g_G4_INFO)
{
free(g_G4_INFO);
}
if(g_G4_INFO->deviceFd >0)
{
close(g_G4_INFO->deviceFd);
g_G4_INFO->deviceFd = -1;
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)