外设测试 - 4G 模块测试

这里介绍 ME3620、ME3630 4G 模块的使用方法。

初始化

ARM Linux 板卡

#!/bin/sh

if [ ! -d "/sys/class/gpio/gpio188" ];then
    echo 188 > /sys/class/gpio/export
    echo out > /sys/class/gpio/gpio188/direction
fi

msleep 20

echo out > /sys/class/gpio/gpio188/direction
echo 1 > /sys/class/gpio/gpio188/value
sleep 1
echo 0 > /sys/class/gpio/gpio188/value
sleep 2
echo 1 > /sys/class/gpio/gpio188/value

注意不同板卡设计可能操作方法有区别。

x86 Ubuntu 主机

sudo modprobe option    # 加载驱动
sudo echo 19d2 1476 > /sys/bus/usb-serial/drivers/option1/new_id    # 使能设备

正常情况下,初始化操作完成后将生成 /dev/ttyUSB0、/dev/ttyUSB1、/dev/ttyUSB2 三个 4G 模块调试串口,以及 usb0 网络节点。

 

建立连接

模块初始化后,需要与通信基站建立连接,以便接入互联网。方法是通过 AT 指令控制模块进行相应的动作。参考代码:

./me3620_network_setup /dev/ttyUSB1 usb0

 

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <time.h>
#include <sys/select.h>

//#define DEBUG_PRINTF
#ifdef	DEBUG_PRINTF
#define DEBUGFMT "%s(%d)-%s: "
#define DEBUGARGS	__FILE__,__LINE__,__FUNCTION__

#define SERIALDBG(format, ...) \
    printf(DEBUGFMT "debug: " format, DEBUGARGS, ## __VA_ARGS__)


#else /* DEBUG_PRINTF */
#define SERIALDBG(format, ...)
#endif

#define CMD "echo \"AT+CFUN=1,1\" > %s"
#define UDHCPC "udhcpc -i %s"
#define PING "ping -I %s www.baidu.com"

static struct termios uartsave;
static struct termios uartset;
static struct termios uartnew;

static int open_serial(char *dev) {
    int fd;
    fd = open(dev, O_RDWR|O_NOCTTY|O_NDELAY, 0);
    if ( fd < 1 ) {
        fprintf(stderr, "open <%s> error %s\n", dev, strerror(errno));
        return -1;
    }

    return fd;
}

static void close_serial(int pf) {
    /* restore original terminal settings on exit */
    tcsetattr(pf, TCSANOW, &uartset);
    close(pf);
}

static void termios_setup(int pf,speed_t speed_param) {
    tcgetattr(pf, &uartsave);
    uartset = uartsave;
    cfsetospeed(&uartset, speed_param);
    cfsetispeed(&uartset, speed_param);

    // Space calibration
    uartset.c_cflag &= ~ CSIZE;  	// Countless according to a bit mask
    uartset.c_cflag |= CS8;		    // 8 bits of data
    uartset.c_cflag &= ~ CSTOPB; 	// If set CSTOPB, 2 stop bits (do not set is a stop bits)
    uartset.c_cflag &= ~ PARODD;    // even parity is used
    uartset.c_cflag |= PARENB;	    // enable calibration
    //uartset.c_cflag &= ~ PARENB;	// no calibration
    uartset.c_cflag &= ~ CRTSCTS;   // No flow control
    //uartset.c_cflag |= CRTSCTS;

    // if not development, just like serial port terminal,
    // without the need for data transmission serial port to handle,
    // then use the original Mode (Raw Mode) way to communication,
    // setting as follows:

    // will CR mapped to litton precision;
    // Start exports hardware flow control;
    // Start entrance software flow control;
    // Allow characters restart flow control
    uartset.c_iflag &= ~ ( ICRNL | IXON | IXOFF | IXANY );
    uartset.c_lflag &= ~ ( ICANON | ECHO | ECHOE | ISIG );
    uartset.c_cc[VMIN] = 0;
    uartset.c_cc[VQUIT] = 0;
    uartset.c_cflag |= CREAD; // enable receiving

    tcsetattr(pf, TCSANOW, &uartset);
    tcgetattr(pf, &uartnew);
}

/* send len bytes data in buffer */
static int serial_write(int fd, const void *buf, int len, struct timeval *write_tv) {
    int 	count;
    int 	ret;
    fd_set	output;
    struct timeval timeout;

    ret = 0;
    count = 0;

    timeout.tv_sec = write_tv->tv_sec;
    timeout.tv_usec = write_tv->tv_usec;

    FD_ZERO(&output);
    FD_SET(fd, &output);

    do{	/* listen */
        ret = select(fd + 1, NULL, &output, NULL, &timeout);
        if (ret == -1) { /* error */
            perror("select()");
            return -1;
        } else if (ret) { /* write buffer */
            ret = write(fd, (char *) buf + count, len);
            if (ret < 1) {
                fprintf(stderr, "write error %s\n", strerror(errno));
                return -1;
            }
            count += ret;
            len -= ret;
        }
        else { /* timeout */
            SERIALDBG("time out.\n");
            return -EAGAIN;
        }
    } while (len > 0);

    SERIALDBG("write count=%d\n",count);

    return count;
}

/* read one char from serial */
int serial_read_ch(int fd, char *c, struct timeval *read_tv) {
    int		ret;
    fd_set	input;
    struct timeval timeout;

    ret = 0;

    timeout.tv_sec = read_tv->tv_sec;
    timeout.tv_usec = read_tv->tv_usec;

    FD_ZERO(&input);
    FD_SET(fd, &input);

    /* listen */
    ret = select(fd + 1, &input, NULL, NULL, &timeout);
    if (ret == -1) { /* error */
        perror("select()");
        return -1;
    }
    else if (ret) { /* read */
        ret = read(fd, c, sizeof(char));
        if (ret < 1) {
            fprintf(stderr, "read error %s\n", strerror(errno));
            return -2;
        }
    }
    else { /* timeout */
        SERIALDBG("time out.\n");
        return -3;
    }

    return 0;
}

/* wait until the first "OK" string come from serial */
static int wait_ok_string(int fd, int timeout_sec) {
    int i;
    int ret = 0;
    char ch = '?';
    char last = '?';
    struct timeval timeout;

    timeout.tv_sec = timeout_sec;
    timeout.tv_usec = 0;

    for (i = 0; i < 1024; i++) {
        /* read one char */
        ret = serial_read_ch(fd, &ch, &timeout);
        if (ret < 0)
            break;

        /* display the char */
        putchar(ch);

        /* check "ok" */
        if (last == 'O' && ch == 'K') {
            ret = 1;
            break;
        }

        last = ch;
    }

    return ret;
}

int main(int argc, char **argv) {
    int fd;
    char cmd[30];
    struct timeval tv;

    /* command line */
    if (argc != 3) {
        printf("usage: ./me3620_network_setup <<device>> <<new_network_card>> \n"
                "eg: ./me3620_network_setup /dev/ttyUSB1 usb0 \n");
        return -1;
    }

    /* open serial */
    fd = open_serial(argv[1]);
    if(fd < 1)
        return -1;

    termios_setup(fd, B115200);
    tcflush(fd, TCIOFLUSH);

    tv.tv_sec = 5;
    tv.tv_usec = 0;

    // Switch modem to ECM mode
    const char *Switch_mode = "AT+ZSWITCH=L\r";
    serial_write(fd, Switch_mode, strlen(Switch_mode), &tv);
    if (wait_ok_string(fd, 5) != 1) {
        printf("Switch modem to ECM mode error. exit!\n");
        goto err;
    }

    // Reboot the modem
    snprintf(cmd, 30, CMD, argv[1]);
    system(cmd);

    //close_serial(fd);
    sleep(10);

    // open serial again
    fd = open_serial(argv[1]);
    if(fd < 1)
        return -1;

    termios_setup(fd, B115200);
    tcflush(fd, TCIOFLUSH);
    tv.tv_sec = 5;
    tv.tv_usec = 0;


    // Setup data call parameter
    const char *Callparameter_mode = "AT+CGDCONT=1,\"IP\",\"CMWAP\"\r";
    serial_write(fd, Callparameter_mode, strlen(Callparameter_mode), &tv);
    if (wait_ok_string(fd, 5) != 1) {
        printf("Setup data call parameter error. exit!\n");
        goto err;
    }

    // Setup ECM data call
    const char *Setupdata_mode = "AT+ZECMCALL=1\r";
    serial_write(fd, Setupdata_mode, strlen(Setupdata_mode), &tv);
    if (wait_ok_string(fd, 5) != 1) {
        printf("Setup ECM data call error. exit!\n");
        goto err;
    }

    // Start DHCP to get IP and DNS
    snprintf(cmd, 30, UDHCPC, argv[2]);
    system(cmd);
    sleep(5);

    // Ping www.baidu.com
    snprintf(cmd, 30, PING, argv[2]);
    system(cmd);
    sleep(1);

    /* release */
    close_serial(fd);
    return 0;

err:
    close_serial(fd);
    return -1;
}

参考

《Ubuntu 下使用 ZTE ME3630 4G 模块》:https://blog.csdn.net/engrossment/article/details/100914601

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页