|
經過兩天的時間,一共分析了兩個函數:手機撥接電話和手機讀取短信函數。這兩天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);
}
該睡覺了!
|
|