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

標題: SIM900A手機模塊之核心代碼--接撥電話函數詳解 [打印本頁]

作者: liuyy    時間: 2015-1-12 14:39
標題: SIM900A手機模塊之核心代碼--接撥電話函數詳解
     SIM900A手機模塊的3大功能:接撥電話,收發短信和TCP/UDP通信。現在的手機基本上可以不叫手機了,真正的手機功能(前面所說的3大功能)占用不到1/5的主機資源。其實手機的工作原理非常簡單,就是一個主機與從機(sim900a之類的DSP或MCU)之間的串口通信,主機向從機發送指令,從機響應指令發回響應值,然后在LCD上顯示相應的界面。

      原子的例程僅僅是最簡單的芯片測試程序,不足很多,離以前的功能機的功能還差老遠。比如:1,接撥電話,收發短信和TCP/UDP通信這三個任務間沒有通信機制,收到短信時不能自動切換到收發短信界面;正常情況下最好是處于待機等待撥號界面;2,沒有通話計時功能;3,只能發固定內容的短信即不能自由編輯短信內容發送;4,沒有通話記錄功能等;5,沒有電話薄功能。這些功能貌似很簡單,實施起來不容易。最近一直在想以前那些簡單功能手機(不帶操作系統)各種功能任務是如何調度的程序上是怎樣實現的。我的想法是,以stm32作為主機加入文件系統和ucosii操作系統與SIM900A芯片構成一個簡單的智能手機。就當是自娛自樂吧!

     SIM900A手機模塊 撥號測試函數“u8 sim900a_call_test(void)”是本例程的核心代碼;本人做了非常詳細的注解,貼出來方便自己隨時登陸溫故學習。也供同道中人參考。

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

        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語句控制范圍的語句都是基于已經接收到sim900a模塊返回的數據,*/
                {
                        sim_at_response(0); /* mode:0,不清零USART2_RX_STA; 將收到的來自sim900a模塊的AT指令應答數據返回給電腦串口 */

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

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

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



作者: 舞了一季秋    時間: 2015-5-27 12:22
解釋很詳細!!!
作者: zhouwei0815    時間: 2019-5-9 11:02
很好  解釋很詳細 方便理解
作者: waerdeng    時間: 2020-2-23 10:00
解釋很詳細!!!適合我等白丁學習。




歡迎光臨 (http://m.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 咪咪色影院| 99久久综合| 亚洲欧美视频在线观看 | 欧美特黄一级片 | 欧美一级在线观看 | 国产精品福利在线观看 | 欧美成人一级 | 美女视频一区二区 | 欧美精产国品一二三区 | 国产白丝精品91爽爽久久 | 欧美性生交 | 在线观看黄网 | 国产精品高潮呻吟久久 | 中文字幕在线观看日本 | 国产成人在线免费视频 | 午夜视频免费观看 | 久久久婷| 我要操网站 | 日本成人一区二区 | 黄色片免费观看 | 视频在线一区二区 | 日韩欧美高清视频 | 羞羞的视频网站 | 国产在线一区二区三区 | 黄色片免费观看 | av免费网站 | 一区二区三区四区视频在线观看 | 中文字幕在线观看日本 | 一级欧美一级日韩 | 成年免费视频黄网站在线观看 | 国产精品美女久久 | 午夜影院在线观看 | 国产高清视频在线播放 | 久久精品黄色 | 午夜一级视频 | 日本欧美在线观看 | 国产精品自拍小视频 | 一级毛片在线播放 | 欧美成人精品一区二区三区在线看 | 亚洲天堂欧美 | 亚洲美女毛片 |