本帖最后由 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后就能进行拨话功能 这为正在拨话的界面,可以随时挂断电话 -------------------------------------------------------------------------华丽温柔的分割线------------------------------------------------------------------
|
|