STM32实战总结:HAL之GPRS

本文档详细介绍了使用SIM800C模组进行GPRS无线通信的过程,包括模组的启动、TCP连接服务器、温湿度数据传输等步骤。SIM800C是一款四频GSM/GPRS模块,支持通过TCP连接到指定服务器,实现数据传输。文中还涉及到AT指令的使用、波特率同步、SIM卡状态检查、网络注册、GPRS服务粘附等一系列操作,确保无线连接的建立和稳定。
摘要由CSDN通过智能技术生成

关于无线传输的基础知识,参考:

无线通信技术概览_路溪非溪的博客-CSDN博客

和wifi一样,GPRS现在也基本上是使用模组。不过GPRS不用和WiFi一样要输入SSID和密码,开机就会自动联网,所以使用起来更方便一些。但是GPRS要有手机卡,流量是要钱的。

GRPS的天线通常是外置的。

关于天线可参考:物联网天线|IoT天线|GPS天线|WiFi天线- 德宝通信

SIM8000C

SIM800C是一款四频GSM/GPRS模块,支持高达85.6kbps的GPRS数据传输。它具有强大的扩展能力和丰富的接口,包括UART、USB2.0、GPIO等。该模块为客户的应用提供了极大的灵活性和易于集成的能力。

更多参考:SIM800C

AT指令示例:

更多详细内容查看厂家给的模组使用手册,此处不再赘述。

关键代码

/* Includes ------------------------------------------------------------------*/
#include "MyApplication.h"

/* Private define-------------------------------------------------------------*/
#define TCP_Server  (uint8_t*)"AT+CIPSTART=\"TCP\",\"115.29.109.104\",6511\r\n"  //Doit.am远程信息转发服务

/* Private variables----------------------------------------------------------*/
static uint8_t SIM800C_Connect_Error_Flag = FALSE; //SIM800C联网错误标志位

/* Private function prototypes------------------------------------------------*/
static void StartUp(void);             //启动SIM800C
static void TCP_Connect_Server(void);  //通过TCP连接服务器
static void Transfer_SHT30(void);      //传送SHT30的温湿度
static void Receive_Information(void); //接收信息
static void DMA_Receive_Set(void);     //DMA重新设置
static void Error(void);               //错误信息

//内部函数
static void SendAT(uint8_t *,uint8_t *);            //发送AT指令

static void Moudle_Sync_Baud(void);                 //同步波特率
static void Moudle_Check_SIM_Status(void);          //检查SIM卡状态
static void Moudle_Check_Network_Register(void);    //检查网络注册
static void Moudle_Check_Attach_GPRS_Service(void); //检查粘附GPRS网络
static void Moudle_BringUp_Wireless_Connect(void);  //建立无线链接
static void Moudle_StartUp_TCP_Connect(void);       //开始TCP连接

/* Public variables-----------------------------------------------------------*/
SIM800C_t  SIM800C = 
{
	FALSE,
	TIMER6_10S,

	StartUp,
	TCP_Connect_Server,
	Transfer_SHT30,
	Receive_Information,
	DMA_Receive_Set,
	Error
};

/*
	* @name   StartUp
	* @brief  启动SIM800C
	* @param  None
	* @retval None      
*/
static void StartUp() 
{
	//如果模块处于开机状态,先关机
	if(READ_GPRS_STATUS == GPIO_PIN_SET)
	{
		printf("The module of SIM800C shutdown!\r\n");
		//模块关机
		SET_GPRS_PWRKEY;
		HAL_Delay(1000);
		HAL_Delay(1000);
		HAL_Delay(1000);
		CLR_GPRS_PWRKEY;
		
		//等待模块关机完成
		Timer6.usDelay_Timer = 0;
		while(READ_GPRS_STATUS == GPIO_PIN_SET)
		{
			if(Timer6.usMCU_Run_Timer >= TIMER6_10S)
			{
				SIM800C.Error();
				break;
			}
		}
		//按手册提示,关机后迅速重启模块,至少延时800ms
		HAL_Delay(1000);
	}
	
	//如果模块处于关机状态,进行开机
	if(READ_GPRS_STATUS == GPIO_PIN_RESET)
	{
		printf("The module of SIM800C startup!\r\n");
		//模块开机
		SET_GPRS_PWRKEY;
		HAL_Delay(1000);
		HAL_Delay(1000);
		CLR_GPRS_PWRKEY;
		
		//等待模块开机完成
		Timer6.usDelay_Timer = 0;
		while(READ_GPRS_STATUS == GPIO_PIN_RESET)
		{
			if(Timer6.usMCU_Run_Timer >= TIMER6_10S)
			{
				SIM800C.Error();
				break;
			}
		}
	}
}

/*
	* @name   SendAT
	* @brief  发送AT指令
	* @param  AT_Command  -> 待发送的AT指令
	          Respond_Str -> 回应数据中包含的字符串
	* @retval None      
*/
static void SendAT(uint8_t * AT_Command,uint8_t * Respond_Str)
{
	uint8_t* const  Ptr_AT_Command   = AT_Command;
	uint8_t* const  Ptr_Respond_Str  = Respond_Str;
	
	//DMA重新接收设置
	SIM800C.DMA_Receive_Set();
	
	//发送AT指令
	UART2.SendString(Ptr_AT_Command);	
	//打印信息
	printf("%s",Ptr_AT_Command);
	
	//等待模块回应数据,超时错误处理
	Timer6.usDelay_Timer = 0;
	while(strstr((const char*)UART2.pucRec_Buffer,"\r\n") == NULL)
	{
		if(Timer6.usDelay_Timer > TIMER6_100mS)
		{
			SIM800C.Error();
			break;
		}
	}
	//延时10ms,接收完全部字节
	HAL_Delay(10);
	
	//模块回应数据处理处理
	if(strstr((const char*)UART2.pucRec_Buffer,(const char*)Ptr_Respond_Str) == NULL)
	{
		SIM800C.Error();
	}
	
	//打印信息
	printf("%s",UART2.pucRec_Buffer);
}

/*
	* @name   TCP_Connect_Server
	* @brief  通过TCP连接服务器
	* @param  None
	* @retval None      
*/
static void TCP_Connect_Server()
{
  __HAL_UART_DISABLE_IT(&huart2,UART_IT_IDLE);   //禁止串口2的空闲中断

	SIM800C.StartUp();                      //启动GPRS模块
	Moudle_Sync_Baud();                     //同步波特率
	SendAT(AT_CMD_ECHO_OFF,(uint8_t*)"OK"); //关闭回显
	Moudle_Check_SIM_Status();              //检查SIM卡状态
	SendAT(AT_CMD_CCID,(uint8_t*)"OK");     //显示ICCID
	Moudle_Check_Network_Register();        //检查网络注册
	Moudle_Check_Attach_GPRS_Service();     //检查粘附GPRS网络
	SendAT(AT_CMD_CIPMODE,(uint8_t*)"OK");  //设置为透传模式
	SendAT(AT_CMD_CSTT,(uint8_t*)"OK");     //开始任务,设置APN
	Moudle_BringUp_Wireless_Connect();      //建立无线链接
    SendAT(AT_CMD_CIFSR,(uint8_t*)".");     //获取本地IP地址
	Moudle_StartUp_TCP_Connect();           //开始TCP连接
    SIM800C.DMA_Receive_Set();	            //DMA重新接收设置,开始接收TCP服务器的指令

	if(SIM800C.TCP_Connect_Status == TRUE)
		__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);   //使能串口2的空闲中断
}

/*
	* @name   Moudle_Sync_Baud
	* @brief  同步波特率
	* @param  None 
	* @retval None      
*/
static void Moudle_Sync_Baud()
{
	SIM800C_Connect_Error_Flag = FALSE;
	LED.LED_OFF(LED2);
	LED.LED_OFF(LED3);
	HAL_GPIO_WritePin(OUT_NPN_GPIO_Port,OUT_NPN_Pin,GPIO_PIN_RESET);
	
	Timer6.usDelay_Timer = 0;
	do
	{
		//DMA重新接收设置
   	SIM800C.DMA_Receive_Set();
		
		//发送AT指令
		UART2.SendString(AT_CMD_AT);
		//打印信息
		printf("%s",AT_CMD_AT);
		//延时100ms,等待接收完成
		HAL_Delay(100);
		
		//打印信息
		printf("%s",UART2.pucRec_Buffer);
		
		//超时处理
		if(Timer6.usDelay_Timer >= TIMER6_10S)
		{
			SIM800C.Error();
			break;
		}
	}
	while(strstr((const char*)UART2.pucRec_Buffer,"OK") == NULL);
}  

/*
	* @name   Moudle_Check_SIM_Status
	* @brief  检查SIM卡状态
	* @param  None 
	* @retval None      
*/
static void Moudle_Check_SIM_Status()
{
	if(SIM800C_Connect_Error_Flag == FALSE)
	{
		Timer6.usDelay_Timer = 0;
		do
		{
			//DMA重新接收设置
			SIM800C.DMA_Receive_Set();
			
			//发送AT指令
			UART2.SendString(AT_CMD_CPIN);
			//打印信息
			printf("%s",AT_CMD_CPIN);
			//延时1000ms,等待接收完成
			HAL_Delay(1000);
			
			//打印信息
			printf("%s",UART2.pucRec_Buffer);
			
			//超时处理
			if(Timer6.usDelay_Timer >= TIMER6_10S)
			{
				SIM800C.Error();
				break;
			}
		}
		while(strstr((const char*)UART2.pucRec_Buffer,"OK") == NULL);
	}
}

/*
	* @name   Moudle_Check_Network_Register
	* @brief  检查网络注册
	* @param  None 
	* @retval None      
*/
static void Moudle_Check_Network_Register()
{
	if(SIM800C_Connect_Error_Flag == FALSE)
	{
		Timer6.usDelay_Timer = 0;
		while(1)
		{
			//DMA重新接收设置
			SIM800C.DMA_Receive_Set();
			//发送AT指令
			UART2.SendString(AT_CMD_CREG);
			//打印信息
			printf("%s",AT_CMD_CREG);
			//延时100ms,等待接收完成
			HAL_Delay(100);		
			//打印信息
			printf("%s",UART2.pucRec_Buffer);
			//判断注册
			if((strstr((const char*)UART2.pucRec_Buffer,",1") != NULL) || (strstr((const char*)UART2.pucRec_Buffer,",5") != NULL))
			{
				break;
			}
			else
			{
				HAL_Delay(1000);
				HAL_Delay(1000);
			}
			
			//超时处理
			if(Timer6.usDelay_Timer >= TIMER6_2min)
			{
				SIM800C.Error();
				break;
			}
		}
	}
}

/*
	* @name   Moudle_Check_Attach_GPRS_Service
	* @brief  建立无线链接
	* @param  None 
	* @retval None      
*/
static void Moudle_Check_Attach_GPRS_Service()
{
	if(SIM800C_Connect_Error_Flag == FALSE)
	{
		Timer6.usDelay_Timer = 0;
		while(1)
		{
			//输出信号强度
			SendAT(AT_CMD_CSQ,(uint8_t*)"OK");
			
			//DMA重新接收设置
			SIM800C.DMA_Receive_Set();
			//发送AT指令
			UART2.SendString(AT_CMD_CGATT);
			//打印信息
			printf("%s",AT_CMD_CGATT);
			//延时100ms,等待接收完成
			HAL_Delay(100);		
			//打印信息
			printf("%s",UART2.pucRec_Buffer);
			//判断注册
			if(strstr((const char*)UART2.pucRec_Buffer,"+CGATT: 1") != NULL)
			{
				break;
			}
			else
			{
				HAL_Delay(1000);
				HAL_Delay(1000);
			}
			
			//超时处理
			if(Timer6.usDelay_Timer >= TIMER6_2min)
			{
				SIM800C.Error();
				break;
			}
		}
	}
}

/*
	* @name   Moudle_BringUp_Wireless_Connect
	* @brief  建立无线链接
	* @param  None 
	* @retval None      
*/
static void Moudle_BringUp_Wireless_Connect()
{
	if(SIM800C_Connect_Error_Flag == FALSE)
	{
		Timer6.usDelay_Timer = 0;
		while(1)
		{
			//DMA重新接收设置
			SIM800C.DMA_Receive_Set();
			//发送AT指令
			UART2.SendString(AT_CMD_CIICR);
			//打印信息
			printf("%s",AT_CMD_CIICR);
			//延时100ms,等待接收完成
			HAL_Delay(100);		
			//打印信息
			printf("%s",UART2.pucRec_Buffer);
			//建立无线链接成功
			if(strstr((const char*)UART2.pucRec_Buffer,"OK") != NULL)
			{
				LED.LED_ON(LED2);
				break;
			}
			//建立无线链接失败
			if(strstr((const char*)UART2.pucRec_Buffer,"ERROR") != NULL)
			{
				SIM800C.Error();
				break;
			}
			
			//超时处理
			if(Timer6.usDelay_Timer >= TIMER6_85S)
			{
				SIM800C.Error();
				break;
			}
		}
	}
}

/*
	* @name   Moudle_StartUp_TCP_Connect
	* @brief  开始TCP连接
	* @param  None 
	* @retval None      
*/
static void Moudle_StartUp_TCP_Connect()
{
	if(SIM800C_Connect_Error_Flag == FALSE)
	{

		printf("Connect TCP Server!\r\n");

		Timer6.usDelay_Timer = 0;
		while(1)
		{
			//DMA重新接收设置
			SIM800C.DMA_Receive_Set();
			//发送AT指令
			UART2.SendString(TCP_Server);
			//打印信息
			printf("%s",TCP_Server);
			//等待模块返回数据
      while(Timer6.usDelay_Timer < TIMER6_160S)
      {
      	if((strstr((const char*)UART2.pucRec_Buffer,"CONNECT") != NULL) | (strstr((const char*)UART2.pucRec_Buffer,"FAIL") != NULL))
      	{
      		break;
      	}
      }	
      //延时100ms,等待接收完成
			HAL_Delay(100);
      
			//打印信息
			printf("%s",UART2.pucRec_Buffer);

			//TCP服务器链接失败
			if(strstr((const char*)UART2.pucRec_Buffer,"FAIL") != NULL)
			{
				printf("Connect TCP Server Failure!\r\n");

				SIM800C.TCP_Reconnect_Timer = 0;
				SIM800C.Error();
				break;
			}
			
			//TCP服务器链接成功
			if(strstr((const char*)UART2.pucRec_Buffer,"CONNECT") != NULL)
			{
				printf("Connect TCP Server Success!\r\n");
				
				SIM800C.TCP_Connect_Status  = TRUE;
				SIM800C.TCP_Reconnect_Timer = 0;
				LED.LED_ON(LED3);
				break;
			}
			
			//超时处理
			if(Timer6.usDelay_Timer >= TIMER6_160S)
			{
				SIM800C.TCP_Reconnect_Timer = 0;
				SIM800C.Error();
				break;
			}
		}
	}
}


/*
	* @name 	Transfer_SHT30
	* @brief	传送SHT30的温湿度
	* @param	NONE
	* @retval None			
*/
static void Transfer_SHT30()
{
	float 	 Temp_float = 0;
	uint16_t Temp_uint16 = 0;
	//温度值  -40至125℃,精度0.1℃
	if(SHT30.fTemperature < 0)
	{
		Temp_float = 0 - SHT30.fTemperature;
		*(UART2.pucSend_Buffer + 0) = '-';
	}
	else
	{
		Temp_float = SHT30.fTemperature;
		*(UART2.pucSend_Buffer + 0) = ' ';
	}
	
	Temp_uint16 = (uint16_t)(Temp_float*10);
	if(Temp_uint16 < 10) //0.x
	{
		*(UART2.pucSend_Buffer + 1) = ' ';
		*(UART2.pucSend_Buffer + 2) = ' ';
		*(UART2.pucSend_Buffer + 3) = '0';
		*(UART2.pucSend_Buffer + 4) = '.';
		*(UART2.pucSend_Buffer + 5) = Temp_uint16 + '0';
	}
	else if(Temp_uint16 < 100)//x.x
	{
		*(UART2.pucSend_Buffer + 1) = ' ';
		*(UART2.pucSend_Buffer + 2) = ' ';
		*(UART2.pucSend_Buffer + 3) = Temp_uint16/10 + '0';
		*(UART2.pucSend_Buffer + 4) = '.';
		*(UART2.pucSend_Buffer + 5) = Temp_uint16%10 + '0';
	}
	else if(Temp_uint16 < 1000)//xx.x
	{
		*(UART2.pucSend_Buffer + 1) = ' ';
		*(UART2.pucSend_Buffer + 2) = Temp_uint16/100 + '0';
		*(UART2.pucSend_Buffer + 3) = Temp_uint16%100/10 + '0';
		*(UART2.pucSend_Buffer + 4) = '.';
		*(UART2.pucSend_Buffer + 5) = Temp_uint16%10 + '0';
	}
	else//xxx.x
	{
		*(UART2.pucSend_Buffer + 1) = Temp_uint16/1000 + '0';
		*(UART2.pucSend_Buffer + 2) = Temp_uint16%1000/100 + '0';
		*(UART2.pucSend_Buffer + 3) = Temp_uint16%100/10 + '0';
		*(UART2.pucSend_Buffer + 4) = '.';
		*(UART2.pucSend_Buffer + 5) = Temp_uint16%10 + '0';
	}
	//数据传送
	UART2.SendString((uint8_t *)"The Temperature of SHT30 is ");
	HAL_Delay(3);  //延时,等待字符串发送完	 时间 = (11*1000ms)/115200 * 28 = 2.68ms
	UART2.SendArray(UART2.pucSend_Buffer,6);
	HAL_Delay(1);  //延时,等待数组发送完 		时间 = (11*1000ms)/115200 * 6 = 0.58ms
	UART2.SendString((uint8_t *)"℃\r\n");
	HAL_Delay(1);  //延时,等待字符串发送完	 时间 = (11*1000ms)/115200 * 4 = 0.39ms
	
	//湿度值 0 - 100%RH,精度1%RH
	if(SHT30.ucHumidity < 10)
	{
		*(UART2.pucSend_Buffer + 0) = ' ';
		*(UART2.pucSend_Buffer + 1) = SHT30.ucHumidity + '0';
	}
	else
	{
		*(UART2.pucSend_Buffer + 0) = SHT30.ucHumidity/10 + '0';
		*(UART2.pucSend_Buffer + 1) = SHT30.ucHumidity%10 + '0';
	}
	
	*(UART2.pucSend_Buffer + 2) = '%';
	*(UART2.pucSend_Buffer + 3) = 'R';
	*(UART2.pucSend_Buffer + 4) = 'H';

	//数据传送
	UART2.SendString((uint8_t *)"The Humidity of SHT30 is ");
	HAL_Delay(3);  //延时,等待字符串发送完	 时间 = (11*1000ms)/115200 * 25 = 2.39ms
	UART2.SendArray(UART2.pucSend_Buffer,5);
}

/*
	* @name 	Receive_Information
	* @brief	接收信息
	* @param	None 
	* @retval None			
*/
static void Receive_Information()
{ 
	if(SIM800C.TCP_Connect_Status == TRUE)
	{
		printf("Received information from the TCP server\r\n");
		printf("%s",UART2.pucRec_Buffer);
		printf("\r\n");
		
		//切换继电器状态
		if(strstr((const char*)UART2.pucRec_Buffer,"Flip Relay") != NULL)
		{
			Relay.Relay_Flip();
		}
		
		if(strstr((const char*)UART2.pucRec_Buffer,"Flip Buzzer") != NULL)
		{
			if(Buzzer.Status == Buzzer_Status_OFF)
			{
				Buzzer.ON();
			}
			else
			{
				Buzzer.OFF();
			}
		}
		
		//DMA重新接收设置,接收TCP服务器的新指令
		SIM800C.DMA_Receive_Set();
	}
}

/*
	* @name 	DMA_Receive_Set
	* @brief	DMA接收设置
	* @param	None 
	* @retval None			
*/
static void DMA_Receive_Set(void)
{
	//串口2禁止DMA接收
	HAL_UART_DMAStop(&huart2);
	//清缓存
	Public.Memory_Clr(UART2.pucRec_Buffer,strlen((const char*)UART2.pucRec_Buffer));		
	//串口2开启DMA接收
	HAL_UART_Receive_DMA(&huart2,UART2.pucRec_Buffer,UART2_Rec_LENGTH);
}

/*
	* @name 	Error
	* @brief	错误信息
	* @param	None 
	* @retval None			
*/
static void Error()
{
	SIM800C_Connect_Error_Flag	= TRUE;
	SIM800C.TCP_Reconnect_Timer = 0;
	HAL_GPIO_WritePin(OUT_NPN_GPIO_Port,OUT_NPN_Pin,GPIO_PIN_SET);
}
/*************************************
  End Of File
*************************************/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值