STM32F103 GU906B模块GPRS、短信收发、拨号等功能的实现
这个程序搞了我很久,尤其是对如何提高响应速度上,程序流程很简单,大概就是:
发送AT指令->等待模块响应->一旦响应了,立即返回,并处理掉。
这个程序不一定只能用在GU906上,程序框架在任何GPRS模块上都能用,只要修改相应的AT指令,按照对应模块的AT指令流程,做下流程上的修改,就没啥问题,框架很简单,不像某宝上店家的那些代码一样,那些代码反正我是看的头晕,程序接口我都留着,只要按照相应的流程调用接口就好。
下面是模块的代码gu906.c文件
- // _ooOoo_
- // o8888888o
- // 88" . "88
- // (| -_- |)
- // O\ = /O
- // ____/`---'\____
- // . ' \\| |// `.
- // / \\||| : |||// \
- // / _||||| -:- |||||- \
- // | | \\\ - /// | |
- // | \_| ''\---/'' | |
- // \ .-\__ `-` ___/-. /
- // ___`. .' /--.--\ `. . __
- // ."" '< `.___\_<|>_/___.' >'"".
- // | | : `- \`.;`\ _ /`;.`/ - ` : | |
- // \ \ `-. \_ __\ /__ _/ .-` / /
- // ======`-.____`-.___\_____/___.-`____.-'======
- // `=---='
- //
- // .............................................
- // 佛祖保佑 永无BUG
- // 佛曰:
- // 写字楼里写字间,写字间里程序员;
- // 程序人员写程序,又拿程序换酒钱。
- // 酒醒只在网上坐,酒醉还来网下眠;
- // 酒醉酒醒日复日,网上网下年复年。
- // 但愿老死电脑间,不愿鞠躬老板前;
- // 奔驰宝马贵者趣,公交自行程序员。
- // 别人笑我忒疯癫,我笑自己命太贱;
- // 不见满街漂亮妹,哪个归得程序员?
- //////////////////////////////////////////////////////////
- #include <string.h>
- #include <stdlib.h>
- #include "stdio.h"
- #include "delay.h"
- #include "config.h"
- #include "usart4.h"
- #include "gu906.h"
- #define DEBUG_EN 1
- //接收缓存
- #define MAXRECVBUFF USART4_BUFF
- #define AT "AT\r\n" //测试命令
- #define ATE(x) ((x)?("ATE1\r\n"):("ATE0\r\n")) //开回显、关回显
- #define ATESIM "AT+ESIMS?\r\n" //检测卡是否存在
- #define ATCNMI "AT+CNMI=2,1\r\n" //设置这组参数来了新信息存储起来
- #define ATCMGD "AT+CMGD=1,4\r\n" //删除当前存储器中全部短信
- #define ATCMGF "AT+CMGF=1\r\n" //0设置短消息为PDU模式, 1设置短消息为txet模式
- #define ATCSMP "AT+CSMP=17,167,2,25\r\n" //设置文本模式的参数
- #define ATUCS2 "AT+CSCS=\"UCS2\"\r\n" //设置为 UCS2 编码字符集
- #define ATGB2312 "AT+CSCS=\"GB2312\"\r\n" //设置GB2312编码
- #define ATATD "ATD%s;\r\n" //对指定手机拨号
- #define ATATH "ATH\r\n" //挂机
- #define ATGSM "AT+CSCS=\"GSM\"\r\n" //设置GSM字符集
- #define ATCPMS "AT+CPMS=\"SM\",\"SM\",\"SM\"\r\n" //设置短信存储单元为SIM卡
- #define ATCSQ "AT+CSQ\r\n" //获取信号强度
- #define ATCREG "AT+CREG?\r\n" //确保模块以及注册到GSM网络
- #define ATCIICR "AT+CIICR\r\n" //让模块激活 GPRS 网络,在需要反复建立 TCP 链接的场合可提高速度
- #define ATCIPSTARTOK "AT+CIPSTART?\r\n" //查询当前是否有网络连接
- #define ATCIPCLOSE "AT+CIPCLOSE=0\r\n" //关闭网络连接
- #define ATCIPSCONT(x) ((x)?("AT+CIPSCONT=0,\"%s\",\"%s\",%d,2")\
- :("AT+CIPSCONT\r\n")) //保存设置
- #define ATCIPSTART "AT+CIPSTART=\"%s\",\"%s\",%d\r\n" //设置TCP连接的IP和端口
- #define ATCIPMUX "AT+CIPMUX=0\r\n" //单链接模式
- #define ATCIPMODE(x) ((x)?("AT+CIPMODE=1,0\r\n")\
- :("AT+CIPMODE=0,0\r\n")) //数据透传输模式、非透传
- #define ATCIPCFG(x) ((x)?("AT+CIPCFG=1,50,0\r\n")\
- :("AT+CIPCFG=0,50,0\r\n")) //自动启动连接命令
- #define ATCIPPACK(x) ((x)?("AT+CIPPACK=1,\"4C4F47494E3A31303031\"\r\n")\
- :("AT+CIPPACK=0,\"0102A0\"\r\n")) //设备注册包、心跳包设置
- #define ATCIPSEND(x) ((x)?("AT+CIPSEND=%d\r\n")\
- :("AT+CIPSEND\r\n")) //设置发送的数据长度
- #define ATCGMR "AT+CGMR\r\n" //获取基站信息
- #define ATCMGS "AT+CMGS=\"%s\"\r\n" //设置需要发送短信的手机号
- #define ATCMGR "AT+CMGR=%s\r\n" //设置要读取的短信的位置
- #define ATCSTT "AT+CSTT=\"CMNET\"\r\n" //账号配置
- #define ATCIPSCONT_C "AT+CIPSCONT?\r\n" //查询透传连接情况
- #define GPRSSEND 0x1A
- #define CLOSEDTU "+++" //关闭透传
- #define OPENDTU "ATO0\r\n" //重新进入透传
- enum order{
- //与命令对应的
- _AT = 1,_ATE,_ATESIM,_ATCNMI,_ATCMGD,_ATCMGF,_ATCSMP,_ATUCS2,
- _ATGB2312,_ATATD,_ATATH,_ATGSM,_ATCPMS,_ATCSQ,_ATCREG,
- _ATCIICR,_ATCIPSTARTOK,_ATCIPCLOSE,_ATCIPSCONT,_ATCIPSTART,
- _ATCIPMUX,_ATCIPMODE,_ATCIPCFG,_ATCIPPACK,_ATCIPSEND,_ATCGMR,
- _ATCMGS,_ATCMGR,_GPRSSEND,_ATCSTT,_ATCIPSCONT_C,_CLOSEDTU,_OPENDTU,
- //额外的数据类型
- _GSMSEND,_GSMSENDEND
- };
- struct GprsData{
- charchar *order;
- int olen;
- enum order type;
- };
- //GPRS数据保存位置
- static char GPRS_Data[MAXRECVBUFF]={0};
- static int GPRS_Dlen = 0;
- static u8 GPRS_Dtu_ConLock = 0;
- u8 RestartGprs = 0; //重启GPRS标志
- #if GU906GSM_EN
- //短信信息在SIM卡中的位置
- static char SIMDataID[5]="";
- struct user_simdata sim;
- #endif
- /*********************************************************
- * @function GPRS_ascii_to_hex
- * @role
- * @input
- * @output None
- * @return
- ********************************************************/
- static int GPRS_ascii_to_hex(u8 *asc_data, u8 *hex_data, int len)
- {
- int i;
- u8 tmp_dat;
- for(i = 0; i < len; i++)
- {
- if ((asc_data[i] >= '0') && (asc_data[i] <= '9')){
- tmp_dat = asc_data[i] - '0';
- }else if ((asc_data[i] >= 'A') && (asc_data[i] <= 'F')){ // A....F
- tmp_dat = asc_data[i] - 0x37;
- }
- else if((asc_data[i] >= 'a') && (asc_data[i] <= 'f')){ // a....f
- tmp_dat = asc_data[i] - 0x57;
- }else return -1;
- hex_data[i] = tmp_dat;
- }
- return 0;
- }
- /*********************************************************
- * @function mypow
- * @role pow库函数的实现,计算num的n次幂,其中n为整数
- * @input num
- * @output n
- * @return 计算结果
- *******************************************************
- static int mypow(int num,int n)
- {
- int powint=1;
- int i;
- for(i=1;i<=n;i++) powint*=num;
- return powint;
- }
- */
- /*********************************************************
- * @function FreeStr
- * @role 删除字符串中的字串,支持16进制数据,无视结束符
- * @input 字符串、字符串总长度、开始删除的起始位置、要删除的长度
- * @output None
- * @return None
- ********************************************************/
- static void FreeStr(charchar *str, int strsiz, int head, int len)
- {
- int i = 0;
- while(len--)
- {
- for(i = head; i < strsiz;i++)
- {
- str[i] = str[i+1];
- }
- }
- }
- #if GU906GSM_EN
- /*********************************************************
- * @function GU906_ParsingSIM
- * @role 解析SIM卡中的短信数据
- * @input 卡中的数据
- * @output None
- * @return 成功返回:0,失败返回:-1
- @data
- +CMGR: "REC READ","18750******",,"2015/03/14 20:02:15+32"
- 124abcABC
- OK
- ********************************************************/
- static int GU906_ParsingSIM(charchar *pinput)
- {
- charchar *p = pinput;
- int i;
- #if DEBUG_EN
- printf("\n分离手机号\n");
- #endif
- if((p = strstr(p,"\",\"")) == 0)
- return -1;
- p += 3;
- memset(sim.phone,0,sizeof(sim.phone));
- for (i = 0; (*p != '\"') && (*p != '\0'); ++i,p++){
- sim.phone[i] = *p;
- }
- sim.phone[i] = '\0';
- #if DEBUG_EN
- printf("sms.phone[%s]\r\n",sim.phone);
- printf("\n分离设备类型\n");
- #endif
- p +=2;
- memset(sim.dev,0,sizeof(sim.dev));
- for (i = 0; (*p != ',') && (*p != '\0'); ++i,p++){
- sim.dev[i] = *p;
- }
- #if DEBUG_EN
- printf("sms.dev[%s]\r\n",sim.dev);
- printf("\n分离时间\n");
- #endif
- p += 2;
- memset(sim.date,0,sizeof(sim.date));
- for (i = 0; (*p != '\"') && (*p != '\0'); ++i,p++){
- sim.date[i] = *p;
- }
- #if DEBUG_EN
- printf("sms.date[%s]\r\n",sim.date);
- printf("\n分离数据\n");
- #endif
- p++;
- memset(sim.data,0,sizeof(sim.data));
- while((*p != '\0') && ((*p == '\n') || (*p == '\r')) ) p++;
- for (i = 0; (*p != '\0') && (*p != '\n') && (*p != '\r'); ++i,p++){
- sim.data[i] = *p;
- }
- sim.data[i] = '\0';
- #if DEBUG_EN
- printf("sms.data:[%s]\r\n",sim.data );
- #endif
- return 0;
- }
- #endif
- /*********************************************************
- * @function GetRecvData
- * @role 提取字符串中跟命令无关的数据,有时在进行命令操作时,
- 会突然收到短信,什么的,这里要做的就是处理并过滤掉这些数据。
- 还有模块突然复位了,这里也做判断,并复位CPU。
- * @input 数据和数据长度
- * @output None
- * @return None
- ********************************************************/
- static void GetRecvData(charchar *pBuff, intint *pLen)
- {
- int rlen = 0;
- char buff[5]="";
- int i = 0;
- charchar *p1 = NULL;
- charchar *p2 = NULL;
- if((pBuff == NULL) || (*pLen == 0))
- return;
- if (((p1 = strstr(pBuff, "+IPD,")) != 0) && ((p2 = strchr(pBuff, ':')) != 0))
- {
- p1+=5;
- for (i = 0; ((p1-pBuff) < *pLen) && (i < 5) && (*p1 != ':'); ++i,++p1) {
- buff[i] = *p1;
- }
- buff[i] = '\0';
- rlen = atoi(buff);
- p2++;
- GPRS_Dlen = ((rlen >= (*pLen - (p2 - pBuff)))?(*pLen - (p2 - pBuff)):rlen);
- memcpy(GPRS_Data, p2,GPRS_Dlen);
- rlen = GPRS_Dlen;
- p1 = strstr(pBuff, "+IPD,");
- p2 = strchr(pBuff, ':');
- rlen += ((p2+1)-p1);
- FreeStr(pBuff, *pLen,p1-pBuff, rlen);
- if((*pLen -rlen) <=3)
- *pLen = 0;
- else
- *pLen -=rlen;
- #if DEBUG_EN
- printf("B[%d][%s]\r\n",*pLen, pBuff);
- #endif
- }
- #if GU906GSM_EN
- else if (strstr(pBuff, "+CMTI:") && ((p1 = strchr(pBuff, ',')) != 0)){ //+CMTI: "SM",2 有短信消息到来
- rlen = 0;
- p1++;
- for(i = 0; *p1 != '\r' && *p1 != '\n' && *p1 != '\0' && rlen < sizeof(SIMDataID);i++, p1++){
- if(*p1 >= '0' && *p1 <= '9')
- SIMDataID[rlen++] = *p1;
- }
- SIMDataID[rlen] = '\0';
- }
- else if ((p1 = strstr(pBuff, "+CMGR:")) != 0){ //读取到短消息
- GU906_ParsingSIM(p1);
- }
- #endif
- else if(strstr(pBuff,"[0000]") || strstr(pBuff,"Build Time"))
- {
- #if (DEBUG_EN == 1)
- printf("restart...\r\n\r\n");
- #endif
- RestartGprs = 1;
- }
- }
- /*********************************************************
- * @function GetFreeBuff
- * @role 处理掉缓存中多余的数据,同时也起到延时200ms的作用,
- 读取数据函数自带延时10ms,所以这里num=20,
- GU906发送命令不能太快,不然GU906会因为处理不过来,而导致出错。
- * @input None
- * @output None
- * @return None
- ********************************************************/
- static void GetFreeBuff(int num)
- {
- char buff[MAXRECVBUFF] = {0};
- int siz = 0;
- while(num--)
- {
- siz = usart4_Receive(buff,MAXRECVBUFF);
- if(siz)
- {
- GetRecvData(buff, &siz);
- }
- }
- }
- /*********************************************************
- * @function SendAT
- * @role 发送AT指令并接收
- * @input gprs:要发送的参数
- * @output out:返回的参数
- * @return 成功返回:_ATOK,失败返回:_ATERROR
- ********************************************************/
- static s8 SendAT(struct GprsData *gprs, charchar *out, u32 Delay)
- {
- int siz = 0;
- int i = 0;
- charchar *p = gprs->order;
- u8 dat[2];
- u8 csq = 0;
- s8 ret = _ATERROR;
- char buff[MAXRECVBUFF] = {0};
- RestartGprs = 0;
- #if (DEBUG_EN == 1)
- printf("\r\n------------------------------\r\n");
- printf("len[%d]\r\n", gprs->olen);
- for(i = 0; i< gprs->olen; i++,++p)
- printf("%c", *p);
- printf("\r\n");
- #endif
- i = 0;
- p = NULL;
- GetFreeBuff(10);
- usart4_Send(gprs->order,gprs->olen);
- if((gprs->type == _GSMSEND) || (gprs->type == _ATATD))
- {
- ret = _ATOK;
- goto GU906_SENDATRET;
- }
- while(1)
- {
- for(i = 0;i<sizeof(buff);i++)
- buff[i]=0;
- siz = 0; i = 0;
- while(siz == 0)
- {
- siz = usart4_Receive(buff,MAXRECVBUFF);
- if(siz){
- #if (DEBUG_EN == 1)
- printf("\r\nrecv:\r\n");
- printf("[%s]\r\n",buff);
- #endif
- GetRecvData(buff, &siz);
- }
- if(i++ > Delay)
- {
- ret = _ATOTIME;
- goto GU906_SENDATRET;
- }
- }
- if(RestartGprs){
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- switch(gprs->type)
- {
- case _AT:
- case _ATE:
- case _ATCNMI:
- case _ATCMGD:
- case _ATCMGF:
- case _ATCSMP:
- case _ATUCS2:
- case _ATATH :
- case _ATGSM :
- case _ATCSTT:
- case _ATCIICR:
- case _ATCIPCFG:
- case _ATCIPPACK:
- case _ATCIPSCONT:
- case _OPENDTU:
- case _CLOSEDTU:
- case _ATGB2312:
- if(strstr(buff, "OK")){
- ret = _ATOK;
- goto GU906_SENDATRET;
- }else if(strstr(buff, "ERROR") || strstr(buff,"NO CARRIER")) {
- GetFreeBuff(100);
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- break;
- case _ATCPMS:
- if(strstr(buff, "OK") && strstr(buff, "+CPMS:")){
- ret = _ATOK;
- goto GU906_SENDATRET;
- }else if(strstr(buff, "ERROR")){
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- break;
- case _ATESIM:
- ret = _ATERROR;
- if(strstr(buff, "OK"))
- {
- if((p = strstr(buff, "+ESIMS: ")) != 0)
- {
- p += 8;
- if(1 == (*p -'0'))
- ret = _ATOK;
- }
- goto GU906_SENDATRET;
- }
- break;
- case _ATCMGS:
- if(strstr(buff, ">")){
- GetFreeBuff(1);
- ret = _ATOK;
- goto GU906_SENDATRET;
- }
- break;
- case _ATCSQ:
- if(strstr(buff, "OK"))
- {
- if((p = strstr(buff, "+CSQ:")) != 0)
- {
- GPRS_ascii_to_hex((u8 *)(p+6), dat, 2);
- csq = dat[0]*10 + dat[1];
- #if DEBUG_EN
- printf("信号:[%d]\r\n", csq);
- #endif
- if (csq < 99 && csq >= GPRSCSQ){ //网络信号要大于GPRSCSQ(18)
- ret = _ATOK;
- goto GU906_SENDATRET;
- } else {
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- }
- }
- else{
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- break;
- case _ATCIPSTARTOK:
- if(strstr(buff, "OK"))
- {
- if (strstr(buff, "+CIPSTART:")) {
- ret = _ATOK;
- goto GU906_SENDATRET;
- }
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }else if(strstr(buff, "ERROR")) {
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- break;
- case _ATCREG:
- if(strstr(buff, "OK"))
- {
- if ((p = strstr(buff, "+CREG: ")) != 0)
- {
- p += 7;
- if(('0' == *p) || ('5' == *p))
- {
- ret = _ATOK;
- goto GU906_SENDATRET;
- }
- }
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }else if(strstr(buff, "ERROR")) {
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- break;
- case _ATCIPSEND:
- if (strstr(buff, ">")) {
- ret = _ATOK;
- goto GU906_SENDATRET;
- }
- else if (strstr(buff, "ERROR")){
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- break;
- case _ATCIPMUX:
- if(strstr(buff, "+CIPMUX: 0") && strstr(buff, "OK")) {
- ret = _ATOK;
- goto GU906_SENDATRET;
- }else if (strstr(buff, "ERROR")){
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- break;
- case _ATCIPMODE:
- if(strstr(buff, "+CIPMODE: ") && strstr(buff, "OK")) {
- ret = _ATOK;
- goto GU906_SENDATRET;
- }else if (strstr(buff, "ERROR")){
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- break;
- case _GPRSSEND:
- if(strstr(buff, "SEND OK")) {
- ret = _ATOK;
- goto GU906_SENDATRET;
- }
- break;
- case _ATCMGR:
- GetRecvData(buff, &siz);
- ret = _ATOK;
- goto GU906_SENDATRET;
- //break;
- case _ATCIPCLOSE:
- if (strstr(buff, "CLOSE OK") || strstr(buff, "+CME ERROR:")) {
- ret = _ATOK;
- goto GU906_SENDATRET;
- }
- else if(strstr(buff, "ERROR")){
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- break;
- case _ATCIPSTART:
- if(!GPRS_Dtu_ConLock)
- {
- if(strstr(buff, "CONNECT OK")){
- ret = _ATOK;
- goto GU906_SENDATRET;
- }
- else if(strstr(buff, "RECONNECTING") || strstr(buff, "ERROR") || strstr(buff, "CONNECT FAIL")){
- GetFreeBuff(100);
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- }
- else if(strstr(buff, "OK")){
- ret = _ATOK;
- goto GU906_SENDATRET;
- }
- else if(strstr(buff, "ERROR")){
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- break;
- case _GSMSENDEND:
- GetFreeBuff(100);
- ret = _ATOK;
- goto GU906_SENDATRET; //忽略返回信息
- /*
- if(strstr(buff, "+CMGS:")) {
- if(strstr(buff, "OK"))
- return _ATOK;
- lock = 1;
- }
- else if(lock && strstr(buff, "OK")) {
- return _ATOK;
- }else return _ATOK; //忽略返回信息
- break;
- */
- case _ATCIPSCONT_C:
- if(strstr(buff,"OK"))
- {
- printf("Line:%d\r\n",__LINE__);
- if(0 != (p = strstr(buff,"+CIPMODE: ")))
- {
- p += 10;
- printf("Line:%d\r\n",__LINE__);
- if(1 == (*p -'0'))
- {
- printf("Line:%d\r\n",__LINE__);
- if(0 != (p = strstr(buff,"+CIPSTART: ")))
- {
- printf("Line:%d\r\n",__LINE__);
- if(strstr(buff,"218.66.59.201") && strstr(buff,"8888"))
- {
- printf("DTU OK\r\n");
- GPRS_Dtu_ConLock = 1;
- ret = _ATOK;
- goto GU906_SENDATRET;
- }
- }
- }
- }
- GPRS_Dtu_ConLock = 0;
- ret = _ATOK;
- goto GU906_SENDATRET;
- }else if(strstr(buff, "ERROR")){
- ret = _ATERROR;
- goto GU906_SENDATRET;
- }
- break;
- default: break;
- }
- }
- GU906_SENDATRET:
- return ret;
- }
- /*********************************************************
- * @function GU906_ExecuteOrder
- * @role 执行命令
- * @input None
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- static s8 GU906_ExecuteOrder(charchar *Order, u32 len, enum order type, u32 num)
- {
- u32 i = 0;
- u32 delay_time = 1000;
- s8 ret = _ATOTIME;
- struct GprsData gprs;
- if(type == _ATCIPSTART)
- delay_time = 4000;
- if(type == _GPRSSEND)
- delay_time = 10;
- gprs.order = Order;
- gprs.olen = len;
- gprs.type = type;
- while((ret = SendAT(&gprs, NULL, delay_time)) != _ATOK)
- {
- if(ret == _ATERROR) {
- if(++i >= num) return _ATERROR;
- delay_s(1);
- }else return _ATOTIME;
- }
- return _ATOK;
- }
- /*********************************************************
- * @function GU906_init
- * @role GSM初始化
- * @input None
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- s8 GU906_init(void)
- {
- s8 ret = _ATOTIME;
- // 开回显:ATE1 关回显:ATE0
- if(_ATOK != (ret = GU906_ExecuteOrder(ATE(0), strlen(ATE(0)), _ATE, 2)))
- return ret;
- // 查询卡是否存在
- if(_ATOK != (ret = GU906_ExecuteOrder(ATESIM, strlen(ATESIM), _ATESIM, 10)))
- return ret;
- #if GU906GSM_EN
- // 设置短信模式为text模式
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCMGF, strlen(ATCMGF), _ATCMGF, 2)))
- return ret;
- // 设置短信存储单元为SIM卡
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCPMS, strlen(ATCPMS), _ATCPMS, 2)))
- return ret;
- // 设置这组参数来了新信息存储起来
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCNMI, strlen(ATCNMI), _ATCNMI, 2)))
- return ret;
- #endif
- //删除SIM卡中的所有短信
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCMGD, strlen(ATCMGD), _ATCMGD, 2)))
- return ret;
- //查询信号强度 信号强度大于等于18才行
- while(_ATOK != (ret = GU906_ExecuteOrder(ATCSQ, strlen(ATCSQ), _ATCSQ, 60)))
- {
- if(ret == _ATOTIME) return ret;
- }
- return _ATOK;
- }
- /*********************************************************
- * @function GU906_Module_State
- * @role 判断GU906的状态
- * @input None
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- s8 GU906_Module_State(void)
- {
- return GU906_ExecuteOrder(AT, strlen(AT), _AT, 0);
- }
- /*********************************************************
- * @function GU906_TCP_Socket
- * @role 进行TCP连接
- * @input IP地址与端口
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- s8 GU906_TCP_Socket(struct Gprs_Config *GprsCon)
- {
- char cipstart[100] = {0};
- s8 ret = _ATOTIME;
- if(GprsCon->server_ip == NULL || !GprsCon->server_port) return ret;
- if(!strlen((charchar *)GprsCon->server_ip)) return ret;
- //确保模块以及注册到GSM网络
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCREG, strlen(ATCREG), _ATCREG, 2)))
- return ret;
- //让模块激活 GPRS 网络,在需要反复建立 TCP 链接的场合可提高速度
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIICR, strlen(ATCIICR), _ATCIICR, 2)))
- return ret;
- //查询当前是否有网络连接
- while(_ATOK == GU906_ExecuteOrder(ATCIPSTARTOK, strlen(ATCIPSTARTOK), _ATCIPSTARTOK, 0))
- {
- //关闭网络连接
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPCLOSE, strlen(ATCIPCLOSE), _ATCIPCLOSE, 2)))
- return ret;
- //保存设置
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPSCONT(0), strlen(ATCIPSCONT(0)), _ATCIPSCONT, 2)))
- return ret;
- }
- //单链接模式
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPMUX, strlen(ATCIPMUX), _ATCIPMUX, 2)))
- return ret;
- //非数据透传输模式
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPMODE(0), strlen(ATCIPMODE(0)), _ATCIPMODE, 2)))
- return ret;
- //自动启动连接命令
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPCFG(0), strlen(ATCIPCFG(0)), _ATCIPCFG, 2)))
- return ret;
- //心跳包设置
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPPACK(0), strlen(ATCIPPACK(0)), _ATCIPPACK, 2)))
- return ret;
- //连接到服务器
- //cipstart=(char *)mymalloc(100);
- //if(cipstart==NULL) return -1;
- sprintf(cipstart, ATCIPSTART,"TCP", GprsCon->server_ip, GprsCon->server_port);
- ret = GU906_ExecuteOrder(cipstart, strlen(cipstart), _ATCIPSTART, 3);
- //myfree(cipstart);
- return ret;
- }
- /*********************************************************
- * @function GU906_DTU_Socket
- * @role 设置透传模式
- * @input IP地址与端口
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- s8 GU906_DTU_Socket(struct Gprs_Config *GprsCon)
- {
- char atorder[100] = "";
- s8 ret = _ATOTIME;
- if(GprsCon->server_ip == NULL || !GprsCon->server_port) return ret;
- if(!strlen((charchar *)GprsCon->server_ip)) return ret;
- //atorder=(char *)mymalloc(100);
- //if(atorder==NULL) return -1;
- //查询数据透设置情况
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPSCONT_C, strlen(ATCIPSCONT_C), _ATCIPSCONT_C, 2)))
- goto GU906_DTU_SOCKETEND;
- if(!GPRS_Dtu_ConLock)
- {
- //设置账号
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCSTT, strlen(ATCSTT), _ATCSTT, 2)))
- goto GU906_DTU_SOCKETEND;
- //透传参数设置
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPCFG(1), strlen(ATCIPCFG(1)), _ATCIPCFG, 2)))
- goto GU906_DTU_SOCKETEND;
- //设置心跳
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPPACK(0), strlen(ATCIPPACK(0)), _ATCIPPACK, 2)))
- goto GU906_DTU_SOCKETEND;
- //设置设备注册包
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPPACK(1), strlen(ATCIPPACK(1)), _ATCIPPACK, 2)))
- goto GU906_DTU_SOCKETEND;
- //单链接模式
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPMUX, strlen(ATCIPMUX), _ATCIPMUX, 2)))
- goto GU906_DTU_SOCKETEND;
- //数据透传输模式
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPMODE(1), strlen(ATCIPMODE(1)), _ATCIPMODE, 2)))
- goto GU906_DTU_SOCKETEND;
- //保存设置
- sprintf(atorder, ATCIPSCONT(1),"TCP", GprsCon->server_ip, GprsCon->server_port);
- if(_ATOK != (ret = GU906_ExecuteOrder(atorder, strlen(atorder), _ATCIPSCONT, 2)))
- goto GU906_DTU_SOCKETEND;
- GPRS_Dtu_ConLock = 1;
- }
- //建立数据透连接
- sprintf(atorder, ATCIPSTART, "TCP", GprsCon->server_ip, GprsCon->server_port);
- if(_ATOK != (ret = GU906_ExecuteOrder(atorder, strlen(atorder), _ATCIPSTART, 2)))
- goto GU906_DTU_SOCKETEND;
- GU906_DTU_SOCKETEND:
- //myfree(atorder);
- return ret;
- }
- /*********************************************************
- * @function GU906_DtuOrAT
- * @role 透传模式与AT模式转换
- * @input None
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- s8 GU906_DtuOrAT(u8 type)
- {
- s8 ret = _ATERROR;
- if(type)
- {
- while(!GPRS_Dtu_ConLock)
- {
- //打开透传
- delay_s(2);
- if(_ATOK != (ret = GU906_ExecuteOrder(OPENDTU, strlen(OPENDTU), _OPENDTU, 0)))
- goto GU906_DTUOFFONEND;
- GPRS_Dtu_ConLock = 1;
- }
- }
- else
- {
- while(GPRS_Dtu_ConLock)
- {
- //关闭透传
- delay_s(2);
- if(_ATOK != (ret = GU906_ExecuteOrder(CLOSEDTU, strlen(CLOSEDTU), _CLOSEDTU, 0)))
- {
- delay_s(1);
- if(_ATOK != (GU906_Module_State()))
- goto GU906_DTUOFFONEND;
- }
- GPRS_Dtu_ConLock = 0;
- }
- }
- GU906_DTUOFFONEND:
- return ret;
- }
- /*********************************************************
- * @function GU906_GPRS_write
- * @role gprs发送数据
- * @input 要发送的数据与数据长度
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- s8 GU906_GPRS_write(char* pdat, int len)
- {
- char atorder[20] = "";
- s8 ret = -1;
- if(strlen(pdat) == 0) return 0;
- //atorder = (char *)mymalloc(20);
- //if(atorder == NULL) return -1;
- if(!GPRS_Dtu_ConLock)//非数据透模式
- {
- //设置数据长度
- sprintf(atorder, ATCIPSEND(1), len);
- if(_ATOK != (ret = GU906_ExecuteOrder(atorder, strlen(atorder), _ATCIPSEND, 0)))
- goto GU906_GPRS_WRITERET;
- //发送数据
- if(_ATOK != (ret = GU906_ExecuteOrder(pdat, len, _GPRSSEND, 0)))
- goto GU906_GPRS_WRITERET;
- }
- else
- {
- //发送数据
- usart4_Send(pdat, len);
- ret = _ATOK;
- }
- GU906_GPRS_WRITERET:
- //myfree(atorder);
- return ret;
- }
- /*********************************************************
- * @function GU906_GPRS_read
- * @role 查询是否接收到数据
- * @input 输出缓存大小
- * @output 接收到的数据
- * @return 接收到的数据长度
- ********************************************************/
- u32 GU906_GPRS_read(charchar *pout, int len)
- {
- int i = 0;
- if(!GPRS_Dtu_ConLock)
- {
- GPRSREAD:
- if(GPRS_Dlen){
- for(i = 0;(i < GPRS_Dlen) && (i < (len -1)); i++){
- pout[i] = GPRS_Data[i];
- }
- memset(GPRS_Data, 0, sizeof(GPRS_Data));
- GPRS_Dlen = 0;
- return i;
- }else{
- GetFreeBuff(1);
- if(GPRS_Dlen)
- goto GPRSREAD;
- }
- }
- else
- {
- return usart4_Receive(pout,len);
- }
- return 0;
- }
- /*********************************************************
- * @function GU906_make_phone
- * @role 向指定的手机拨号
- * @input 手机号
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- s8 GU906_make_phone(charchar *phone)
- {
- char mphone[20]="";
- sprintf(mphone, ATATD, phone);
- return GU906_ExecuteOrder(mphone, strlen(mphone), _ATATD, 0);
- }
- /*********************************************************
- * @function GU906_Answer_Phone
- * @role 等待电话被接听
- * @input 手机号
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- s8 GU906_Answer_Phone(u32 Delay)
- {
- int siz = 0;
- u32 i = 0;
- char buff[MAXRECVBUFF] = "";
- i = 0;
- while(1)
- {
- siz = 0;
- siz = usart4_Receive(buff,MAXRECVBUFF);
- if(siz){
- GetRecvData(buff, &siz);
- if(strstr(buff, "+COLP:") && strstr(buff, "OK")){
- return _ATOK;
- }else if(strstr(buff, "NO CARRIER") || strstr(buff, "+CREG: 1") || strstr(buff, "ERROR")){
- return _ATERROR;
- }
- }
- if(i++ > Delay)
- {
- return _ATOTIME;
- }
- }
- }
- /*********************************************************
- * @function GU906_end_phone
- * @role 挂机
- * @input None
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- s8 GU906_end_phone(void)
- {
- return GU906_ExecuteOrder(ATATH, strlen(ATATH), _ATATH, 0);
- }
- #if GU906GSM_EN
- /*********************************************************
- * @function GU906_Chinese_text
- * @role 向指定的手机发送中文短信
- * @input phone 手机号指针,pmsg 短消息指针
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- s8 GU906_Chinese_text(charchar *phone,char* pmsg)
- {
- s8 ret = _ATOTIME;
- char atphone[50] = "";
- char end[]={0x1A,0x00};
- if(strlen(phone) != 11) return _ATERROR;
- //atphone = (char *)mymalloc(50);
- //if(atphone == NULL) return -1;
- //设置短消息为txet模式
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCMGF, strlen(ATCMGF), _ATCMGF, 2)))
- goto GU906_CHINESE_TEXTEND;
- //设置GB2312编码
- if(_ATOK != (ret = GU906_ExecuteOrder(ATGB2312, strlen(ATGB2312), _ATGB2312, 2)))
- goto GU906_CHINESE_TEXTEND;
- //设置这组参数来了新信息存储起来
- if(_ATOK != (ret = GU906_ExecuteOrder(ATCNMI, strlen(ATCNMI), _ATCNMI, 2)))
- goto GU906_CHINESE_TEXTEND;
- //设置用户手机号
- sprintf(atphone,ATCMGS,phone);
- if(_ATOK != (ret = GU906_ExecuteOrder(atphone, strlen(atphone), _ATCMGS, 2)))
- goto GU906_CHINESE_TEXTEND;
- //发送数据
- if(_ATOK == (ret = GU906_ExecuteOrder(pmsg, strlen(pmsg), _GSMSEND, 0)))
- {
- ret = GU906_ExecuteOrder(end, 1, _GSMSENDEND, 0);
- }
- GU906_CHINESE_TEXTEND:
- //myfree(atphone);
- return ret;
- }
- /*********************************************************
- * @function GU906_Read_SIM
- * @role 读取短信信息
- * @input 短信在SIM卡中的位置
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- static s8 GU906_Read_SIM(charchar *pnum)
- {
- s8 ret = _ATOTIME;
- char cmgr[20]="";
- //读取短信的编码格式为GB2312
- if(_ATOK != (ret = GU906_ExecuteOrder(ATGB2312, strlen(ATGB2312), _ATGB2312, 2)))
- return ret;
- //读取短消息
- sprintf(cmgr,ATCMGR,pnum);
- return GU906_ExecuteOrder(cmgr, strlen(cmgr), _ATCMGR, 2);
- }
- /*********************************************************
- * @function GU906_DeleteSms
- * @role 删除SIM卡中的所有短信
- * @input None
- * @output None
- * @return 成功返回:_ATOK,失败返回:_ATERROR,超时返回:_ATOTIME
- ********************************************************/
- static int GU906_DeleteSms(void)
- {
- return GU906_ExecuteOrder(ATCMGD, strlen(ATCMGD), _ATCMGD, 2);
- }
- /*********************************************************
- * @function GU906_Read_UserSMS
- * @role 查询并读取短信数据
- * @input None
- * @output None
- * @return 0,接收到新数据,-1,未接收到新数据
- ********************************************************/
- s8 GU906_Read_UserSMS(void)
- {
- SMSREAD:
- if(strlen(SIMDataID)){
- #if DEBUG_EN
- printf("SIMDataID[%s]\r\n",SIMDataID);
- #endif
- GU906_Read_SIM(SIMDataID);
- GU906_DeleteSms();
- memset(SIMDataID,0,sizeof(SIMDataID));
- return 0;
- }else{
- GetFreeBuff(1);
- if(strlen(SIMDataID))
- goto SMSREAD;
- }
- return -1;
- }
- #endif
gu906.文件如下
- #ifndef _GU906_H_
- #define _GU906_H_
- #include "sys.h"
- #define GU906GSM_EN 1 //是否开启短信功能
- #define GPRSCSQ 18 //信号强度,在使用GPRS功能时,最低要求信号强度不得低于18
- #define _ATOK 0 //执行成功
- #define _ATERROR -1 //执行错误
- #define _ATOTIME -2 //执行超时
- #define _LINKNOT -3 //掉线了
- struct Gprs_Config{
- u8 *server_ip; //服务器IP
- u32 server_port; //服务器端口
- };
- #if GU906GSM_EN
- //根据实际内存情况而定
- struct user_simdata{
- char phone[15]; //用户手机号
- char dev[50]; //用户使用的设备
- char date[50]; //接收时间
- char data[200]; //接收的数据
- };
- extern struct user_simdata sim;
- s8 GU906_Read_UserSMS(void);
- s8 GU906_Chinese_text(charchar *phone,char* pmsg);
- #endif
- s8 GU906_init(void);
- s8 GU906_Module_State(void);
- s8 GU906_TCP_Socket(struct Gprs_Config *GprsCon);
- s8 GU906_DTU_Socket(struct Gprs_Config *GprsCon);
- s8 GU906_GPRS_write(char* pdat, int len);
- u32 GU906_GPRS_read(charchar *pout, int len);
- s8 GU906_make_phone(charchar *phone);
- s8 GU906_Answer_Phone(u32 Delay);
- s8 GU906_end_phone(void);
- s8 GU906_DtuOrAT(u8 type);
- #endif
main.c
- #include <string.h>
- #include <stdlib.h>
- #include "stdio.h"
- #include "delay.h"
- #include "GU906.h"
- #include "config.h"
- #include "usart1.h"
- #include "usart4.h"
- int main(void)
- {
- u32 ret = 0;
- char buff[200]="";
- struct Gprs_Config GprsCon;
- delay_init();
- usart4_Configuration(115200); //GU900默认通信波特率是115200
- usart1_Configuration(115200); //调试输出端口波特率设置
- delay_s(5); //刚上电 要等待10秒,等待GU906模块初始化完成
- printf("\r\nBegin...\r\n");
- GprsCon.server_ip = (u8 *)"210.66.59.211"; //GPRS通信时的服务器IP
- GprsCon.server_port = atoi("8888"); //GPRS通信时的服务器端口
- //GSM初始化
- while(1)
- {
- if(_ATOK == GU906_init()){
- printf("GU906 init ok.\r\n\r\n");
- break;
- }
- printf("init error.\r\n");
- delay_s(1);
- }
- /*****************************************************************************/
- //GU906 GPRS TCP 非透传模式通信测试
- while(1)
- {
- if(_ATOK == GU906_TCP_Socket(&GprsCon))
- {
- printf("socket ok\r\n\r\n");
- delay_s(3);
- while(1)
- {
- ret = GU906_GPRS_read(buff, 200);
- if(ret)
- {
- printf("GPRS:[%d][%s]\r\n", ret,buff);
- if(_ATOK != GU906_GPRS_write((charchar *)"OK", 2))
- {
- printf("Send Error.\r\n");
- }
- }
- }
- }
- printf("GU906_TCP_Socket ERROR.\r\n");
- while(1);
- }
- /*******************************************************************************/
- /*****************************************************************************/
- //GU906 GPRS TCP 透传模式通信测试
- while(1)
- {
- if(_ATOK == GU906_DTU_Socket(&GprsCon))
- {
- printf("socket ok\r\n\r\n");
- delay_s(3);
- while(1)
- {
- ret = GU906_GPRS_read(buff, 200);
- if(ret)
- {
- printf("GPRS:[%d][%s]\r\n", ret,buff);
- if(_ATOK != GU906_GPRS_write((charchar *)buff, ret))
- {
- printf("Send Error.\r\n");
- }
- if(strstr(buff,"CLOSE"))
- {
- GU906_DtuOrAT(0);
- }
- if(strstr(buff,"OPEN"))
- {
- GU906_DtuOrAT(1);
- }
- }
- }
- }
- printf("GU906_TCP_Socket ERROR.\r\n");
- while(1);
- }
- /*******************************************************************************/
- /*****************************************************************************/
- //发送短信测试
- while(_ATOK != GU906_Chinese_text("18750******", "123abd 测试"))
- {
- delay_s(5);
- }
- //接收短信测试
- while(1)
- {
- if(0 == GU906_Read_UserSMS())
- {
- printf("------------------------------\r\n");
- printf("号码:%s\r\n",sim.phone);
- printf("设备:%s\r\n",sim.dev);
- printf("时间:%s\r\n",sim.date);
- printf("信息:%s\r\n",sim.data);
- }
- delay_ms(50);
- }
- /******************************************************************************/
- /*****************************************************************************/
- //打电话测试
- if (_ATOK == GU906_make_phone("18750******"))
- {
- //等待接听
- while(_ATOTIME == GU906_Answer_Phone(1000))
- {
- printf("make ok\r\n");
- GU906_end_phone();
- }
- printf("make ok\r\n");
- }
- else
- {
- printf("make error\r\n");
- //SoftReset();
- }
- /******************************************************************************/
- while(1);
- }
工程下载:
链接:http://pan.baidu.com/s/1dEQwME9 密码:9fwz
STM32F103 GU906B模块GPRS、短信收发、拨号等功能的实现的更多相关文章
- linux下利用GPRS模块发短信、打电话
一.开发环境 内核版本:linux-3.0 开发板:FL2440(nandflash:K9F1G08 128M) GPRS模块:SIM900 二.与发短信和拨号相关的 AT 指 ...
- Linux-C实现GPRS模块发送短信
“GSM模块,是将GSM射频芯片.基带处理芯片.存储器.功放器件等集成在一块线路板上,具有独立的操作系统.GSM射频处理.基带处理并提供标准接口的功能模块.GSM模块根据其提供的数据传输速率又可以分为 ...
- 树莓派.GPRS.短信接收器
起因 曾经用过西门子出的短信猫, 好处是直接有SDK开发包, 不会硬件开发也能直接使用 缺点也是明显的, 就是只支持Windows系统, 另外就是在Windows下工作很不稳定, 隔开几天就会出现收不 ...
- 在Linux下用C语言实现短信收发
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lyserver/archive/2008/10/01/3007090.aspx 首先,我根据功能需要创建了几个头文件 ...
- 使用python移动飞信模块发送短信
作者:miaoo 1.应用场景 由于自己做的一个系统需要用到发送短信到自己手机的功能,于是搜索了一下,发现了一个通过移动飞信通道发送短信开源库:PyFetion PyFetion 模拟实现了飞信的通信 ...
- iOS打电话、发短信、发邮件功能开发
本文转载至 http://www.lvtao.net/ios/506.html 今天把APP里常用小功能 例如发短信.发邮件.打电话.全部拿出来简单说说它们的实现思路. 1.发短信实现打电话的功能,主 ...
- Android 节日短信送祝福(功能篇:1-数据库操作类与自定义ContentProvider)
首先,还是展示一下部分目录结构: 在节日短信送祝福的功能实现方面,为了能够方便直观展示实现过程,小编我以Java文件为基础,一个一个来展示,免得到时候这个java文件写点,一下又跳到另外一个java ...
- Android短信收发(二)
接收SMS类,代码如下 //for receive SMS private SmsReceiver mSmsReceiver; @Override protected void onResume() ...
- iOS 打电话、发短信、发邮件功能
打电话 方法1 最简单最直接的方式:直接跳到拨号界面 NSURL *url = [NSURL URLWithString:@"tel://10010"]; [[UIApplicat ...
随机推荐
- loadrunner场景执行出现:Failed to Initialize. Reason: TimeOut
问题1: Failed to Initialize. Reason: TimeOut LoadRunner的异常原因(Failed to Initialize. Reason: TimeOut) ...
- ul>li中自定义属性后取值的问题
动态赋值的li: $.ajax({ type: "POST", url: "${base}/before/subDemand/listType", succes ...
- MVC Partial页面的使用
先建立Action: public PartialViewResult CurrentCount() { ViewBag.Count = CurrentUserCount; return Partia ...
- Ngnix的日志管理和用定时任务完成日志切割
一.日志管理 先来看看ngnix的配置文件的server段 接下来我们解释一下默认格式的具体意思 #log_format main '$remote_addr(远程IP) - $remote_user ...
- Java中的强引用,软引用,弱引用
作者:winterSunshine链接:https://www.zhihu.com/question/37401125/answer/100981172来源:知乎著作权归作者所有.商业转载请联系作者获 ...
- codevs 5294 挖地雷
5294 挖地雷 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个地图上有N个地窖(N<=20),每个地窖中埋有一 ...
- 【轮廓线DP】POJ2411-Mondriaan's Dream
今天美国的院士过来讲课XD以为会很无聊但是谜之好听,而且英语基本上都听懂了的样子♪(´▽`) 逃到图书馆来写解题报告 [题目大意] 给出一个m*n的方格,用2*1的骨牌覆盖有几种情况. [思路] 最基 ...
- 2017-2018-1 JAVA实验站 冲刺 day01
2017-2018-1 JAVA实验站 冲刺 day01 各个成员在 Alpha 阶段认领的任务 小组成员 分工 任务量 张韵琪 写博客.后期市场推广,营销.打杂.各职能的配合 齐力锋 提供宣传用图. ...
- Hash表及hash算法的分析
Hash表中的一些原理/概念,及根据这些原理/概念: 一. Hash表概念 二. Hash构造函数的方法,及适用范围 三. Hash处理冲突方法,各自特征 四. ...
- Dubbo整合SpringCloud图片显示问题
Dubbo整合SpringCloud图片显示问题 Tips:公司项目,记录一点经验吧,理解的不对的地方欢迎大神指点 问题:商品图片上传功能(公司没有专门文件服务器)写的保存目录直接是保存在docker ...