sim868模块

最近使用了SIM868模块做了项目,单片机使用的是STM32F103C8T6,使用串口2与SIM模块通信,实现了打电话、发短信、GPS定位、GPRS发送数据的功能,能够实时定位,1s发送一次定位数据到服务器。

SIM模块代码如下:

#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';		//添加结束符
	
}

示例工程下载:
https://download.csdn.net/download/Emb_2333/12549004

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值