找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 19518|回复: 4
打印 上一主题 下一主题
收起左侧

SIM900A模块短信读取函数详解- 想做手机的人可以参考

[复制链接]
跳转到指定楼层
楼主
ID:72008 发表于 2015-1-12 14:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
       经过两天的时间,一共分析了两个函数:手机拨接电话和手机读取短信函数。这两天tmd除了吃饭,睡觉和跑步外,时间全部耗在这上面了。不过收获也很大,关键是字符和字符串处理方面的知识收获较大。现在终于可以完工了,将自己的心血注释奉献出来,以供同道中人参考;当然要与原子的SIM900A模块程序其它源码对应才有意义。

///////////////////////////////////////////////////////// //短信测试部分代码:

//SIM900A读短信测试
void sim900a_sms_read_test(void)
{
        u8 *p,*p1,*p2;
        u8 timex=0;
        u8 msgindex[3];
        u8 msglen=0;
        u8 msgmaxnum=0;                //短信最大条数
        u8 key=0;
        u8 smsreadsta=0;        //是否在短信显示状态
        p=mymalloc(SRAMIN,200);//申请200个字节的内存
        LCD_Clear(WHITE);
        POINT_COLOR=RED;
        Show_Str_Mid(0,30,"ATK-SIM900A 读短信测试",16,240);                                             
        Show_Str(30,50,200,16,"读取:     总信息:",16,0);        
        kbd_fn_tbl[0]="读取";
        kbd_fn_tbl[1]="返回";
        sim900a_load_keyboard(0,180,(u8**)kbd_tbl1);//显示键盘  
        while(1)
        {
                key=sim900a_get_keynum(0,180);
                if(key)  /* 下面的操作都是基于触摸键有被按下  */
                { /*△*/
                        if(smsreadsta)/*一旦读取到短信内容,即LCD上显示读取到的短信内容,这时按任意键都会清除显示的短信内容*/
                        {
                                LCD_Fill(30,75,239,179,WHITE);/*清除显示的短信内容*/
                                smsreadsta=0;
                        }
                        if(key<10||key==11)/* key11对应“0”,key<10对应“1-9”号键 */
                        {
                                if(msglen<2) /*“msglen<2”确保读取的短信数小于100;即msgindex[0]和msgindex[1];因为一共只有50条短信  */
                                {/*msgindex[msglen]短信索引号,即告诉模块想要读哪条短信,首次进入时msglen==0,执行msglen++(msglen++是后自增,其整体的值是msglen加1之前的值,如:int i=3;int j=i++;这时j的值是3,i的值是4;也就是说这时 msgindex[msglen++]==msgindex[0],msglen则等于1;所以msgindex[0]= kbd_tbl[key-1][0]; 假设首次按下“8”,这时msglen++==0,所以msgindex[0]= 8;当再按下“8”时,则执行msglen++==1,msglen==2,msgindex[1]=8;因为这时msglen==2,所以执行下面的if(msglen==2)语句;即得出key值*/
                                   msgindex[msglen++]=kbd_tbl[key-1][0];
                    /* 本句等价于msgindex[msglen++]=*kbd_tbl[key-1]; */
                                   u2_printf("AT+CLDTMF=2,\"%c\"\r\n",kbd_tbl[key-1][0]);
                 /* 本句等价于u2_printf("AT+CLDTMF=2,\"%c\"\r\n",*kbd_tbl[key-1]); */
                                }  /* "AT+CLDTMF=2"命令,测试DTMF音,时长2秒 ,将命令和键值发送给模块,同时每隔2s都会有返回值
                        功能:每拨一个数字键(只对0-9号数字键有效)耳机得到模块返回的发出相应的拨号音*/
                                if(msglen==2)
                                {/* “msgindex[0]-'0'”短信“十位”数;“msgindex[1]-'0'”个位数 */
                                        key=(msgindex[0]-'0')*10 + msgindex[1]-'0';
       /* key键值等于“十位”加“个位”之和;确保key的取值范围在0-99!字符与字符相减,就是他们的ASCII码相减,得到整数值,
                                                 得到一个比较值,就是谁前谁后; 例如 'c'-'a' 的就是:2*/
                                        if(key>msgmaxnum)
                                        { /* msgmaxnum是短信最多条数值,该值的大小由模块查询可知 */
                                          msgindex[0]=msgmaxnum/10+'0';/*这里“+'0'”的意思是字符“0”,在LCD上以十进制显示*/
                                          msgindex[1]=msgmaxnum%10+'0'; /*只要用了单引号' ',这就是一个字符。50对10取余结果为0*/
                                        }/* 这种算法记住! */
                                }
                        }else
                        {
                                if(key==13)if(msglen)msglen--;//删除  
                                if(key==14&&msglen)//执行读取短信
                                {
                                  LCD_Fill(30,75,239,179,WHITE);//清除之前的显示                    
                                  sprintf((char*)p,"AT+CMGR=%s",msgindex);/*AT+CMGR=3的意思是,向sim卡读取3号短信命令*/
/* sprintf()函数的意思是将AT+CMGR=msgindex指令存储在P指针,并将AT+CMGR=msgindex以字符串形式发送给串口以实现向sim卡发送读取3号短信命令,本例中sprintf()函数非常重要,在这里相当于执行了向sim900a模块发送字符串(即命令)任务,实际上就是把P的内容发送给串口USART2_TX_DATA寄存器*/
                                 if(sim900a_send_cmd(p,"+CMGR:",200)==0)/*读取短信,以下都是基于cpu收到了来自模块的返回值*/
                                  { /*第一次发送AT+CMGR=2(即msgindex值)的时候,SIM900A模块返回的是(省略了多余的回车换行和“OK”等字符串,下同):+CMGR: "REC UNREAD","+8613560491039","@ZF","13/05/01,16:06:53+32"00410054004B002D00530049004D00390030003000414E2D82F1658777ED4FE16D4B8BD50020  */
                                                POINT_COLOR=RED;
                                                Show_Str(30,75,200,12,"状态:",12,0);
                                                Show_Str(30+75,75,200,12,"来自:",12,0);
                                                Show_Str(30,90,200,12,"接收时间:",12,0);
                                                Show_Str(30,105,200,12,"内容:",12,0);
                                                POINT_COLOR=BLUE;
                                                if(strstr((const char*)(USART2_RX_BUF),"UNREAD")==0)
                          /* 其中:"REC UNREAD",表示该短信没有被读取过,也就是未读短信。  */
                          Show_Str(30+30,75,200,12,"已读",12,0);
                                                else Show_Str(30+30,75,200,12,"未读",12,0);
                                                p1=(u8*)strstr((const char*)(USART2_RX_BUF),",");
                                                p2=(u8*)strstr((const char*)(p1+2),"\"");
                                                p2[0]=0;//加入结束符
                                                sim900a_unigbk_exchange(p1+2,p,0);        /*将unicode字符转换为gbk码  */
                                                Show_Str(30+75+30,75,200,12,p,12,0);        //显示电话号码
                                                p1=(u8*)strstr((const char*)(p2+1),"/");
                                                p2=(u8*)strstr((const char*)(p1),"+");
                                                p2[0]=0;//加入结束符
                                                Show_Str(30+54,90,200,12,p1-2,12,0);/*显示接收时间  */
                                                p1=(u8*)strstr((const char*)(p2+1),"\r"); /*寻找回车符*/
                                                sim900a_unigbk_exchange(p1+2,p,0);        /*将unicode字符转换为gbk码*/
                                                Show_Str(30+30,105,180,75,p,12,0);        /*显示短信内容*/
                                                smsreadsta=1;         /*标记有显示短信内容,这时按任意键都会清除显示的短信内容 */
                                  }else
                                        {
                                                Show_Str(30,75,200,12,"无短信内容!!!请检查!!",12,0);
                                                delay_ms(1000);
                                                LCD_Fill(30,75,239,75+12,WHITE);//清除显示
                                        }          
                                        USART2_RX_STA=0;
                                }
                                if(key==15)break;/*结束while循环回到短信收发界面*/
                        }
                        msgindex[msglen]=0; /*每拨一个短信索引号都在其后加一个结束符!本句很重要!字符串的结束符是'\0' 也是0;  */
                        LCD_Fill(30+40,50,86,50+16,WHITE);  /* */
                        Show_Str(30+40,50,86,16,msgindex,16,0);  /*显示要读取sim卡中短信索引号即要读取几号短信*/         
                } /*△*/   /*数组名msgindex代表整个msgindex数组空间,即显示整个msgindex空间内容 */
                if(timex==0)                //2.5秒左右更新一次
                {
                        if(sim900a_send_cmd("AT+CPMS?" , "+CPMS:",200)==0)  /* 查询优选消息存储器 */
                        { /* AT+CPMS,用于查询/设置优选消息存储器,通过发送:AT+CPMS?,可以查询当前SIM卡最大支持多少条短信存储,
       以及当前存储了多少条短信等信息。如发送AT+CPMS?命令返回:+CPMS: "SM",21,50,"SM",21,50,21是指已经一共有了21条短信,50是指最大能存储50条短信 */
                                p1=(u8*)strstr((const char*)(USART2_RX_BUF),","); /*P1指向第一个逗号 */
                                p2=(u8*)strstr((const char*)(p1+1),",");/* P2指向第二个逗号 */
                                p2[0]='/'; /* 将P2指针的第一个字符赋值为'/'以在LCD上显示出来,p2[1]='5',p2[2]='0', p2[3]==',' ;   */
                                if(p2[3]==',')/* 小于64K SIM卡,最多存储几十条短信 */
                                {/* if(p2[3]==',')语句的意思:  */
                                        msgmaxnum=(p2[1]-'0')*10+p2[2]-'0'; /* 获取最大存储短信条数50 */
                                        p2[3]=0;  /* 加入结束符,目的是为了在LCD上显示"21/50" ;有了这个结束符可以推出:P1+1的内容是"21/50"  */
                                }else /* 如果是64K SIM卡,则能存储100条以上的信息 */
                                {
                                        msgmaxnum=(p2[1]-'0')*100+(p2[2]-'0')*10+p2[3]-'0';//获取最大存储短信条数
                                        p2[4]=0;
                                }  /* 这种字符串的与字符的取值方法值得学习,必须温故!    */
                                sprintf((char*)p,"%s",p1+1); /* 将指针“P1+1”的字符串存储到P,P1+1的内容是"21/50" */
                                Show_Str(30+17*8,50,200,16,p,16,0);  /* 显示sim卡一共已存储短信数 ,如显示:21/50  */
                                USART2_RX_STA=0;        /* 重新准备接受数据 */       
                        }
                }       
                if((timex%20)==0)LED0=!LED0;//200ms闪烁
                timex++;
                delay_ms(10);
                if(USART2_RX_STA&0X8000)sim_at_response(1);/*检查从GSM模块接收到的数据,不断扫描接收来自模块的返回值 */
        }
        myfree(SRAMIN,p);
}

该睡觉了!
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶3 踩
回复

使用道具 举报

沙发
ID:82513 发表于 2015-6-9 14:28 | 只看该作者
请问楼主  if(msglen<2) /*“msglen<2”确保读取的短信数小于100;即msgindex[0]和msgindex[1];因为一共只有50条短信  */
这一句是确保短信数小于100吗?
回复

使用道具 举报

板凳
ID:114054 发表于 2016-4-13 20:33 | 只看该作者
请问楼主如果想实现删除全部短信,怎么写代码,我加了sim900a_send_cmd("AT+CMGD=4","OK",200);但是没用,急,求助
回复

使用道具 举报

地板
ID:106341 发表于 2016-6-14 08:36 | 只看该作者
mar一下
回复

使用道具 举报

5#
ID:401590 发表于 2019-8-30 16:24 | 只看该作者
楼主真nb
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表