- #include "sim.h"
- #include "delay.h"
- #include "string.h"
- #include "oled.h"
- #include "key.h"
- #include "usart.h"
- #include "usart2.h"
- //SIM868 模块的响应格式为: <回车><换行><响应内容><回车><换行>。 !!!!!!!
- //发送的短信内容:SOS!我们在经纬度为39.915403,116.403906的地方遇险,请求帮助!
- unsigned char Send_Message[] = "0053004F0053002162114EEC57287ECF7EAC5EA64E3A00330039002E003900310035003400300033002C003100310036002E0034003000330039003000367684573065B990479669FF0C8BF76C425E2E52A9FF01";
- unsigned char LBS_Location[30] = {0}; //保存基站定位最近一次读取到的位置信息
- unsigned char SNSS_Location[30] = {0}; //保存SNSS定位最近一次读取到的位置信息
- unsigned char IPaddr_port[] = "AT+CIPSTART="TCP","103.46.128.49","21455""; //GPRS 连接的外网IP和端口号
- unsigned char GPRS_SEND[] = "ID001,39.915403,116.403906"; //GPRS 发送的信息。其中IDxxx为设备的编号,加上纬度,经度
- //发送命令后,检测接收到的应答
- //p:期待的应答结果
- //返回值:0,没有得到期待的应答结果
- //返回值:1,得到期待的应答结果
- #define SIM_Check_OK 1
- #define SIM_Check_ERROR 0
- unsigned char SIM_Check(unsigned char *p)
- {
- if(USART2_RX_STA&0X8000) //判断串口是否接收到一次数据了
- {
- USART2_RX_BUF[USART2_RX_STA&0X7FFF]=0; //在接收到的字符最后添加结束符
-
- if(strstr((const char*)USART2_RX_BUF,(const char*)p) == NULL) //判断 p 是否为 USART2_RX_BUF 的子串
- {
- //return 0;
- return SIM_Check_ERROR;
- }
- }
-
- //return 1;
- return SIM_Check_OK;
- }
- //向SIM800C发送命令
- //cmd:发送的命令字符串(不需要添加回车了)
- //ack:期待的应答结果,如果为空,则表示不需要等待应答
- //waittime:等待时间(单位:10ms)
- //返回值:0,发送成功(得到了期待的应答结果)
- // 1,发送失败
- #define SIM_Send_Cmd_OK 0
- #define SIM_Send_Cmd_ERROR 1
- unsigned char SIM_Send_Cmd(u8 *cmd,u8 *ack,u16 waittime)
- {
- unsigned char res = SIM_Send_Cmd_OK;
-
- USART2_RX_STA=0; //清空接收到的字符串数组
- if((u32)cmd<=0XFF) //发送数字(如发短信的结束符0x1A)
- {
- while((USART2->SR&0X40)==0); //等待上一次串口数据发送完成
- USART2->DR=(u32)cmd;
- }
- else //发送命令
- {
- u2_printf("%s\r\n",cmd);//发送命令
- }
- if(ack&&waittime) //需要等待应答
- {
- while(--waittime) //等待倒计时
- {
- delay_ms(10);
- if(USART2_RX_STA&0X8000)//接收到期待的应答结果
- {
- if(SIM_Check(ack)) //判断SIM模块应答是否正常
- {
- break;
- }
- USART2_RX_STA=0;
- }
- }
- if(waittime==0)res=SIM_Send_Cmd_ERROR; //超时
- }
-
- return res;
- }
- void SIM_Init() //SIM卡初始化
- {
- unsigned char flag=1;
-
- while(SIM_Send_Cmd("AT","OK",100)) //检测是否应答AT指令
- {
- OLED_P8x16Str(0,1, "Sim Fail!");
- delay_ms(400);
- OLED_P8x16Str(0,1, " ");
- delay_ms(300);
- }
- OLED_P8x16Str(0,1, " ");
- OLED_P8x16Str(0,1, "AT is OK!");
-
- SIM_Send_Cmd("ATE0","OK",100);//不回显
- delay_ms(200);
- while(SIM_Send_Cmd("AT+CPIN?","READY",100)) //检测是否存在SIM卡
- {
- OLED_P8x16Str(0,1, "No Sim Card!");
- delay_ms(400);
- OLED_P8x16Str(0,1, " ");
- delay_ms(300);
- }
- OLED_P8x16Str(0,1, "GPS Open...");
- while(SIM_Send_Cmd("AT+CGNSPWR=1","OK",100)) //打开gps定位
- {
- OLED_P8x16Str(0,1, "GPS Open fail!");
- delay_ms(400);
- OLED_P8x16Str(0,1, " ");
- delay_ms(300);
- }
- OLED_P8x16Str(0,1, "GPRS Init...");
- while(flag) //设置GPRS通信
- {
- flag = 0;
- SIM_Send_Cmd("AT+CIPCLOSE=1","ERROR",100); //关闭当前 TCP 连接
- SIM_Send_Cmd("AT+CIPSHUT","OK",100); //关闭场景
-
- if(SIM_Send_Cmd("AT+CGCLASS="B"","OK",1000))flag=1; //设置GPRS移动台类别为B,支持包交换和数据交换
- if(SIM_Send_Cmd("AT+CGDCONT=1,"IP","CMNET"","OK",1000))flag=2; //设置PDP上下文,互联网接协议,接入点等信息
- if(SIM_Send_Cmd("AT+CGATT=1","OK",500))flag=3; //附着GPRS业务
- if(SIM_Send_Cmd("AT+CIPCSGP=1,"CMNET"","OK",500))flag=4; //设置为GPRS连接模式
- if(SIM_Send_Cmd("AT+CIPHEAD=1","OK",500))flag=5; //设置接收数据显示IP头(方便判断数据来源)
- if(flag)
- {
- OLED_P8x16Str(0,1, "GPRS ERROR! ");
- delay_ms(800);
- OLED_P8x16Str(0,1, " ");
- delay_ms(300);
- }
- }
- while(SIM_Send_Cmd(IPaddr_port,"OK",500)) //发起GPRS连接
- {
- OLED_P8x16Str(0,1,"CONNECT FAIL! ");
- delay_ms(400);
- OLED_P8x16Str(0,1, " ");
- delay_ms(300);
- }
- OLED_P8x16Str(0,1, " ");
- OLED_P8x16Str(0,1, "SIM is OK!");
-
- }
- //函数功能:
- //1.不断读取定位信息,并且将有效的数据存储到GPRS_SEND数组中
- //2.将读取到的有效定位数据掉点保存(未实现)
- void SIM_ReadData() //不断读取当前的定位信息
- {
- //获取定位信息
- if(SIM_Send_Cmd("AT+CGNSINF","+CGNSINF: 1,1",100) == SIM_Send_Cmd_OK) //定位数据有效则进行记录
- {
- OLED_P6x8Str(0,5, "SNSS IS OK ");
- SNSS_Save_Location(); //记录定位信息
- OLED_print(SNSS_Location); //OLED显示定位信息
- Change_MessageLocation(SNSS_Location); //修改发送的短信中的定位信息定位信息
- }
- else
- {
- OLED_P6x8Str(0,5, "GPS Location...");
- }
-
- }
- //函数功能:
- //将数据发送到固定的端口中
- void SIM_GprsSend()
- {
- if(SIM_Send_Cmd("AT+CIPSEND",">",500)==0) //发送数据
- {
- //printf("CIPSEND DATA:%s\r\n",p1); //发送数据打印到串口
- u2_printf("%s\r\n",GPRS_SEND);
- delay_ms(50);
- if(SIM_Send_Cmd((u8*)0X1A,"SEND OK",1000)==0)
- {
- OLED_P6x8Str(0,3,"Data send is ok"); //最长等待10s
- }
- else
- {
- OLED_P6x8Str(0,3,"Data send is error");
- }
- delay_ms(500);
- OLED_P8x16Str(0,3," ");
- }
- else
- {
- SIM_Send_Cmd((u8*)0X1B,0,0); //ESC,取消发送
- }
-
- }
- void SIM_SendMessage() //发短信 OK
- {
- OLED_P8x16Str(0,5, " ");
- OLED_P8x16Str(0,5, "Send a Message..");
-
- SIM_Send_Cmd("AT","OK",100);
- SIM_Send_Cmd("AT+CMGF=1","OK",100); //设置短信模式为文本模式
- SIM_Send_Cmd("AT+CSMP=17,167,1,8","OK",100); //设置短信为中英文模式
- SIM_Send_Cmd("AT+CSCS="UCS2"","OK",100); //设置为UCS2字符集编码
- SIM_Send_Cmd("AT+CMGS="0031 0033 003x003x003x003x003x003x003x003x003x"",">",500); //设置对方手机号,需要修改
- SIM_Send_Cmd(Send_Message,">",1000); //发送短信内容
-
- SIM_Send_Cmd((u8*)0X1A,"+CMGS:",1000);//发送结束符,等待发送完成(最长等待10秒钟,因为短信长了的话,等待时间会长一些)
-
- OLED_P8x16Str(0,5, "Finish Send! ");
- delay_ms(500);
- OLED_P8x16Str(0,5, " ");
- }
- void SIM_Call() //打电话 OK
- {
- unsigned char Key;
- unsigned char callbuf[] = "13xxxxxxxxx;"; //预存电话,需要修改
- OLED_P8x16Str(0,5, " ");
- OLED_P8x16Str(0,5, "Call a phone...");
-
- u2_printf("ATD%s\r\n",callbuf); //拨号
-
- while(1)
- {
- Key = KEY_Scan(0);
- if(Key == KEY2_PRES)
- {
- u2_printf("ATH\r\n"); //挂电话
- OLED_P8x16Str(0,5, "over the phone!");
- delay_ms(500);
- OLED_P8x16Str(0,5, " ");
- break;
- }
- }
- }
- //根据模块的基站定位和SNSS定位修改发送的信息和GPRS发送的消息的经纬度
- //参数: *p
- //LBS_Location表示使用的是基站定位
- //SNSS_Location表示的是使用SNSS定位
- void Change_MessageLocation(unsigned char p[])
- {
- unsigned char i;
-
- for(i=12; i<32; i++) //修改报警信息中的经纬度
- {
- if((i==15)||(i==22)||(i==25)) //小数点不修改
- {
- continue;
- }
-
- Send_Message[i*4-1] = p[i-12];
-
- }
-
- for(i=0; i<20; i++) //修改GPRS发送的经纬度
- {
- GPRS_SEND[i+6] = p[i];
- }
-
- }
- void LBS_Save_Location() //保存基站定位最近一次的位置信息, 基站定位是输出 精度,纬度
- {
- unsigned char i,flag = 0;
-
- if((USART2_RX_BUF[2] == '+')&&(USART2_RX_BUF[9] == '0')) //判断SIM模块是否读取到了地址
- {
- for(i=11; flag != 2; i++) //SIM模块LBS定位返回来的信息,第11位开始为经纬度信息。注意sim868返回消息的格式
- {
- if(USART2_RX_BUF[i] == ',')
- {
- flag++;
- }
- LBS_Location[i-11] = USART2_RX_BUF[i]; //记录经纬度
- }
-
- LBS_Location[i-12] = '\0'; //添加结束符
- }
- }
- void OLED_print(unsigned char p[]) //基站定位和SNSS定位显示经纬度到OLED
- {
- unsigned char i,Flag = 0;
- for(i=0;p[i] != '\0';i++)
- {
- if(p[i] == ',') //分开经度和纬度
- {
- p[i] = 0;
- Flag = i;
- break;
- }
- }
-
- if(Flag != 0)
- {
- OLED_P6x8Str(0,6,p);
- OLED_P6x8Str(0,7,p+i+1);
- p[i] = ',';
- }
- }
- void SNSS_Save_Location() //保存SNSS定位最近一次的位置信息,SNSS定位输出是 纬度,经度
- {
- unsigned char i,flag = 0;
-
- for(i=35; flag != 2; i++) //SIM模块SNSS定位返回来的信息,第35位开始为经纬度信息。注意sim868返回消息的格式
- {
- if(USART2_RX_BUF[i] == ',')
- {
- flag++;
- }
- SNSS_Location[i-35] = USART2_RX_BUF[i]; //记录经纬度
- }
-
- SNSS_Location[i-36] = '\0'; //添加结束符
-
- }