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

[复制链接]
zhanghuichun 发表于 2015-3-2 15:13 | 显示全部楼层 |阅读模式
本帖最后由 zhanghuichun 于 2015-3-2 15:48 编辑

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

由于stm的硬件buff只有一个字节,那就极可能造成字符串没接收完,就开始判断,这就会造成信息的丢失。比如说,我要提取一字符串中的某些内容,这样如果字符串没接收完就会出现你前面判断对了,但是你要提取的信息在后头,这样提取的信息就变成空的了!
为了解决这个问题,我引入一个定时器在限定的时间内把缓冲区填满否则也判断完了,接着在开始对字符串进行处理。如上面的代码如果整个缓冲区填满了,那样就使能标志位对字符串处理,如果还能进行保存数据则打开定时器3(定时6ms),定时器3中断后对字符串进行处理(判断为接收完了)。
接下来看看定时器3中的处理:
  1. /*
  2.         函数名:TIM3_Interrupt
  3.         描述:        tim3中断函数
  4.         输入:        无
  5.         输出:        无
  6. */
  7. void TIM3_IRQHandler(void)
  8. {
  9.         uint8_t write_buf[2];
  10.         u8 mesaddr[3];
  11.         u8 *p1 = NULL;
  12.         u8 *p2 = NULL;
  13.         
  14.         if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
  15.         {               
  16.                 TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
  17.                 TIM3_Set( 0 );        //关闭计时器
  18.                 GSM_RX_BUFF[GSM_RX_FLAG & 0x7fff] = '\0';
  19.                 GSM_IT_FLAG = 1;
  20.                 GSM_RX_FLAG = 0;
  21.                 if( NULL != strstr(GSM_RX_BUFF, "+CMTI:"))
  22.                 {        
  23.                         mesaddr[0] = *(strstr(GSM_RX_BUFF, ",")+1);
  24.                         mesaddr[1] = *(strstr(GSM_RX_BUFF, ",")+2);
  25.                         write_buf[0]=mesaddr[0];
  26.                         write_buf[1]=mesaddr[1];
  27.                         if( mesaddr[1] >= '0' && mesaddr[1] <= '9')
  28.                         {
  29.                                 Messagenum = (mesaddr[0] - '0')*10 + (mesaddr[1] - '0');
  30.                         }
  31.                         else
  32.                         {
  33.                                 Messagenum = (mesaddr[0] - '0');
  34.                         }
  35.                         Messagebuff[Messagenum-1] = 1;
  36.                         FlagNewMessage=1;
  37.                         //将短信数量保存
  38.                         if (ee_WriteBytes(write_buf, 0, 2) == 0)
  39.                         {
  40.                                 USART_printf(USART6,"写eeprom出错!\r\n");
  41.                                        
  42.                         }
  43.                         else
  44.                         {               
  45.                                 USART_printf(USART6,"写eeprom成功!\r\n");
  46.                                 USART_printf(USART6,"\r\n%d\r\n",Messagenum);
  47.                         }
  48.                         
  49.                 }
  50.                 else if( NULL != strstr(GSM_RX_BUFF, "+CLIP:"))
  51.                 {
  52.                 p1 = (u8 *)strstr((char *)GSM_RX_BUFF, """);
  53.                 p2 = (u8 *)strstr((char *)(p1+1), """);
  54.                 p2[0] = '\0';
  55.                 strcpy(RingNumber, p1+1);
  56.                 if(!WM_IsWindow(WinPara.hRing))//判断当前激活的窗口
  57.                 WM_SendMessageNoPara(WinPara.hWinMain,MY_MESSAGE_RING);
  58.                 Moter(ON);
  59.                 }
  60.                
  61.                 else if(NULL != strstr(GSM_RX_BUFF, "CLOSE"))
  62.                 {
  63.                 //        GPRSFLAG = 3;        
  64.                 }
  65.         }
  66. }

巧妙使用strstr函数,减少出错率。判断接收到的字符串是否含有+CMTI:(来短信信息反馈)、+CLIP:(来电信息反馈)、CLOSE(GPRS连接断开信息反馈)这几个信息。
当有电话来的时候,就会有带有+CLIP:的字符串反馈,则我们就给主窗口发送来电信息(WM_SendMessageNoPara(WinPara.hWinMain,MY_MESSAGE_RING);),并提取来电号码、使能震动电机。
接下来看看主窗口回调函数部分代码:
  1. /*
  2.         描述:主窗口的回调函数
  3. */
  4. static void _cbMainWin(WM_MESSAGE * pMsg)
  5. {
  6.         RTC_TimeTypeDef RTC_TimeStruct;
  7.         RTC_DateTypeDef RTC_DateStruct;
  8.         WM_HWIN hText;
  9.         int NCode;
  10.         int id;
  11.         int Sel;
  12.         char text_buffer[20];
  13.         int xSize, ySize;
  14.         
  15.         switch (pMsg->MsgId) {
  16.                 case WM_NOTIFY_PARENT:
  17.                         id = WM_GetId(pMsg->hWinSrc);                //获取控件的ID
  18.                         NCode = pMsg->Data.v;
  19.                         if(id == GUI_ID_ICONVIEW0 && NCode == WM_NOTIFICATION_RELEASED)
  20.                         {
  21.                                 Sel= ICONVIEW_GetSel(pMsg->hWinSrc);        //获取图标索引
  22.                                 switch(Sel)
  23.                                 {
  24.                                         case 0:
  25.                                                 GUI_Phone();
  26.                                                 break;
  27.                                         case 1:
  28.                                                 GUI_Message();
  29.                                                 break;
  30.                                         case 2:
  31.                                                 GUI_time();
  32.                                                 break;
  33.                                         case 3:
  34.                                                 
  35.                                                 break;
  36.                                         case 4:
  37.                                                 
  38.                                                 break;
  39.                                         case 5:
  40.                                                 
  41.                                                 break;
  42.                                 }
  43.                         }
  44.                         break;         
  45.                 case MY_MESSAGE_RTC:
  46.                         hText = WM_GetDialogItem(pMsg->hWin, GUI_ID_TEXT1);
  47.                         RTC_GetTime(RTC_Format_BIN,&RTC_TimeStruct);
  48.                         RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
  49.                         sprintf(text_buffer, "%02d:%02d",RTC_TimeStruct.RTC_Hours,RTC_TimeStruct.RTC_Minutes);
  50.                         TEXT_SetText(hText, text_buffer);
  51.                         
  52.                         hText = WM_GetDialogItem(pMsg->hWin, GUI_ID_TEXT2);
  53.                         sprintf(text_buffer, "20%02d-%02d-%02d",RTC_DateStruct.RTC_Year,RTC_DateStruct.RTC_Month,RTC_DateStruct.RTC_Date);
  54.                         TEXT_SetText(hText, text_buffer);
  55.                
  56.                         hText = WM_GetDialogItem(pMsg->hWin, GUI_ID_TEXT3);
  57.                         switch(RTC_DateStruct.RTC_WeekDay)
  58.                         {
  59.                                 case 1:sprintf(text_buffer,"Monday");
  60.                                         break;
  61.                                 case 2:sprintf(text_buffer,"Tuesday");
  62.                                         break;
  63.                                 case 3:sprintf(text_buffer,"Wednesday");
  64.                                         break;
  65.                                 case 4:sprintf(text_buffer,"Thursday");
  66.                                         break;
  67.                                 case 5:sprintf(text_buffer,"Friday");
  68.                                         break;
  69.                                 case 6:sprintf(text_buffer,"Saturday");
  70.                                         break;
  71.                                 case 7:sprintf(text_buffer,"Sunday");
  72.                                         break;
  73.                                 default:sprintf(text_buffer,"");
  74.                                         break;
  75.                         }
  76.                         TEXT_SetText(hText, text_buffer);
  77.                         break;
  78.                 case MY_MESSAGE_RING:
  79.                         Phone_Ring();
  80.                         break;
  81.                 case WM_PAINT:                      //重绘背景
  82.                                 xSize = WM_GetWindowSizeX(pMsg->hWin);
  83.                                 ySize = WM_GetWindowSizeY(pMsg->hWin);               

  84.                                 GUI_DrawGradientV(0, 0, xSize - 1, ySize - 1, 0xfffff56c, 0xffffffe8);
  85.                                 GUI_DrawGradientV(0,0,240,280,0xffff0d23,0xfffff56c);
  86.                         break;                                      
  87.                
  88.                  
  89.                 default:               
  90.       WM_DefaultProc(pMsg);
  91.                 }
  92. }

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

小浣熊 发表于 2015-3-5 20:43 | 显示全部楼层
不错,楼主加油,这种智能产品相对有发展前景些!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

101

帖子

9

粉丝
快速回复 在线客服 返回列表 返回顶部

20

主题

101

帖子

9

粉丝
快速回复 在线客服 返回列表 返回顶部