打印
[STM32F4]

【Nucleo设计分享】基于stm32f411re的智能手表(通话功能)

[复制链接]
1613|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 zhanghuichun 于 2015-3-2 15:48 编辑

由于要讲详细点,所以分开来讲,造成不便敬请原谅
通话功能主要是基于SIM908模块建立起来的,所以不得不说一下串口字符处理。那就从串口中断讲开去……
先看中断代码:
void USART1_IRQHandler(void)
{
        char data;
        if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
        {
//        USART_ClearFlag(USART1,USART_IT_RXNE);
                data = USART_ReceiveData(USART1);
                if(GSM_RX_FLAG < DATA_BUFF_SIZE)        //还能接收数据
                {
                        TIM3->CNT = 0;        //清空计数器
                        if( GSM_RX_FLAG == 0 )
                        {
                                TIM3_Set( 1 );        //开计数器3
                        }
                        
                        GSM_RX_BUFF[GSM_RX_FLAG++] = data;
                }
                else
                {
                        GSM_RX_FLAG |= 1<<15;        //接收标志强制置1
                }
        }
}

由于stm的硬件buff只有一个字节,那就极可能造成字符串没接收完,就开始判断,这就会造成信息的丢失。比如说,我要提取一字符串中的某些内容,这样如果字符串没接收完就会出现你前面判断对了,但是你要提取的信息在后头,这样提取的信息就变成空的了!
为了解决这个问题,我引入一个定时器在限定的时间内把缓冲区填满否则也判断完了,接着在开始对字符串进行处理。如上面的代码如果整个缓冲区填满了,那样就使能标志位对字符串处理,如果还能进行保存数据则打开定时器3(定时6ms),定时器3中断后对字符串进行处理(判断为接收完了)。
接下来看看定时器3中的处理:
/*
        函数名:TIM3_Interrupt
        描述:        tim3中断函数
        输入:        无
        输出:        无
*/
void TIM3_IRQHandler(void)
{
        uint8_t write_buf[2];
        u8 mesaddr[3];
        u8 *p1 = NULL;
        u8 *p2 = NULL;
        
        if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
        {               
                TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
                TIM3_Set( 0 );        //关闭计时器
                GSM_RX_BUFF[GSM_RX_FLAG & 0x7fff] = '\0';
                GSM_IT_FLAG = 1;
                GSM_RX_FLAG = 0;
                if( NULL != strstr(GSM_RX_BUFF, "+CMTI:"))
                {        
                        mesaddr[0] = *(strstr(GSM_RX_BUFF, ",")+1);
                        mesaddr[1] = *(strstr(GSM_RX_BUFF, ",")+2);
                        write_buf[0]=mesaddr[0];
                        write_buf[1]=mesaddr[1];
                        if( mesaddr[1] >= '0' && mesaddr[1] <= '9')
                        {
                                Messagenum = (mesaddr[0] - '0')*10 + (mesaddr[1] - '0');
                        }
                        else
                        {
                                Messagenum = (mesaddr[0] - '0');
                        }
                        Messagebuff[Messagenum-1] = 1;
                        FlagNewMessage=1;
                        //将短信数量保存
                        if (ee_WriteBytes(write_buf, 0, 2) == 0)
                        {
                                USART_printf(USART6,"写eeprom出错!\r\n");
                                       
                        }
                        else
                        {               
                                USART_printf(USART6,"写eeprom成功!\r\n");
                                USART_printf(USART6,"\r\n%d\r\n",Messagenum);
                        }
                        
                }
                else if( NULL != strstr(GSM_RX_BUFF, "+CLIP:"))
                {
                p1 = (u8 *)strstr((char *)GSM_RX_BUFF, "\"");
                p2 = (u8 *)strstr((char *)(p1+1), "\"");
                p2[0] = '\0';
                strcpy(RingNumber, p1+1);
                if(!WM_IsWindow(WinPara.hRing))//判断当前激活的窗口
                WM_SendMessageNoPara(WinPara.hWinMain,MY_MESSAGE_RING);
                Moter(ON);
                }
               
                else if(NULL != strstr(GSM_RX_BUFF, "CLOSE"))
                {
                //        GPRSFLAG = 3;        
                }
        }
}

巧妙使用strstr函数,减少出错率。判断接收到的字符串是否含有+CMTI:(来短信信息反馈)、+CLIP:(来电信息反馈)、CLOSE(GPRS连接断开信息反馈)这几个信息。
当有电话来的时候,就会有带有+CLIP:的字符串反馈,则我们就给主窗口发送来电信息(WM_SendMessageNoPara(WinPara.hWinMain,MY_MESSAGE_RING);),并提取来电号码、使能震动电机。
接下来看看主窗口回调函数部分代码:
/*
        描述:主窗口的回调函数
*/
static void _cbMainWin(WM_MESSAGE * pMsg)
{
        RTC_TimeTypeDef RTC_TimeStruct;
        RTC_DateTypeDef RTC_DateStruct;
        WM_HWIN hText;
        int NCode;
        int id;
        int Sel;
        char text_buffer[20];
        int xSize, ySize;
        
        switch (pMsg->MsgId) {
                case WM_NOTIFY_PARENT:
                        id = WM_GetId(pMsg->hWinSrc);                //获取控件的ID
                        NCode = pMsg->Data.v;
                        if(id == GUI_ID_ICONVIEW0 && NCode == WM_NOTIFICATION_RELEASED)
                        {
                                Sel= ICONVIEW_GetSel(pMsg->hWinSrc);        //获取图标索引
                                switch(Sel)
                                {
                                        case 0:
                                                GUI_Phone();
                                                break;
                                        case 1:
                                                GUI_Message();
                                                break;
                                        case 2:
                                                GUI_time();
                                                break;
                                        case 3:
                                                
                                                break;
                                        case 4:
                                                
                                                break;
                                        case 5:
                                                
                                                break;
                                }
                        }
                        break;         
                case MY_MESSAGE_RTC:
                        hText = WM_GetDialogItem(pMsg->hWin, GUI_ID_TEXT1);
                        RTC_GetTime(RTC_Format_BIN,&RTC_TimeStruct);
                        RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
                        sprintf(text_buffer, "%02d:%02d",RTC_TimeStruct.RTC_Hours,RTC_TimeStruct.RTC_Minutes);
                        TEXT_SetText(hText, text_buffer);
                        
                        hText = WM_GetDialogItem(pMsg->hWin, GUI_ID_TEXT2);
                        sprintf(text_buffer, "20%02d-%02d-%02d",RTC_DateStruct.RTC_Year,RTC_DateStruct.RTC_Month,RTC_DateStruct.RTC_Date);
                        TEXT_SetText(hText, text_buffer);
               
                        hText = WM_GetDialogItem(pMsg->hWin, GUI_ID_TEXT3);
                        switch(RTC_DateStruct.RTC_WeekDay)
                        {
                                case 1:sprintf(text_buffer,"Monday");
                                        break;
                                case 2:sprintf(text_buffer,"Tuesday");
                                        break;
                                case 3:sprintf(text_buffer,"Wednesday");
                                        break;
                                case 4:sprintf(text_buffer,"Thursday");
                                        break;
                                case 5:sprintf(text_buffer,"Friday");
                                        break;
                                case 6:sprintf(text_buffer,"Saturday");
                                        break;
                                case 7:sprintf(text_buffer,"Sunday");
                                        break;
                                default:sprintf(text_buffer,"");
                                        break;
                        }
                        TEXT_SetText(hText, text_buffer);
                        break;
                case MY_MESSAGE_RING:
                        Phone_Ring();
                        break;
                case WM_PAINT:                      //重绘背景
                                xSize = WM_GetWindowSizeX(pMsg->hWin);
                                ySize = WM_GetWindowSizeY(pMsg->hWin);               

                                GUI_DrawGradientV(0, 0, xSize - 1, ySize - 1, 0xfffff56c, 0xffffffe8);
                                GUI_DrawGradientV(0,0,240,280,0xffff0d23,0xfffff56c);
                        break;                                      
               
                 
                default:               
      WM_DefaultProc(pMsg);
                }
}

当主窗口接到来电信息就会建立子窗口(即来电提示)。代码繁多就不把来电显示窗口的代码放出来了!
这就是来电的效果图,有来电显示功能,点击YES就能接听电话,点击No则为拒接并退出此窗口,Back键主要用于,接听完电话退出界面的。
除了来电功能,还有拨话功能!
这为拨话的界面,编辑好电话号码后点击Call后就能进行拨话功能
这为正在拨话的界面,可以随时挂断电话
-------------------------------------------------------------------------华丽温柔的分割线------------------------------------------------------------------

沙发
小浣熊| | 2015-3-5 20:43 | 只看该作者
不错,楼主加油,这种智能产品相对有发展前景些!!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

99

帖子

9

粉丝