嵌入式Linux中同时实现GPRS和SMS短信收发

 2010-6-11         

        随着移动通讯技术的发展普及,GPRS无线通讯和SMS短信收发越来越多地应用到工业领域的远程数据通讯中。GPSR主要是进行的数据通讯,SMS则是AT指令的操作模式,在不少的无线通讯模块,比如西门子的MC39i、华为的GTM900,模块一旦处于GPRS数据通讯状态,则无法再进行AT指令的操作,从而难以同时实现SMS短信数据收发的功能。解决这个问题方法之一是在软件上实现多路转换协议,这种方式通过软件协议的方式将一个物理口虚拟为多个口,从而将GPRS通讯和SMS通讯分开,这种模式程序往往比较复杂,在嵌入式的应用中比较难以实现。方法之二就是直接在硬件物理口上将GPRS和SMS通讯分开,西门子提供的MC37i无线模块本身就自带有两个物理串口,可以支持分别进行GPRS和SMS通讯的操作。本文将结合英利公司提供的ARM9 Linux主板EM9160和ETA300 GPRS扩展单元(GPRS无线模块为MC37i),着重介绍如何同时实现GPSR通讯和SMS短信收发的应用。

 

硬件组成

        英利公司的嵌入式Linux主板EM9160共有6个异步串口,在Linux环境中为“/dev/ttyS1”-“/dev/ttyS6”。ETA300是包括MC37i模块的外挂式GPRS通讯单元,可直接通过带线与英利EM9160开发评估底板相连,如下图所示。其中GPRS通讯占用EM9160的 “/dev/ttyS1” (或称COM2) 口,SMS通讯占用EM9160的“/dev/ttyS4”( 或称COM5 ) 口,连接方式如下图所示。

 

嵌入式Linux工控板EM9160连接GPRS模块示例图

 

MC37i电源管理

        通过ETA300 GPRS扩展单元可实现对MC37i的电源管理,MC37i的电源管理是通过两路GPIO:GPIO8和GPIO9来实现,分别对应GPRS _STB、GPRS_AUX管脚信号。在程序上操作GPIO8、GPIO9实现对MC37i的上电、关电操作。以下为提供的对MC37i电源管理的操作函数:

        // 功能描述:该函数通过对EM9160的GPRS_STB和GPRS_AUX两个管脚信号的操作,实现对GPRS模块的电源管理。
        // 输入参数 OpMode: 电源管理功能索引号,有效索引号包括:
                             OpMode = 1: 对GPRS模块进行上电操作,并把执行该操作后电 源状态返回;
                             OpMode = 2: 对GPRS模块进行强制关电,并把执行该操作后电源状态返回;
                             OpMode = 3: 读取GPRS模块当前的电源状态。
        // 输出参数 pResult: 用于存储读取的电源状态信息。
                             *pResult = 0: 表示GPRS模块的电源已关闭;
                             *pResult = 1: 表示GPRS模块的电源已加载成功;

        int GPRS_PM( int fd, int OpMode, int* pResult )

 

嵌入式Linux中的GPRS拨号

        嵌入式Linux ppp GPRS拨号程序pppd和相关的脚本文件,均已经缺省包含在EM9160板卡的根文件系统中。

 

        嵌入式Linux主板EM9160环境下进行GPRS拨号时,首先调用函数GPRS_PM(…)使MC37i上电成功,然后再启动pppd进程进行GPRS拨号。

 

        printf('GPRS Power On\n');
        GPRS_PM(fd, 1, &GPRS_State);
        // MC37i模块上电登录到移动网络等待时间
        for( i1=0; i1<8; i1++ )
        {
                sleep( 1 );
                printf( '.\n' );
        }
        system( 'pppd call pppd-connect-script' );

 

        挂断直接可调用ppp-off脚本:

        system( '/etc/ppp/ppp-off' );

 

嵌入式Linux中的SMS短信收发

        SMS短信收发的核心通讯模式为串口通讯,应用程序上也是采用的C++的编程方式,利用英利公司网站技术天地栏目中《嵌入式Linux串口通讯的C++设计》一文中介绍的CSerial类,在CSerial基础上派生了一个针对于SMS收发应用的class SMS,该派生类 class SMS 中重新实现了虚函数PackagePro(…) 接收数据处理函数,以满足SMS收发的应用需求。

 

        在sms.h中定义了短信的数据结构:

        struct SMS_DATA
        {
                unsigned char PhoneNum[16]; // 对端电话号码
                struct Date d; // 日期:年月日
                struct Time t; // 时间:时分秒
                int DatLen; // 数据长度
                unsigned char DBuf[168]; // 短信数据内容
        };

 

        对于SMS短信收发可调用的类函数包括有:

        // 按照指定的参数打开短信Modem端口,并创建短信接收线程
        int OpenPort( int PortNo, int baudrate, char databits, char stopbits, char parity );
        // 关闭短信Modem端口并释放相关资源
        int ClosePort( );
        // 发送AT指令初始化短信Modem
        int InitSMSModem( );
        // 发送短信
        int SendMessage( struct SMS_DATA* pSMS );

 

        在该例程中短信接收的处理放在函数PackagePro(…)中实现的,用户可以根据实际情况加以调整。SMS短信收发的实现代码均在sms.cpp下,由于是CSerial的派生类,其接收的主要流程可参见英利公司网站技术天地栏目中《嵌入式Linux串口通讯的C++设计》一文中相关介绍,这里不再赘述。

 

        在class SMS中实现了支持中文短信的发送,所以短信发送的模式均采用PDU模式。对于中文字符,在短信发送时还需要转换为unicode码,程序代码中已经实现了中文内码到unicode 码的自动转换,客户在测试该程序时,需要注意的是要将unicode 的相关转换文件表COPY到/mn/nandflash:gsm0338.bin gb2312.bin unicode.bin。

 

        本文中所介绍的例程仅仅适用于英利EM9160嵌入式主板,均有源码提供。感兴趣的客户可以发邮件到公司技术支持邮箱 support@emlinix.com索取相关代码。