|
经过两天的时间,一共分析了两个函数:手机拨接电话和手机读取短信函数。这两天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);
}
该睡觉了!
|
|