打印

(开源)gprs联网软硬件方案(md251,可移植代码)求拍砖

[复制链接]
11520|44
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sinanjj|  楼主 | 2012-5-21 08:58 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 sinanjj 于 2012-6-8 10:37 编辑

方案目的:mcu通过串口和gprs 模块连接,gprs模块将串口数据转到设置好的服务器。
方案成本:100rmb内(模块75rmb零售价,天线,pcb板等自行计算)
方案特色:低成本,soc化,soc内部可以编程!有服务器中间件提供的ack机制保证稳定性,快速的短线重连接。
支持:md251的供应商提供一般技术支持。
硬件稳定性:因为md251就是mtk的手机板,稳定性由广大山塞手机用户可以验证。
方案主芯片:MT6252A MTK
芯片英文介绍:
MT6252 - Single-Chip GSM/GPRS/EGPRS entry-multimedia solution
MT6252 is a single-chip GSM/GPRS/EGPRS solution that offers highest level of integration with lowest power consumption and best-in-class features. Key features include embedded 32MB pseudo-SRAM, external SPI serial flash, multimedia support up to 0.3Mpixel camera, MP4 CIF video and WQVGA display. Integrated RF solution offers exceptional radio performance under stringent ambient conditions. MT6252 platform is pre-integrated with MediaTek's highly proven, feature-rich SW solution thus considerably reducing the design cycle time and increasing the phone premium for consumers.
Features
● GSM/GPRS Class 12, Quad band
● ARM7-EJ 104MHz
● Embedded 32MB pseudo-SRAM
● Audio: MP3, AAC, AMR-NarrowBand
● Tier-1 voice noise reduction and echo cancellation
● Support up to 262K color WQVGA LCM
● Support up to 0.3MP camera (YUV)
● MP4 CIF@30fps video decode and up to HVGA@15fps.
● Rich video codec support: H.264, AVI, MJPEG
● Support dual-standby single talk
● Integrated RF, PMU, USB 2.0 FS
● Integrated Class-AB audio amplifier (700mW@3.7V)
● Integrated resistive touch controller
● Pre-integrated with MediaTek’s highly proven, feature-rich SW platform.

(注:对比真正应用的物联网项目,此开源版删除了ID系统,只保留了链路部分。)

                                 (以太网的ti soc我有空搞了也会开放)



源码包(下有讲解,可直接看思路)

MD251.zip (484.12 KB)

相关帖子

沙发
sinanjj|  楼主 | 2012-6-8 09:41 | 只看该作者

实物图(直观概念)

本帖最后由 sinanjj 于 2012-6-8 09:47 编辑

使用特权

评论回复
板凳
sinanjj|  楼主 | 2012-6-8 09:48 | 只看该作者
本帖最后由 sinanjj 于 2012-6-8 09:53 编辑

硬件图纸:








请仅参考,因为这个第一版的图纸串口使用了串口1,应该使用串口2. 电源封装也不对(这个得询问伟大的供应商硬件工程师)
更正后的会后续放出。

pcb和sch: MD251_sch_pcb.zip (454.58 KB)

使用特权

评论回复
地板
sinanjj|  楼主 | 2012-6-8 09:55 | 只看该作者
模块供应商联系人:

QQ: 23767329

相关资料可以找他要。

(未有商业关系,如有成本更低,或者同是mtk方案的,大家可以在下提供供应商,以便于竞争)

使用特权

评论回复
5
sinanjj|  楼主 | 2012-6-8 09:59 | 只看该作者
本帖最后由 sinanjj 于 2012-6-8 10:03 编辑

软件部分:

大体介绍:

这个md251是可以像mcu一样使用的,100Mhz速度,当然,跑了一堆mtk的东西了。

编译使用的是gcc,RVCT31,windows下的一个gcc环境(做的还不错,感觉挺好)。

编译环境,首先安装这个rvct_install,就是gcc,make等编译工具,然后在openat(就是个源码包文件,里边一堆库)文件夹里打make指令(当然是要在cmd shell下)就可以编译了。

编译完成,使用厂家提供的下载软件,通过串口1就可以下载了(串口1必须得流出来,而且程序里不能用串口1,串口1用来跟踪debug信息的。)

只有openat文件夹的子目录,src文件里是我们要编译的源文件。

这里我已经将源文件精简到100多行,一个文件。很简单吧。

系统函数的功能,高手可以直接猜了,这个mtk的系统使用了大量的函数指针作为函数参数的回调这种方式(适合事件机制啊),中文文档里也有些写的不明白,具体靠猜了。

当然,如果大家只引用我的源文件,那是一点问题没有的。

源文件:

oa_app.zip (1.64 KB)

使用特权

评论回复
6
sinanjj|  楼主 | 2012-6-8 10:10 | 只看该作者
本帖最后由 sinanjj 于 2012-6-8 10:21 编辑

md251源代码思路:(稳定性的保证)(大侠们可以浏览一下)

首先说下大体思路:
上电以后,初始化串口(防止串口数据对程序构成影响----虽然貌似也没啥影响),然后等待gsm ready,gsm ready了等待gprs ready(都是基于事件的回调函数啊,写的七零八落的),gprs ready了创建udp socket,然后开始转发uart数据和gprs来的数据,保证心跳包结构。
每10s检测一次数据包丢失情况,如果数据包丢失大于5个,则重启模块。
(要求数据传输是个不间断的过程,要是间断的请自行添加心跳包。)



void oa_app_main(void * param) 入口函数
{
        oa_uart_struct uart_setting = { 设置结构体。基本的设置
                115200,        // baudrate
                oa_uart_len_8,        // dataBits
                oa_uart_sb_1,        // stopBits
                oa_uart_pa_none,        // parity
                oa_uart_fc_none,        // flow control
                0x11,        // xonChar
                0x13,        // xoffChar
                OA_FALSE
        };
        oa_uart_open(OA_UART2, &uart_setting); 打开串口的封装函数

        oa_uart_set_read_delay(OA_UART2, 48);        //set the time interval between uart data, for received data frame by frame,one frame max length is 300 bytes
看英文注释哈。
        oa_uart_register_callback(OA_UART2, uart_null);        //register UART1 received data callback function
这个是操作系统的特点了,回调函数的,这里指向一个直接return的函数uart_null因为,开始没有加入网络期间,这段时间gprs数据是无法收发的,所以直接扔掉,但是又不能让串口的数据对系统构成影响,所以直接写了个null函数,就是gprs不通的时候,数据全部扔掉(什么?缓存所有的?也可以,但是大部分系统都是侧重于实时数据吧,比如说一个电机,gprs恢复了你也是首先关注当前信息吧!所以系统设计的第一要求是尽量的上传实时数据!)
        oa_timer_start(OA_APP_SCHEDULER_ID, wait_gsm, NULL, 1000);
这个类似于for(;;), while(1)之类,1000表示1s执行一次,执行的函数名叫wait_gsm。看名就知道这个是等待gsm网络ready的。就是你手机打开以后会等一回才能加入网络,一般刚开机,会经过10s左右。我测试是15s左右。
}

使用特权

评论回复
7
sinanjj|  楼主 | 2012-6-8 10:17 | 只看该作者
本帖最后由 sinanjj 于 2012-6-8 10:24 编辑

void wait_gsm(void* param)
{
        if(oa_sim_network_is_valid()) { 这个api是检测gsm网络ready的,可以看到,不ready继续检测,ready了 执行wait_gprs 去。思路从名字都看得出来。
                oa_timer_start(OA_APP_SCHEDULER_ID, wait_gprs, NULL, 1000);
        } else {
                oa_timer_start(OA_APP_SCHEDULER_ID, wait_gsm, NULL, 1000);
        }
}

void wait_gprs(void* param)
{
        oa_soc_apn_info_struct apn_info_cmnet = {"cmnet","",""};
        oa_gprs_set_apn_req(&apn_info_cmnet, apn_handler);
        oa_gprs_attach_req(gprs_handler); 这些是手机上网必须设置的。估计用gprs上过网的人都熟吧。(什么?你不知道?打开手机找找设置)
        if(gprs_ok) { 这个是从回调函数里设置的值,回调函数是 gprs_handler.
                oa_sockaddr_struct soc_addr = { OA_SOCK_DGRAM, 14, "173.255.226.41", 2001 };
                socket_id = oa_soc_create(OA_SOCK_DGRAM, 0);
                oa_soc_notify_ind_register(udp_data);        //register socket network notify event callback function
                oa_soc_connect(socket_id, OA_IP_ADDRESS, &soc_addr); 这里创建链接,使用的udp,不是tcp哈,在网络不稳定的情况下尽量使用udp,因为底层可以自己优化(当然你用raw socket写tcp状态机当我没说)

                oa_uart_set_read_delay(OA_UART2, 48);        //set the time interval between uart data, for received data frame by frame,one frame max length is 300 bytes
                oa_memset(ack_seq, '\x01', 256);ack_seq是一个数组,为什么用数组呢?因为数据包的延时ack机制,就是每一个发出的数据包都有一个序列号,这个序列号是1个byte的,作用就是区分ack,相当于tcp里的序列号,每个ack到达与否对应于这个数组中的值。(确实比较难解释。。。)
                oa_uart_register_callback(OA_UART2, uart_handler);        //register UART1 received data callback function
oa_uart_write (OA_UART2,"\r\nstart\r\n",9); 标识gprs开始
               
                oa_timer_start(OA_APP_SCHEDULER_ID, ack_check, NULL, 10000); 这个daemon是不断的检测ack的情况,一旦检测到5个包没有ack就自动重启模块。
        } else {
                oa_timer_start(OA_APP_SCHEDULER_ID, wait_gprs, NULL, 1000);
        }
}


然后重要的部分就是ack,心跳了,我这里使用了每3s一次的采集参数作为心跳,ack。

服务器程序需要满足ack需求,即:每个ack的值都是包头的第一个值,即是序列号。

void uart_handler (void * param, oa_uint32 len)
{
    if (len>=512) return;
    pkt_len = len +3;
    oa_memset(pkt, '\x00', 515);
    oa_memcpy((void *)&pkt[3], param, len);
    seq ++;
    pkt[0] = seq; pkt[1] = 0x00; pkt[2] = 0x01;    // | 1byte seq | 2 byte ID | uart data |
    oa_soc_send(socket_id, pkt, pkt_len);
    *(ack_seq+seq) = 0;
}

重点在于     pkt[0] = seq; pkt[1] = 0x00; pkt[2] = 0x01;    // | 1byte seq | 2 byte ID | uart data |
0001是id号,大家可以不管,seq是序列号,保证ack的。

使用特权

评论回复
8
sinanjj|  楼主 | 2012-6-8 10:33 | 只看该作者
本帖最后由 sinanjj 于 2012-6-8 10:35 编辑

服务器部分代码(会写的自己改改,不会写的我发了全部也没用。这里发部分)


        int udp_fd;
        if ((udp_fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { printf ("error: socket\n"); exit (0); }
        struct sockaddr_in servaddr; bzero(&servaddr, sizeof(struct sockaddr_in));
        servaddr.sin_family = PF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(CAPTURE_PORT);
        if (bind(udp_fd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in)) == -1) {
                printf("error: bind()\n"); exit(0);
        }

        struct sockaddr_in clientaddr;
        int slen = sizeof(clientaddr);
        unsigned char buf[2500];
        int n;
        for (;;) {
                n = recvfrom(udp_fd, buf, 2500, 0, (struct sockaddr *)&clientaddr, (socklen_t *)&slen);
                if (n == -1) continue;
                sendto(udp_fd, buf, 1, 0, (struct sockaddr *)&clientaddr,sizeof(struct sockaddr));这里送回ack

                printf(“source:%s:%d length:%05d data:",  inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), n);
                unsigned int i;for (i=0; i<n; i++) printf( "%02x ", buf);
                printf("\n");
        }
}




这个还只能记录,不能下发,(绝对不是我不会写啦)以后公布全功能的中间件。




使用特权

评论回复
9
mpuhome| | 2012-6-8 20:57 | 只看该作者
顶你,真不错的方案
便宜量又足

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
李小双 + 1 变形金刚百度影音 http://www.7677.tv/.
10
JohnsonWorker| | 2012-6-9 00:13 | 只看该作者
这家公司一直做出口,最近2年才在国内市场上卖产品。我们用这家公司的产品用了5年了,一直都很稳定,技术支持很不错。原先我们用的希姆通的模块,现在都换成MD251了。这家公司的GPRS模块都是通过了CE,FCC,CCC,Rohns等认证,连香港的沃达丰都用这家公司产品。

使用特权

评论回复
11
javie| | 2012-6-9 11:25 | 只看该作者
小司南,怎么要这么贵?你被人黑了吧?

使用特权

评论回复
12
sinanjj|  楼主 | 2012-6-9 12:19 | 只看该作者
小司南,怎么要这么贵?你被人黑了吧?
javie 发表于 2012-6-9 11:25


目前使用的宏电的这个,不仅gsm断网以后不会自动恢复,而且是800rmb一个。而且双服务器指向还要加几百块(1000多拉)。当然,工业应用不差这点钱,但是因为他不自动启动这一项,还专门搞了个断电从起。。。。。

我接手自然时要把这种垃圾货色淘汰了。。。。

服务器设计了支撑上万个节点,程序需要很细节的优化,耗时测量。这个还在优化。

使用特权

评论回复
13
kyzb001| | 2012-6-9 13:05 | 只看该作者
SIM卡呢

使用特权

评论回复
14
kyzb001| | 2012-6-9 13:05 | 只看该作者
也是一笔支出,并且还是持续的!

使用特权

评论回复
15
sinanjj|  楼主 | 2012-6-9 16:50 | 只看该作者
也是一笔支出,并且还是持续的!
kyzb001 发表于 2012-6-9 13:05


所以民用还是得用wifi

野外的情况用gprs。

使用特权

评论回复
16
sinanjj|  楼主 | 2012-6-10 19:25 | 只看该作者
todolist:

1, 增加io表示链路状态。重启如何不影响。
2,发送数据确认提示。

使用特权

评论回复
17
相信哥咯| | 2012-6-10 21:10 | 只看该作者
你说什么东西阿

使用特权

评论回复
18
nextkey| | 2012-6-11 07:25 | 只看该作者
成本偏高吧

使用特权

评论回复
19
lou0908| | 2012-8-5 23:50 | 只看该作者
成本相当高了,现在很多gprs模块只要6~70块钱就能做到了

使用特权

评论回复
20
sinanjj|  楼主 | 2012-8-6 09:47 | 只看该作者
成本相当高了,现在很多gprs模块只要6~70块钱就能做到了
lou0908 发表于 2012-8-5 23:50


这个芯片成本只有15rmb。你如果自己做核心板成本自己想。

我说的是零售价。kkk的量的自己想。


考虑成本是完全无意义的。因为一旦上量,各种方案成本差异很小,不上量也盈利不多。


高富帅狂升硬件,矮穷丑狂写软件,说的也有一定道理。(特别对有些错误理解的人。)

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:In God We Trust 独立的个人,体赖科学技术工具提供针对个人的产品与服务,是通向幸福的唯一道路 工程师,设计师等可以个人创业的群体,将逐步瓦解官僚体制公司,成为中国中产。(重复劳动,工厂等,将逐步机械化) seacer.co

456

主题

6300

帖子

25

粉丝