基于RTthread的sim800c连接mqtt服务器通信

最近在搞GPRS模块,SIM800C,具体流程是:GPRS先连接TCP服务器,再连接阿里云的MQTT物联网套件,上传给服务器一些消息,服务器收到以后再回复一些指令,或者可以通过手机微信小程序主动下发一些指令给设备。

代码是基于RTthread写的,STM32F103,系统tick 1000,标准库。

分为几个部分:

GPRS.c    //SIM800C连接TCP服务器以及MQTT服务器过程
MQTTClient.c    //MQTT的应用层接口函数

/**
  * @file   GPRS.c
  * @author yufei_qf@foxmail.com
  */ 
#include "GPRS.h" 
  
#define AT_RESP_END_OK    		"OK" 
#define AT_RESP_END_ERROR     	"ERROR" 

#define GPRS_CMD_AT             "AT\r\n"				//1.AT	
#define GPRS_CMD_ATE0           "ATE0\r\n"				//2.关闭回显	
#define GPRS_CMD_AT_CPIN        "AT+CPIN?\r\n"			//3.AT+CPIN? (查看SIM卡的状态)回车,返回:+CPIN:READY  OK(正常)。	
#define GPRS_CMD_AT_CREG        "AT+CREG?\r\n"			//4.网络注册及状态查询; 0, 1, 2, 3, 4, 5 ,
                                                        //	其中 0 代表没有注册网络同时模块没有找到运营商,
                                                        //		 1 代注册到了本地网络, 2 代表找到运营商但没有注册网络,
                                                        //		 3 代表注册被拒绝, 4 代表未知的数据, 5代表注册在漫游状态. 
#define GPRS_CMD_AT_IFC         "AT+IFC=0,0\r\n"		//5.本地流控, 无流控, 2,2: 硬件流控 1,1 软件流控	
#define GPRS_CMD_AT_CIPMODE     "AT+CIPMODE=1\r\n"		//6.设置为透传模式	
#define GPRS_CMD_AT_CGATT       "AT+CGATT?\r\n"			//7. 查询是否成功附着了GPRS网络
#define GPRS_CMD_AT_CGATT_1     "AT+CGATT=1\r\n"    	//   模块开机后首先查询模块是否附着GPRS网络,不要主动设置AT+CGATT=1,除非待机状态
                                                        //   下主动上报+CGATT: 0,此时可以设置AT+CGATT=1,否则不要设置。 
#define GPRS_CMD_AT_CSTT        "AT+CSTT\r\n"			//8. 设置APN,使用默认的APN	 
#define GPRS_CMD_AT_CIICR       "AT+CIICR\r\n"			//9. 激活移动场景激活移动场景模块超时设置40s,如果40s还没有激活成功,模块端会自动
                                                        //上报+PDP:DEACT。如果前面CSQ、CREG、CGATT、AT+CSTT状态都
                                                        //是正常的,移动场景激活失败,那肯定是网络侧原因所致。当然CSQ值过
                                                        //低,比如10以下,移动场景激活成功概率较低。
                                                        //如果移动场景激活失败,执行AT+CIPSHUT(关闭移动场景),模块设置超时时间20s。 
#define GPRS_CMD_AT_CIFSR       "AT+CIFSR\r\n"			//10.获取本地IP,若指令正确,模块将返回随机IP。
														//必须有这一步才能使IP STATE变成IP STATUS,后续去建立具体的连接时才能成功。	
#define GPRS_CMD_AT_CIPSTATUS 	"AT+CIPSTATUS\r\n" 		//11.查看模块的IP STATE是什么状态。	

#define MAX_ERR_Times       4
#define MAX_WAIT_TIME       3000    //3s
#define MAX_READ_TIME       5000 

#define GPRS_DEVICE_NAME   	"uart4"
#define GPRS_buff_size_max 	1024

typedef  struct {
    rt_device_t   dev;           	//设备描述符
    struct rt_semaphore  r_tx;   	//读串口信号量
    char buff[GPRS_buff_size_max];
    unsigned short buff_i;   
    unsigned char errtime;  
}GPRS_DEV ;
static GPRS_DEV GprsDev;

ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t GPRS_stack[ 1024 * 2 ];
static struct rt_thread GPRS_thread;

rt_err_t GPRS_Poweron(void);
rt_err_t GPRS_config(void);


/*
 串口接收的回调函数
 函数中置信号量
 串口一旦接收到了数据, 就调用该函数.
*/
static rt_err_t GPRS_rx_ind(rt_device_t dev, rt_size_t size)
{
    rt_sem_release(&(GprsDev.r_tx));
    return RT_EOK;
}

/*
* 读取数据知道遇到"\r\n"然后再解析收到的数据中是否具有我们想要的包
* 最大等待时间maxtime,
* 返回值:
*    0: 读取超时;
*    1: 读取成功
*   -1: 读取失败,CRC错误.
*/
int GPRS_waitRead(int maxtime, char *str1, char *str2)
{
    rt_tick_t  timeout_tick = 0;
    char ch = 0, last_ch = 0;
    rt_err_t ret;

    RT_ASSERT(GprsDev.dev);

    timeout_tick = rt_tick_get(); //rt_tick_get 获取当前tick.

    /* 清空接收参数.,做接收准备 */ 
    GprsDev.buff_i = 0;
    memset(GprsDev.buff, 0, GPRS_buff_size_max);

    while(1)
    {
        if (rt_tick_get() - maxtime > timeout_tick)
        {
            GprsDev.errtime++;
            return 0;       //读取超时
        }

        /* 等待信号量(信号量在回调函数中被release.) */
        if ((ret = rt_sem_take(&GprsDev.r_tx, 1000)) != RT_EOK)
        {
            rt_kprintf("[GPRS]: Wait Serial sem timeout. reply:%s\r\n", ret);
            continue;
        }
        
        /* read one character from device */
        while (rt_device_read(GprsDev.dev, 0, &ch, 1) == 1)
        {
            if (GprsDev.buff_i < GPRS_buff_size_max)
            {
                GprsDev.buff[GprsDev.buff_i++] = ch;
            }
            else 
            {
				/* 检查是否具有我们想要的数  */
				if (str1)
				{
					if (strstr(GprsDev.buff, str1) != 0)
						return 1;
				}
				
				if (str2)
				{
					if (strstr(GprsDev.buff, str2) != 0)
						return 1;
				}
				
				return -1;
            }
			if ((ch == '\n' && last_ch == '\r'))
			{
				//检查是否具有我们想要的数据
				if (str1)
				{
					if (strstr(GprsDev.buff, str1) != 0)
						return 1;
				}
				
				if (str2)
				{
					if (strstr(GprsDev.buff, str2) != 0)
						return 1;
				}
			}
			last_ch = ch; 
		}
			
        rt_thread_delay(100);
    }
}

/**
 * @brief GPRS_TCP_Response_Check透传模式下连接TCP的反馈结果判断.
 * @return
 *      0: 没有收到消息
 *      1: 收到了连接成功的消息
 *     -1: 收到了错误消息, 命令发送的错误
 *     -2: 收到了服务器关闭的消息.
 */
int GPRS_TCP_Response_Check()
{
    if (strstr(GprsDev.buff, AT_RESP_END_OK) != 0)
    {
        if (strstr(GprsDev.buff, "TCP CLOSED\r\n") != 0 || strstr(GprsDev.buff, "CONNECT FAIL\r\n") != 0)
        {
            rt_kprintf("[GPRS]: Connect Server Fail:%s\r\n", GprsDev.buff);
            return -1;
        }
        else if (strstr(GprsDev.buff, "CONNECT\r\n") != 0)
        {
            rt_kprintf("[GPRS]: Connect Server Sucess:%s\r\n", GprsDev.buff);
            return 1;
        }
    }
	else if(strstr(GprsDev.buff, "ALREAD
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值