久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 17477|回復(fù): 3
打印 上一主題 下一主題
收起左側(cè)

SIM900A手機(jī)模塊之核心代碼--接撥電話函數(shù)詳解

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:72008 發(fā)表于 2015-1-12 14:39 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
     SIM900A手機(jī)模塊的3大功能:接撥電話,收發(fā)短信和TCP/UDP通信。現(xiàn)在的手機(jī)基本上可以不叫手機(jī)了,真正的手機(jī)功能(前面所說(shuō)的3大功能)占用不到1/5的主機(jī)資源。其實(shí)手機(jī)的工作原理非常簡(jiǎn)單,就是一個(gè)主機(jī)與從機(jī)(sim900a之類的DSP或MCU)之間的串口通信,主機(jī)向從機(jī)發(fā)送指令,從機(jī)響應(yīng)指令發(fā)回響應(yīng)值,然后在LCD上顯示相應(yīng)的界面。

      原子的例程僅僅是最簡(jiǎn)單的芯片測(cè)試程序,不足很多,離以前的功能機(jī)的功能還差老遠(yuǎn)。比如:1,接撥電話,收發(fā)短信和TCP/UDP通信這三個(gè)任務(wù)間沒(méi)有通信機(jī)制,收到短信時(shí)不能自動(dòng)切換到收發(fā)短信界面;正常情況下最好是處于待機(jī)等待撥號(hào)界面;2,沒(méi)有通話計(jì)時(shí)功能;3,只能發(fā)固定內(nèi)容的短信即不能自由編輯短信內(nèi)容發(fā)送;4,沒(méi)有通話記錄功能等;5,沒(méi)有電話薄功能。這些功能貌似很簡(jiǎn)單,實(shí)施起來(lái)不容易。最近一直在想以前那些簡(jiǎn)單功能手機(jī)(不帶操作系統(tǒng))各種功能任務(wù)是如何調(diào)度的程序上是怎樣實(shí)現(xiàn)的。我的想法是,以stm32作為主機(jī)加入文件系統(tǒng)和ucosii操作系統(tǒng)與SIM900A芯片構(gòu)成一個(gè)簡(jiǎn)單的智能手機(jī)。就當(dāng)是自?shī)首詷?lè)吧!

     SIM900A手機(jī)模塊 撥號(hào)測(cè)試函數(shù)“u8 sim900a_call_test(void)”是本例程的核心代碼;本人做了非常詳細(xì)的注解,貼出來(lái)方便自己隨時(shí)登陸溫故學(xué)習(xí)。也供同道中人參考。

//////////////////////////////////////////////////////////   SIM900A手機(jī)模塊 撥號(hào)測(cè)試函數(shù)“u8 sim900a_call_test(void)”  ////////////////////////撥號(hào)測(cè)試部分代碼
//sim900a撥號(hào)測(cè)試
//用于撥打電話和接聽(tīng)電話
//返回值:0,正常
//    其他,錯(cuò)誤代碼
u8 sim900a_call_test(void)
{
        u8 key;
        u16 lenx;
        u8 callbuf[20];
    u8 wangyan[]={"13476852658"};//向自己的手機(jī)撥號(hào),因?yàn)槌绦蛑惺前咽謾C(jī)號(hào)碼當(dāng)作字符處理,所以要加英文引號(hào)
        u8 pohnenumlen=0;        //號(hào)碼長(zhǎng)度,最大15個(gè)數(shù),如 callbuf[pohnenumlen]; usart通信時(shí)電話號(hào)碼就是ASCII碼;
        u8 *p,*p1,*p2;
        u8 oldmode=0;
        u8 cmode=0;        /*模式0:等待撥號(hào);模式1:撥號(hào)中;模式2:通話中;模式3:接收到來(lái)電,共4種情況 */
        LCD_Clear(WHITE);
        if(sim900a_send_cmd("AT+CLIP=1","OK",200))return 1;        //設(shè)置來(lái)電顯示
        if(sim900a_send_cmd("AT+COLP=1","OK",200))return 2;        //設(shè)置被叫號(hào)碼顯示
        p1=mymalloc(SRAMIN,20);        //申請(qǐng)20個(gè)字節(jié)直接用于存放SIM900A模塊返回的來(lái)電電話號(hào)碼,usart通信時(shí)電話號(hào)碼就是ASCII碼;
        if(p1==NULL)return 2;       
        POINT_COLOR=RED;
        Show_Str_Mid(0,30,"ATK-SIM900A 撥號(hào)測(cè)試",16,240);                                             
        Show_Str(40,70,200,16,"請(qǐng)撥號(hào):",16,0);
        kbd_fn_tbl[0]="撥號(hào)";
        kbd_fn_tbl[1]="返回";
        sim900a_load_keyboard(0,180,(u8**)kbd_tbl1);/*加載撥號(hào)鍵盤(pán)界面,由此可見(jiàn)進(jìn)入什么功能就加載相應(yīng)的界面*/

        POINT_COLOR=BLUE;
        while(1)
        {   if(KEY_LEFT==KEY_Scan(0)) u2_printf("ATD%s;\r\n",wangyan);
                delay_ms(10);
                if(USART2_RX_STA&0X8000)        /*以下凡是受此if語(yǔ)句控制范圍的語(yǔ)句都是基于已經(jīng)接收到sim900a模塊返回的數(shù)據(jù),*/
                {
                        sim_at_response(0); /* mode:0,不清零USART2_RX_STA; 將收到的來(lái)自sim900a模塊的AT指令應(yīng)答數(shù)據(jù)返回給電腦串口 */

                        if(cmode==1||cmode==2)/*首次進(jìn)入時(shí)cmode為0,模式0:等待撥號(hào);模式1:撥號(hào)中;模式2:通話中;模式3:接收到來(lái)電  */
                        {/* 首先發(fā)送:ATE1,設(shè)置回顯,再發(fā)送:AT+COLP=1,設(shè)置被叫號(hào)碼顯示。然后發(fā)送:ATD10086;,撥打10086,在接通后,SIM900A模塊返回:+COLP: "10086",129,"","",此時(shí),我們就可以聽(tīng)到中國(guó)移動(dòng)那熟悉的聲音了….待一堆廢話結(jié)束后,我們發(fā)送:AT+VTS=1,即可查詢本機(jī)電話號(hào)碼。最后,通過(guò)發(fā)送:ATH,掛斷,結(jié)束本次 */
                 if(cmode==1)if(sim900a_check_cmd("+COLP:"))cmode=2;        //撥號(hào)成功
                                if(sim900a_check_cmd("NO CARRIER"))cmode=0;        //撥號(hào)失敗
                                if(sim900a_check_cmd("NO ANSWER"))cmode=0;        //撥號(hào)失敗
                                if(sim900a_check_cmd("ERROR"))cmode=0;                //撥號(hào)失敗
                        }
                        if(sim900a_check_cmd("+CLIP:")) /*接收到來(lái)電, 如果返回值是+CLIP:則表示接收到來(lái)電 */
                        {/*"+CLIP:"的含義是:設(shè)置提示來(lái)電號(hào)碼,帶來(lái)電顯示時(shí)的返回值格式是:"+CLIP:(<n>取值列表) " 參考AT命令手冊(cè)P59
                      AT+CLIP用于設(shè)置來(lái)電顯示,通過(guò)發(fā)送:AT+CLIP=1,可以實(shí)現(xiàn)設(shè)置來(lái)電顯示功能,模塊接收到來(lái)電的時(shí)候,會(huì)返回來(lái)電號(hào)碼。并且可以在串口接收到來(lái)電號(hào)碼,如:+CLIP: "02038271790",161,"",,"ALIENTEK",0,表示當(dāng)前接入號(hào)碼為:02038271790。
此時(shí),我們發(fā)送:ATA,即可接聽(tīng)來(lái)電,并進(jìn)行通話。當(dāng)對(duì)方掛斷電話的時(shí)候,SIM900A模塊會(huì)返回:NO CARRIER,并結(jié)束此次通話;當(dāng)然,我們也可以通過(guò)發(fā)送:ATH,來(lái)主動(dòng)結(jié)束通話。*/
                                cmode=3; /* 模式0:等待撥號(hào);模式1:撥號(hào)中;模式2:通話中;模式3:接收到來(lái)電  */
                                p=sim900a_check_cmd("+CLIP:"); /* 將接收到的"+CLIP:"字符串(即來(lái)自模塊返回值)存儲(chǔ)到P */
                                p+=8; /*將模塊返回的來(lái)電號(hào)碼存儲(chǔ)在(P+8)處,p+8,就是偏移8個(gè)字節(jié),不是一共8個(gè)內(nèi)存空間 */
                            p2=(u8*)strstr((const char *)p,"\"");/*在(P+8)處開(kāi)始,找到第一個(gè)出現(xiàn)“\”符號(hào)(每個(gè)字符串結(jié)束符      
                                             都有“\”符號(hào))的位置,實(shí)際上就是從模塊返回值中取得電話號(hào)碼;并將電話號(hào)碼存儲(chǔ)到P2開(kāi)始處*/
                 p2[0]=0; /*添加結(jié)束符。字符串的結(jié)束符是'\0' 也是0;p2=(u8*)strstr((const char*)(p1),","); 指定結(jié)束符的位置 */
                                /*上面兩步的作用是給字符串加上“\0”這個(gè)字符串末尾標(biāo)志  */
                                strcpy((char*)p1,(char*)p);/* 字符串P復(fù)制到P1,用于下面case3語(yǔ)句顯示 */

                        }
                        USART2_RX_STA=0; /*將接收到的數(shù)據(jù)清零,以便讓串口2再次進(jìn)入中斷執(zhí)行“if(USART2_RX_STA==0)TIM4_Set(1)”語(yǔ)句*/
                } /*對(duì)sim900a返回值的處理部分到此結(jié)束 ;*/
/* 上面部分的語(yǔ)句主要是對(duì)sim900a返回值的處理,并根據(jù)返回值的情況定義4種工作狀態(tài):模式0:等待撥號(hào);模式1:撥號(hào)中;模式2:通話中;模式3:接收到來(lái)電 */               

         key=sim900a_get_keynum(0,180);/* 檢測(cè)是哪個(gè)觸摸鍵被按下,下面根據(jù)對(duì)觸摸鍵觸摸情況、對(duì)相關(guān)功能進(jìn)行處理 */
                if(key)  /* 下面的操作都是基于觸摸鍵有被按下  */
                {
                        if(key<13)
                        {
                           if(cmode==0&&pohnenumlen<15) /*模式0:等待撥號(hào)且pohnenumlen對(duì)應(yīng)的鍵值小于15,首次進(jìn)入時(shí)是0 */
                           {
                                 callbuf[pohnenumlen++]=kbd_tbl[key-1][0];/*執(zhí)行pohnenumlen++的條件是必須有觸摸鍵按下 */
       /* 二維數(shù)組kbd_tbl[key-1][0]實(shí)際上等價(jià)于kbd_tbl[key-1];本句的作用是將被按下的觸屏鍵值即對(duì)應(yīng)的字符存儲(chǔ)到callbuf[pohnenumlen++]  */
               /* 假設(shè)i=3,j=1,則key==11即key[1][3]:x軸第二格,y軸第4格,該處就是存放“11” */
                                 u2_printf("AT+CLDTMF=2,\"%c\"\r\n",kbd_tbl[key-1][0]);
/* "AT+CLDTMF=2參考AT命令手冊(cè)P126,測(cè)試DTMF音,時(shí)長(zhǎng)2秒 ,將命令和鍵值發(fā)送給模塊,功能:每撥一個(gè)數(shù)字鍵(只對(duì)0-9號(hào)數(shù)字鍵有效)耳機(jī)發(fā)出相應(yīng)的撥號(hào)音*/
                                }else if(cmode==2)//通話中,主叫撥通了通話中
                                {
                                        u2_printf("AT+CLDTMF=2,\"%c\"\r\n",kbd_tbl[key-1][0]);
                                        delay_ms(100);
                                        u2_printf("AT+VTS=%c\r\n",kbd_tbl[key-1][0]);
                                        LCD_ShowChar(40+56,90,kbd_tbl[key-1][0],16,0);
                      /*在“請(qǐng)撥號(hào)”后面顯示按下的鍵值,即顯示撥號(hào)鍵 */
                                }
                        }else
                        {
                                if(key==13)if(pohnenumlen&&cmode==0)pohnenumlen--;
   /*刪除;1,如果pohnenumlen==0,則說(shuō)明callbuf[pohnenumlen]數(shù)組中沒(méi)有存放任何號(hào)碼,所以就不必執(zhí)行“pohnenumlen--;”  2,“cmode==0”即等待撥號(hào)模式;3,通過(guò)對(duì)數(shù)組下表的加減就可以增刪數(shù)組元素;如,本例中通過(guò)執(zhí)行“pohnenumlen--;”操作,就將callbuf[pohnenumlen]數(shù)組元素做了增刪,重要! */
                                if(key==14)//執(zhí)行撥號(hào)
                                {
                                        if(cmode==0)/*撥號(hào)模式;如果按了撥號(hào)鍵且處于等待撥號(hào)模式  */
                                        {
                                                callbuf[pohnenumlen]=0;/*最后加入結(jié)束符, 字符串結(jié)束符是“\0”也是“0” */
                                          //        u2_printf("ATD%s;\r\n",callbuf);/*撥號(hào),號(hào)碼就是callbuf存儲(chǔ)的內(nèi)容 */
                          u2_printf("ATD%s;\r\n",wangyan);
                     /*給自己撥號(hào)撥號(hào),號(hào)碼就是wangyan存儲(chǔ)的內(nèi)容即13476852658;當(dāng)按下“撥號(hào)”鍵時(shí),相應(yīng)的手機(jī)就接到了本機(jī)的來(lái)電 */
                                                cmode=1;         //撥號(hào)中模式1:57:01星期三 2014年8月6日
                                        }else /* 如果按了撥號(hào)鍵key14*/
                                        {
                                                sim900a_send_cmd("ATH","OK",200);//掛機(jī)
                                                cmode=0; /*將工作模式設(shè)置為等待撥號(hào)模式  */
                                        }
                                }
                                if(key==15) /* 在通話測(cè)試模式中key15就是“接聽(tīng)”  */
                                {
                                        if(cmode==3) /*如果按下“接聽(tīng)”鍵且處于“接聽(tīng)中”(cmode==3) 模式 */
                                        {/* 接收到來(lái)電;上面有“if(sim900a_check_cmd("+CLIP:"))”語(yǔ)句,所以只要有電話打進(jìn)來(lái),cmode就會(huì)等于3!*/
                                                sim900a_send_cmd("ATA","OK",200);/*發(fā)送應(yīng)答指令,ATA,即可接聽(tīng)來(lái)電*/
                                                Show_Str(40+56,70,200,16,callbuf,16,0);/*顯示來(lái)電號(hào)碼,本句是否有問(wèn)題? */
                                                cmode=2; /* 設(shè)置為模式2:通話中 */
                                        }else  /* 如果沒(méi)有電話打進(jìn)來(lái),觸摸15鍵則會(huì)執(zhí)行“break;”退出while大循環(huán)回到主函數(shù)界面,*/
                                        {
                                                sim900a_send_cmd("ATH",0,0); /* 不管有沒(méi)有在通話,都結(jié)束通話即掛機(jī) */
                                                break;/*退出循環(huán),執(zhí)行“myfree(SRAMIN,p1);”語(yǔ)句*/
                                        }
                                }
                        }
                        if(cmode==0)//只有在等待撥號(hào)模式有效
                        { /* “callbuf[pohnenumlen]=0; ”這一句非常重要!該句確保每撥一個(gè)字符都能正確的顯示 */
                                callbuf[pohnenumlen]=0; /*該句作用是每按一下?lián)芴?hào)鍵就在相應(yīng)的鍵值后加一個(gè)結(jié)束符,用以顯示在LCD上 */
                                LCD_Fill(40+56,70,239,70+16,WHITE);
                                Show_Str(40+56,70,200,16,callbuf,16,0);/*將每個(gè)撥號(hào)鍵值顯示出來(lái) */         
                        }                               
                }
                if(oldmode!=cmode)//模式變化了,只要cmode不等于0模式就會(huì)進(jìn)入下面語(yǔ)句
                {
                        switch(cmode)
                        {
                                case 0:
                                        kbd_fn_tbl[0]="撥號(hào)";
                                        kbd_fn_tbl[1]="返回";
                                        POINT_COLOR=RED;
                                        Show_Str(40,70,200,16,"請(qǐng)撥號(hào):",16,0);  
                                        LCD_Fill(40+56,70,239,70+16,WHITE);
                                        if(pohnenumlen)
                                        {
                                                POINT_COLOR=BLUE;
                                                Show_Str(40+56,70,200,16,callbuf,16,0);
                                        }
                                        break;
                                case 1:
                                        POINT_COLOR=RED;
                                        Show_Str(40,70,200,16,"撥號(hào)中:",16,0);
                                        pohnenumlen=0;//將電話號(hào)碼清零
                                case 2:
                                        POINT_COLOR=RED;
                                        if(cmode==2)Show_Str(40,70,200,16,"通話中:",16,0);
                                        kbd_fn_tbl[0]="掛斷";
                                        kbd_fn_tbl[1]="返回";        
                                        break;
                                case 3:
                                        POINT_COLOR=RED;
                                        Show_Str(40,70,200,16,"有來(lái)電:",16,0);
                                        POINT_COLOR=BLUE;
                                        Show_Str(40+56,70,200,16,p1,16,0); //顯示來(lái)電
                                        kbd_fn_tbl[0]="掛斷";
                                        kbd_fn_tbl[1]="接聽(tīng)";
                                        break;                               
                        }
                        if(cmode==2)Show_Str(40,90,200,16,"DTMF音:",16,0);//通話中,可以通過(guò)鍵盤(pán)輸入DTMF音
                        else LCD_Fill(40,90,120,90+16,WHITE);
                        sim900a_load_keyboard(0,180,(u8**)kbd_tbl1); //顯示鍵盤(pán)
                        oldmode=cmode; /*退出“switch(cmode)”語(yǔ)句,確保界面處于一種穩(wěn)定的與cmode值對(duì)應(yīng)的模式 */
                }/*假設(shè)cmode==2“通話中模式”,根據(jù)通話的具體情況cmode會(huì)得到不同的值,這樣就又可以進(jìn)入“switch(cmode)”語(yǔ)句了。  */
                if((lenx%50)==0)LED0=!LED0;                                              
                lenx++;         
        }
        myfree(SRAMIN,p1);
        return 0;
}
/*
1,u8 sim900a_call_test(void)函數(shù)總結(jié):該函數(shù)可以接聽(tīng)撥打電話測(cè)試,是該模塊的核心函數(shù)之一,里面的算法以及c語(yǔ)言運(yùn)用技巧都值得不斷溫故;可以分為2個(gè)部分:
1),按下key0鍵,做一些撥打電話之前的準(zhǔn)備工作讓sim900a模塊進(jìn)入工作狀態(tài)并加載觸摸屏界面;首次進(jìn)入該函數(shù)時(shí),把cmode設(shè)置為等待撥號(hào)模式;
2),該部分包含在一個(gè)while大循環(huán)里,這個(gè)while大循環(huán)就是該函數(shù)的核心,為了便于分析該函數(shù),將while循環(huán)的功能細(xì)分為;a),以“if(USART2_RX_STA&0X8000)”語(yǔ)句為控制范圍的內(nèi)容,它的主要功能是假設(shè)收到了來(lái)自sim900a模塊的AT指令應(yīng)答數(shù)據(jù)即模塊返回?cái)?shù)據(jù),基于此并根據(jù)接收到的返回值含義把sim900a模塊定義為4種工作模式:模式cmode0:等待撥號(hào);模式cmode1:撥號(hào)中;模式cmode2:通話中;模式cmode3:接收到來(lái)電;而后面程序的操作就是圍繞這四種工作模式不斷變化使LCD界面適應(yīng)相應(yīng)的操作需求以便于主機(jī)發(fā)出相應(yīng)的命令;如果sim900a模塊接收到來(lái)電就會(huì)向串口返回相應(yīng)的數(shù)據(jù)和來(lái)電電話號(hào)碼,程序就將sim900a模塊設(shè)置為cmode3即接聽(tīng)模式并將來(lái)電號(hào)碼顯示在LCD;如果是撥號(hào)中或通話中模式,則根據(jù)sim900a模塊的返回值將cmode設(shè)置為相應(yīng)的工作模式值;b)接著就是根據(jù)某個(gè)觸摸鍵是否按下即根據(jù)獲得的觸摸鍵值key執(zhí)行向sim900a模塊發(fā)出相應(yīng)的AT指令,同時(shí)將cmode定義為相應(yīng)的工作模式值,以便于下一步操作;c),根據(jù)cmode模式值執(zhí)行相應(yīng)的switch語(yǔ)句內(nèi)容。
*/


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:81248 發(fā)表于 2015-5-27 12:22 | 只看該作者
解釋很詳細(xì)!!!
回復(fù)

使用道具 舉報(bào)

板凳
ID:350104 發(fā)表于 2019-5-9 11:02 | 只看該作者
很好  解釋很詳細(xì) 方便理解
回復(fù)

使用道具 舉報(bào)

地板
ID:71535 發(fā)表于 2020-2-23 10:00 | 只看該作者
解釋很詳細(xì)!!!適合我等白丁學(xué)習(xí)。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 久久久成人网 | 久久久人成影片一区二区三区 | 国产欧美一区二区久久性色99 | 91视视频在线观看入口直接观看 | 久草在线在线精品观看 | 九九成人 | 国产一级毛片精品完整视频版 | 国产精品高潮呻吟久久av野狼 | 成人精品高清 | 国产露脸国语对白在线 | 中文字幕 在线观看 | 亚洲一区二区三区免费视频 | 巨大荫蒂视频欧美另类大 | 国产精品成人一区 | 久久精品国产99国产 | 一区二区不卡 | 国产精品美女www爽爽爽 | 国产精品久久久久久238 | 久在草 | 黄色国产在线播放 | 午夜视频一区二区三区 | 日韩高清一区 | 欧美成人a| 一区二区三区国产 | 天天狠狠| 久在草| 一级片在线观看视频 | 国产视频中文字幕 | 婷婷久 | 在线视频一区二区 | 99re视频在线观看 | 在线免费av观看 | 黄视频免费观看 | 国产精品久久久久久av公交车 | 欧美黑人又粗大 | 一区二区三区国产 | 免费观看一级黄色录像 | 久久久久欧美 | 欧美精品v | 国产精品色 | 国产一区二区毛片 |