/**************************************************************
51 單片機例程
本例程使用11.0592MHZ時鐘---->必須為11.0592M
串口設置為:9600,8,n,1.
******************************************/
#include <reg52.h>
#include "string.h"
#include "GA6_module_errors.h"
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
/************* 本地常量聲明 **************/
#define Buf_Max 70 //串口1緩存長度
#define STABLE_TIMES 10 //等待上電后穩定
/************* 本地變量聲明 **************/
//串口1發送回車換行
#define UART1_SendLR() UART1_SendData(0X0D);UART1_SendData(0X0A)
/*LED端口定義*/
sbit LED0 = P1^0;
sbit LED1 = P1^1;
sbit LED5 = P2^0;
sbit LED6 = P1^6;
sbit LED7 = P2^7;
/*KEY端口定義*/
sbit KEY0 = P2^4;
sbit KEY1 = P2^5;
sbit KEY2 = P2^6;
sbit KEY3 = P2^7;
/************* 本地變量聲明 **************/
xdata u8 Uart1_Buf[Buf_Max];
u8 First_Int = 0;
u16 count_20ms;
u8 receive_mode = 0;
u8 find_string_flag = 0;
idata char num_message[4];//暫時假設最多只能存999條短信
idata char AT_CMGR[15];
/************* 本地函數聲明 **************/
void delay_ms(u16 ms); //延時ms個20ms ms*20ms
void CLR_Buf(void); //清串口接收緩存
u8 Find(u8 *a); //查找字符串
void UART1_SendData(u8 dat); //串口1發送 1字節
void UART1_SendString(char *s);//串口1發送 字符串
void UART1_Send_Command(char *s);
u8 UART1_Send_AT_Command(u8 *b,u8 *a,u8 wait_time,u16 interval_time);
u8 Wait_CREG(u8 query_times);
void Timer0Init(void) //20毫秒@115200
{
TMOD &= 0xF0;
TMOD |= 0x01; //
TL0 = (65536-20000)%256; //
TH0 = (65536-20000)/256; //
TF0 = 0; //
ET0 = 1; //
TR0 = 1; //開始計時
}
void Uart1Init(void) //9600bps@11.05926MHz
{
PCON &= 0x7F; //
SCON = 0x50; //
TMOD &= 0x0F; //
TMOD |= 0x20; //
TL1 = 0xFD; //
TH1 = 0xFD; //
ET1 = 0; //
TR1 = 1; //
ES = 1; //
}
int check_status(void)
{
int ret;
ret = UART1_Send_AT_Command("AT","OK",3,50);//測試通信是否成功
if(ret == 0)
{
return COMMUNITE_ERROR;
}
ret = UART1_Send_AT_Command("AT+CPIN?","READY",2,50);//查詢卡是否插上
if(ret == 0)
{
return NO_SIM_CARD_ERROR;
}
ret = Wait_CREG(3);//查詢卡是否注冊到網絡
if(ret == 0)
{
return SIM_CARD_NO_REG_ERROR;
}
return 1;
}
/***************************************************************
注:當然你可以返回其他值,來確定到底是哪一步發送指令出現失敗了。
****************************************************************/
int config_format(void)
{
u8 ret;
//設置存儲位置
ret = UART1_Send_AT_Command("AT+CPMS=\"SM\",\"ME\",\"SM\"","OK",3,100);
if(ret == 0)
{
return AT_CPMS_ERROR;
}
ret = UART1_Send_AT_Command("AT+CMGF=1","OK",3,50);//配置為TEXT模式
if(ret == 0)
{
return AT_CMGF_ERROR;
}
ret = UART1_Send_AT_Command("AT+CSCS=\"GSM\"","OK",3,50);//設置字符格式
if(ret == 0)
{
return AT_CSCS_ERROR;
}
return 1;
}
int read_message(void)
{
char *buffer_ptr;
u8 i,len;
u8 ret;
memset(num_message,'\0',4);
memset(AT_CMGR,'\0',15);
buffer_ptr = strstr(Uart1_Buf,"\"SM\",");
len = strlen("\"SM\",");
i = len;
if(buffer_ptr != NULL)
{
while(*(buffer_ptr + i) != 0x0D && i < (len+3))
{
num_message[i-len] = *(buffer_ptr + i);
i++;
}
}
else
{
return NO_SMS_LEN_ERROR;
}
memset(AT_CMGR,'\0',15);
strcpy(AT_CMGR,"AT+CMGR=");
strcat(AT_CMGR,num_message);
ret = UART1_Send_AT_Command(AT_CMGR,"OK",3,50);
return ret;
}
/**********************************************/
/*設計思路:
(0)進行串口、定時器初始化工作。
(1)開機等待22秒,等待模塊準備好。
(2)發送相應的指令。
************************************************/
void main(void)
{
u8 i;
int ret;
P0 = P1 = P2 = P3 = 0xff;
Uart1Init(); //串口初始化
Timer0Init();//TIM0初始化
EA = 1; //開啟總中斷
for(i = 0;i < STABLE_TIMES;i++)//等待網絡穩定
{
delay_ms(50);
}
ret = check_status();
if(ret == 1)
{
ret = config_format();//配置
if(ret == 1)
{
LED0 = 0;
}
else
{
LED0 = 1;
}
}
CLR_Buf();
receive_mode = 1;
while (1)
{
delay_ms(50);
LED1 = ~LED1;
if(find_string_flag == 1)
{
delay_ms(5);//延時一點,讓串口把數據接收完成
if(Find("+CMTI"))//說明接收到了短信
{
ret = read_message();
if(ret == 1)
{
if(Find("open"))
{
LED7 = 0;
LED6 = 1;
CLR_Buf();
find_string_flag = 0;
}
else if(Find("close"))
{
LED7 = 1;
LED6 = 0;
CLR_Buf();
find_string_flag = 0;
}
else
{
LED7 = LED7;
LED6 = 0;
CLR_Buf();
find_string_flag = 0;
}
}
}
}
}
}
/*******************************************************************************
* 函數名 : Timer0_ISR
* 描述 : 定時器0中斷服務入口函數,1ms中斷一次
* 輸入 :
* 輸出 :
* 返回 :
* 注意 :
*******************************************************************************/
void Timer0_ISR() interrupt 1
{
TR0=0;//關定時器
TL0 = (65536-20000)%256; //重設定時器初值
TH0 = (65536-20000)/256; //
if(count_20ms > 0) //20ms延時計數器
{
count_20ms--;
}
TR0=1;//開定時器
}
/********************* UART1中斷函數************************/
void UART1_ISR (void) interrupt 4
{
if (RI)
{
RI = 0; //清除RI位
Uart1_Buf[First_Int] = SBUF; //將接收到的字符串存到緩存中
First_Int++; //緩存指針向后移動
if(First_Int > Buf_Max) //如果緩存滿,將緩存指針指向緩存的首地址
{
First_Int = 0;
}
if(receive_mode == 1)
{
if(First_Int > 6)
{
find_string_flag = 1;
}
}
}
if (TI)
{
TI = 0; //清除TI位
}
}
/*******************************************************************************
* 函數名 : CLR_Buf
* 描述 : 清除串口2緩存數據
* 輸入 :
* 輸出 :
* 返回 :
* 注意 :
*******************************************************************************/
void CLR_Buf(void)
{
u8 k;
for(k=0;k<Buf_Max;k++) //將緩存內容清零
{
Uart1_Buf[k] = 0x00;
}
First_Int = 0; //接收字符串的起始存儲位置
}
/*******************************************************************************
* 函數名 : Find
* 描述 : 判斷緩存中是否含有指定的字符串
* 輸入 :
* 輸出 :
* 返回 : unsigned char:1 找到指定字符,0 未找到指定字符
* 注意 :
*******************************************************************************/
u8 Find(u8 *a)
{
ES = 0; //改進程序
if(strstr(Uart1_Buf,a)!=NULL)
{
ES = 1;
return 1;
}
else
{
ES = 1;
return 0;
}
}
/*******************************************************************************
* 函數名 : Wait_CREG
* 描述 : 等待模塊注冊成功
* 輸入 :
* 輸出 :
* 返回 :
* 注意 :
*******************************************************************************/
u8 Wait_CREG(u8 query_times)
{
u8 i;
u8 k;
u8 j;
i = 0;
CLR_Buf();
while(i == 0)
{
UART1_Send_Command("AT+CREG?");
delay_ms(100);
for(k=0;k<Buf_Max;k++)
{
if((Uart1_Buf[k] == '+')&&(Uart1_Buf[k+1] == 'C')&&(Uart1_Buf[k+2] == 'R')&&(Uart1_Buf[k+3] == 'E')&&(Uart1_Buf[k+4] == 'G')&&(Uart1_Buf[k+5] == ':'))
{
if((Uart1_Buf[k+7] == '1')&&((Uart1_Buf[k+9] == '1')||(Uart1_Buf[k+9] == '5')))
{
i = 1;
return 1;
}
}
}
j++;
if(j > query_times)
{
return 0;
}
}
return 0;
}
/*----------------------------
UART1 發送串口數據
-----------------------------*/
void UART1_SendData(u8 dat)
{
ES=0; //關串口中斷
SBUF=dat;
while(TI!=1); //等待發送成功
TI=0; //清除發送中斷標志
ES=1; //開串口中斷
}
/**********************************
發送命令
**********************************/
void UART1_Send_Command(char *s)
{
CLR_Buf();
while(*s)//檢測字符串結束符
{
UART1_SendData(*s++);//發送當前字符
}
UART1_SendLR();
}
/*******************************************************************************
* 函數名 : Second_AT_Command
* 描述 : 發送AT指令函數
* 輸入 : 發送數據的指針、希望收到的應答、發送等待時間(單位:interval_time*20 ms)
* 輸出 :
* 返回 :
* 注意 :
*******************************************************************************/
u8 UART1_Send_AT_Command(u8 *b,u8 *a,u8 wait_time,u16 interval_time)
{
u8 i;
CLR_Buf();
i = 0;
while(i < wait_time)
{
UART1_Send_Command(b);
delay_ms(interval_time);
if(Find(a)) //查找需要應答的字符
{
return 1;
}
i++;
}
return 0;
}
void delay_ms(u16 ms)
{
count_20ms = ms;
while(count_20ms);
}
|