• 欢迎大家分享资料!前往留言板评论即可!

Luat Air720S系列模块_CMUX_使用说明

合宙 模组资料网 2年前 (2021-05-15) 383次浏览 0个评论 扫描二维码
                        <pre><span style="font-weight: 700;"><span style="font-family: 宋体; font-size: 22pt;">1.</span></span><b style="color: inherit; font-family: inherit;"><span style="font-family: 宋体; font-size: 22pt;"><font face="宋体">启动</font>CMUX<font face="宋体">模式</font></span></b></pre><p class="MsoNormal"><span style="font-family: 宋体; color: rgb(77, 77, 77); font-size: 11pt; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;"><font face="宋体">通常模块发送</font>AT+CMUX命令来激活多路复用,该命令格式为:</span><span style="font-family: 宋体; color: rgb(77, 77, 77); font-size: 11pt; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;"><o:p></o:p></span></p><table class="MsoNormalTable" border="1" cellspacing="0" style="width: 489.05pt; margin-left: 5.4pt; border: none;"><tbody><tr><td width="94" valign="top" style="width:56.7000pt;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid rgb(178,161,199);

mso-border-left-alt:0.5000pt solid rgb(178,161,199);border-right:1.0000pt solid rgb(178,161,199);mso-border-right-alt:0.5000pt solid rgb(178,161,199);
border-top:1.0000pt solid rgb(178,161,199);mso-border-top-alt:0.5000pt solid rgb(178,161,199);border-bottom:1.0000pt solid rgb(178,161,199);
mso-border-bottom-alt:0.5000pt solid rgb(178,161,199);background:rgb(192,192,192);”>

命令类型

语法

返回

设置命令

AT+CMUX= [[,[,[,[,[,[,[,[,]]]]]]]]]

 

OK

查询命令

AT+CMUX?

+CMUX:[[,[,[,[,[,[,[,[,]]]]]]]]]

 

OK

测试命令

AT+CMUX=?

+CMUX:(),(s),( s),(s),(s),(s),(s),(s),(s) 

 

OK

 

参数定义:

参数

定义

取值

对取值的说明

复用透传机制

0

基本选择{gw:这里改成基本模式更合适些吧}

控制通道的复用器建立的方式

0

仅使用UIH

传输速率,单位为bits/s

1

9600

2

19200

3

38400

4

57600

5

115200

6

230400

7

460800

最大报文大小

1~255

默认:127

接收timer10ms为单位

1-255

默认:10(100 ms)

重传的最大数量

0-100

默认:3

复用器控制通道的响应定时器,以10ms 为单位

2-255

默认:30

唤醒响应定时器,以秒为单位

1-255

默认:10

窗口大小,适用于有错误恢复选项的高级操作

1-7

默认:2


2.CMUX 帧结构 

多路复用有三种操作模式:基本模式、带错误恢复功能的高级模式、不带错误恢复功能的高级模式(具体可以参见GSM 07.10协议)。不同的GPRS模块也支持不同的模式。

 Luat Air720S系列模块_CMUX_使用说明

其中,帧类型可分控制帧和信息帧。

CMUX双方通过控制帧协商用以构建、拆除虚拟链路,控制帧又为以下几种:

SABM:建立DLC

UA:响应SABM帧或DISC

DM:链路未成功建立时,对收到的DISC命令的响应

DISC:通知对端拆除链接,在DLC0发送DISC帧,等于退出MUX功能

 

信息帧:

UIH\UI\I:这三种是信息帧,也就是携带要传输数据的帧。

3.LINUX下的CMUX使用

3.1 挂载USB设备

在可移动设备,勾选QinHeng USB2.0-Serial

Luat Air720S系列模块_CMUX_使用说明

然后打开终端控制台,ls /dev/ttyUSB*查看USB设备,如下表示挂载成功。

Luat Air720S系列模块_CMUX_使用说明

3.2 CMUX虚拟串口生成

参考用例:https://www.kernel.org/doc/html/latest/driver-api/serial/n_gsm.html


3.2.1 测试实例gsmmux.h源代码

#ifndef _LINUX_GSMMUX_H

#define _LINUX_GSMMUX_H

 

struct gsm_config

{

unsigned int adaption;

unsigned int encapsulation;

unsigned int initiator;

unsigned int t1;

unsigned int t2;

unsigned int t3;

unsigned int n2;

unsigned int mru;

unsigned int mtu;

unsigned int k;

unsigned int i;

unsigned int unused[8]; /* Padding for expansion without

   breaking stuff */

};

 

#define GSMIOC_GETCONF _IOR('G', 0, struct gsm_config)

#define GSMIOC_SETCONF _IOW('G', 1, struct gsm_config)

 

struct gsm_netconfig {

unsigned int adaption;  /* Adaption to use in network mode */

unsigned short protocol;/* Protocol to use - only ETH_P_IP supported */

unsigned short unused2;

char if_name[IFNAMSIZ]; /* interface name format string */

__u8 unused[28];        /* For future use */

};

 

#define GSMIOC_ENABLE_NET      _IOW('G', 2, struct gsm_netconfig)

#define GSMIOC_DISABLE_NET     _IO('G', 3)

 

 

#endif

3.2.2 测试实例cmux.c 源代码

#include <stdlib.h>

#include <stdio.h>

#include <stdarg.h>

#include <string.h>

#include <sys/ioctl.h>

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

/**

* gsmmux.h provides n_gsm line dicipline structures and functions.

* It should be kept in sync with your kernel release.

*/

#include "gsmmux.h"

 

/* n_gsm ioctl */

#ifndef N_GSM0710

# define N_GSM0710 21

#endif

 

/* attach a line discipline ioctl */

#ifndef TIOCSETD

# define TIOCSETD 0x5423

#endif

 

/* serial port of the modem */

//#define SERIAL_PORT "/dev/ttyUSB0"

 

/* line speed */

#define LINE_SPEED B115200

 

/* maximum transfert unit (MTU), value in bytes */

#define MTU 512

 

/**

* whether or not to create virtual TTYs for the multiplex

* 0 : do not create

* 1 : create

*/

#define CREATE_NODES 1

 

/* number of virtual TTYs to create (most modems can handle up to 4) */

#define NUM_NODES 4

 

/* name of the virtual TTYs to create */

#define BASENAME_NODES "/dev/ttyGSM"

 

/* name of the driver, used to get the major number */

#define DRIVER_NAME "gsmtty"

 

/**

* whether or not to print debug messages to stderr

* 0 : debug off

* 1 : debug on

*/

#define DEBUG 1

 

/**

* whether or not to detach the program from the terminal

* 0 : do not daemonize

* 1 : daemonize

*/

#define DAEMONIZE 1

 

 /* size of the reception buffer which gets data from the serial line */

#define SIZE_BUF 256

 

 

/**

* Prints debug messages to stderr if debug is wanted

*/

static void dbg(char *fmt, ...) {

va_list args;

 

if (DEBUG) {

fflush(NULL);

va_start(args, fmt);

vfprintf(stderr, fmt, args);

va_end(args);

fprintf(stderr, "\n");

fflush(NULL);

}

return;

}

 

/**

* Sends an AT command to the specified line and gets its result

* Returns  0 on success

* -1 on failure

*/

int send_at_command(int serial_fd, char *command, int max_retry) {

char buf[SIZE_BUF];

int r;

int retry = 0;

 

do{

/* write the AT command to the serial line */

if (write(serial_fd, command, strlen(command)) <= 0)

err(EXIT_FAILURE, "Cannot write to ttyUSB");

/* wait a bit to allow the modem to rest */

sleep(1);

 

/* read the result of the command from the modem */

memset(buf, 0, sizeof(buf));

r = read(serial_fd, buf, sizeof(buf));

if (r == -1)

{

dbg("read errno %d", errno);

retry++;

dbg("retry write time: %d", retry);

}

/* if there is no result from the modem, return failure */

if (r == 0) {

dbg("%s\t: No response", command);

retry++;

//return -1;

}

if(retry!= 0 && retry >= max_retry)

{

err(EXIT_FAILURE, "Cannot read ttyUSB");

}

else

{

break;

}

}while(1);

 

 

 

/* if we have a result and want debug info, strip CR & LF out from the output */

if (DEBUG) {

int i;

char bufp[SIZE_BUF];

memcpy(bufp, buf, sizeof(buf));

for(i=0; i

if (bufp[i] == '\r' || bufp[i] == '\n')

bufp[i] = ' ';

}

dbg("%s\t: %s", command, bufp);

}

 

/* if the output shows "OK" return success */

if (strstr(buf, "OK\r") != NULL) {

return 0;

}

return -1;

 

}

 

 

/**

* Gets the major number of the driver device

* Returns  the major number on success

* -1 on failure

*/

int get_major(char *driver) {

 

FILE *fp;

char *line = NULL;

size_t len = 0;

ssize_t read;

char device[20];

int major = -1;

/* open /proc/devices file */

if ((fp = fopen("/proc/devices", "r")) == NULL)

err(EXIT_FAILURE, "Cannot open /proc/devices");

 

/* read the file line by line */

while ((major == -1) && (read = getline(&line, &len, fp)) != -1) {

/* if the driver name string is found in the line, try to get the major */

if (strstr(line, driver) != NULL) {

if (sscanf(line,"%d %s\n", &major, device) != 2)

major = -1;

}

/* free the line before getting a new one */

if (line) {

free(line);

line = NULL;

}

 

}

 

/* close /proc/devices file */

fclose(fp);

 

return major;

}

 

/**

* Creates nodes for the virtual TTYs

* Returns the number of nodes created

*/

int make_nodes(int major, char *basename, int number_nodes) {

 

int minor, created = 0;

dev_t device;

char node_name[15];

mode_t oldmask;

 

/* set a new mask to get 666 mode and stores the old one */

oldmask = umask(0);

 

for (minor=1; minor

 

/* append the minor number to the base name */

sprintf(node_name, "%s%d", basename, minor);

/* store a device info with major and minor */

device = makedev(major, minor);

/* create the actual character node */

if (mknod(node_name, S_IFCHR | 0666, device) != 0) {

warn("Cannot create %s", node_name);

} else {

created++;

dbg("Created %s", node_name);

}

 

}

 

/* revert the mask to the old one */

umask(oldmask);

 

return created;

}

 

/**

* Removes previously created TTY nodes

* Returns nothing, it doesn't really matter if it fails

*/

void remove_nodes(char *basename, int number_nodes) {

 

int node;

char node_name[15];

 

for (node=1; node

 

/* append the minor number to the base name */

sprintf(node_name, "%s%d", basename, node);

/* unlink the actual character node */

dbg("Removing %s", node_name);

if (unlink(node_name) == -1)

warn("Cannot remove %s", node_name);

 

}

 

return;

}

 

/**

* Function raised by signal catching

*/

void signal_callback_handler(int signum) {

remove_nodes(BASENAME_NODES, NUM_NODES);

return;

}

int main(int argc, char** argv) {

 

int serial_fd, major;

struct termios tio;

int ldisc = N_GSM0710;

struct gsm_config gsm;

char atcommand[40];

 

char* port;

 

if(argc != 2)

{

printf("usage\n ./cmux /dev/ttyUSBx\n");

exit(-1);

}

port = argv[1];

 

/* print global parameters */

dbg("SERIAL_PORT = %s", port);

 

/* open the serial port */

serial_fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);

if (serial_fd == -1)

{

dbg("openport ret = %d\n", errno);

err(EXIT_FAILURE, "Cannot open %s", port);

}

/* get the current attributes of the serial port */

if (tcgetattr(serial_fd, &tio) == -1)

err(EXIT_FAILURE, "Cannot get line attributes");

/* set the new attrbiutes */

tio.c_iflag = 0;

tio.c_oflag = 0;

tio.c_cflag = CS8 | CREAD | CLOCAL;

tio.c_cflag &= (~CRTSCTS);

tio.c_lflag = 0;

tio.c_cc[VMIN] = 1;

tio.c_cc[VTIME] = 0;

/* write the speed of the serial line */

if (cfsetospeed(&tio, LINE_SPEED) < 0 || cfsetispeed(&tio, LINE_SPEED) < 0)

err(EXIT_FAILURE, "Cannot set line speed");

/* write the attributes */

if (tcsetattr(serial_fd, TCSANOW, &tio) == -1)

err(EXIT_FAILURE, "Cannot set line attributes");

 

/**

* Send AT commands to put the modem in CMUX mode.

* This is vendor specific and should be changed

* to fit your modem needs.

* The following matches Quectel M95.

*/

//if (send_at_command(serial_fd, "AT+IFC=2,2\r") == -1)

// errx(EXIT_FAILURE, "AT+IFC=2,2: bad response");

if (send_at_command(serial_fd, "AT+CGMM\r", 3) == -1)

warnx("AT+GMM: bad response");

if (send_at_command(serial_fd, "AT\r", 0) == -1)

warnx("AT: bad response");

sprintf(atcommand, "AT+CMUX=0,0,5\r");

if (send_at_command(serial_fd, atcommand, 0) == -1)

errx(EXIT_FAILURE, "Cannot enable modem CMUX");

 

/* use n_gsm line discipline */

sleep(2);

if (ioctl(serial_fd, TIOCSETD, &ldisc) < 0)

err(EXIT_FAILURE, "Cannot set line dicipline. Is 'n_gsm' module registred?");

 

/* get n_gsm configuration */

if (ioctl(serial_fd, GSMIOC_GETCONF, &gsm) < 0)

err(EXIT_FAILURE, "Cannot get GSM multiplex parameters");

 

/* set and write new attributes */

gsm.initiator = 1;

gsm.encapsulation = 0;

gsm.mru = MTU;

gsm.mtu = MTU;

gsm.t1 = 10;

gsm.n2 = 3;

gsm.t2 = 30;

gsm.t3 = 10;

 

if (ioctl(serial_fd, GSMIOC_SETCONF, &gsm) < 0)

err(EXIT_FAILURE, "Cannot set GSM multiplex parameters");

dbg("Line dicipline set");

/* create the virtual TTYs */

if (CREATE_NODES) {

int created;

if ((major = get_major(DRIVER_NAME)) < 0)

errx(EXIT_FAILURE, "Cannot get major number");

if ((created = make_nodes(major, BASENAME_NODES, NUM_NODES)) < NUM_NODES)

warnx("Cannot create all nodes, only %d/%d have been created.", created, NUM_NODES);

}

 

/* wait to keep the line discipline enabled, wake it up with a signal */

signal(SIGINT, signal_callback_handler);

signal(SIGTERM, signal_callback_handler);

/* detach from the terminal if needed */

if (DAEMONIZE) {

dbg("Going to background");

if (daemon(0,0) != 0)

err(EXIT_FAILURE, "Cannot daemonize");

}

 

dbg("catching sig");

 

pause();

/* remove the created virtual TTYs */

if (CREATE_NODES) {

remove_nodes(BASENAME_NODES, NUM_NODES);

}

 

/* close the serial line */

close(serial_fd);

 

return EXIT_SUCCESS;

}

3.2.3 生成cmux可执行文件

通执行gcc cmux.c -o cmux cmux.c编译成可执行文件

3.2.4 虚拟串口生成

通执行 ./cmux /dev/ttyUSB0 就会创建几个虚拟串口

下图中的ttyGSM1,ttyGSM2,ttyGSM3,ttyGSM4及为虚拟出的串口

Luat Air720S系列模块_CMUX_使用说明

4.常见问题处理

4.1 常见AT 错误处理

命令

错误情况

错误原因

处理

AT+CMUX

+CME ERROR: 980

参数输入错误

检查一下输入参数是否正确

4.2 VMware无法识别USB设备的解决方法

我的虚拟机上认不到USB设备,发现是VMware USB Arbitration Service服务没有启动,手动启动VMware USB Arbitration Service服务,再重启VMware,虚拟机就能识别出USB设备了。

具体步骤:
1.点击开始->运行,在对话框中输入”services.msc”,确定,打开windows服务管理器。

2.在服务列表中选中”VMware USB Arbitration Service”,双击打开属性对话框,再选择”启动”,就能启动VMware USB Arbitration Service服务了。

3.关闭VMware软件,并重新打开,启动一下虚拟机。

4.3 虚拟串口生成失败

如下图所示

Luat Air720S系列模块_CMUX_使用说明

出现原因是没有选择正确的USB口,我们720SL开发板上的开关要拨到UART2一端,出现上面的错误的原因是因为开关要拨到UART1一端了,把开关拨到UART2一端,重启一下模块,然后在做上述操作。



转载请注明原文链接:Luat Air720S系列模块_CMUX_使用说明
喜欢 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址