BC28 NB-IOT模块调试记录

1、A08版本软件域名解析很慢的情况

       用A07版本做域名解析的时候发现很快,但是升级到A08版本,发现变得很慢,咨询原厂说是域名解析配置不对,A08默认是3gpp的epco,国内运营商的IE类型 是pco

       通过这个指令配置

                      AT+NCONFIG=PCO_IE_TYPE,PCO

 

2、BC28模块会每隔1小时自己启动

       通过长时间测试发现,模块会每隔1小时启动一次,导致让费电量。咨询原厂才发现是模块里面因为集成的华为平台连接功能,默认是打开的,需要关闭才行

       指令

             AT+QREGSWT=2

 

3、BC28 进入休眠的问题

        BC28进入休眠的时候,通信串口的TX存在一个 0.03V的虚电压,这里会导致休眠后,电流为100多ua,并且还会漂移,所以在主控那里休眠后需要将这个口拉低就不存在电流漏电

 

4、BC28 连不上基站降低功耗的办法

        由于板子上没有设计模块断电的电路,当模块连接不上基站的时候,模块还会一直去连接,导致功耗大的情况,这时可以在联网超时的时候发送如下指令,关闭模块搜索基站

"AT+COPS=2\r\n"

 

5、NB读卡问题

         在调试的时候出现,有些卡能读的到的有些卡不能读到的情况,最好发现是卡槽的问,有些卡偏薄一点,导致卡槽关闭后还是接触不良。所以卡槽这块也需要注意

 

6、BC28驱动代码

/*********************************************
* @文件: driverBC28.c
* @作者: cjx
* @版本: v1.0.1
* @时间: 2020-02-21
* @概要: BC28 连接驱动
*********************************************/
#include "libraryAll.h"
#include "ioctrl.h"
#include "public.h"

/********************************************
基本宏定义区
*********************************************/
//IO宏定义
#define BC28_TX_PORT			GPIO_PORT_1
#define BC28_TX_PIN				GPIO_PIN_2
#define BC28_RX_PORT			GPIO_PORT_1
#define BC28_RX_PIN				GPIO_PIN_3
#define BC28_RST_PORT			GPIO_PORT_2
#define BC28_RST_PIN			GPIO_PIN_4

#define BC28_RST_EN()			GPIO_SetActive(BC28_RST_PORT, BC28_RST_PIN)
#define BC28_RST_DI()			GPIO_SetInactive(BC28_RST_PORT, BC28_RST_PIN)

//AT命令定义
#define AT						"AT\r\n"
#define ATI						"ATI\r\n"
#define AT_RST					"AT+RST\r\n"
#define AT_GMR					"AT+CGMS\r\n" //获取软件版本
#define AT_CGSN 				"AT+CGSN=1\r\n" //获取IMEI
#define AT_CIMI 				"AT+CIMI\r\n" //获取IMSI
#define AT_ICCID 				"AT+NCCID\r\n" //获取ICCID
#define AT_CGATT				"AT+CGATT?\r\n" //查询网络附着
#define AT_CSQ					"AT+CSQ\r\n" //查询信号强度
#define AT_CGDCONT 				"AT+CGDCONT?\r\n" //查询APN
#define AT_CSCON 				"AT+CSCON=1\r\n" //开启nb连接状态打印
#define AT_CPSMS				"AT+CPSMS=1,,,01001010,00000101\r\n" //修改PSM模式参数 TAU:100H act:10s
#define AT_QREGSWT				"AT+QREGSWT=2\r\n" //关闭自启动
#define AT_NRB					"AT+NRB\r\n" //模块复位
#define AT_COPS					"AT+COPS=1,2,\"46000\"\r\n" //手动入网
#define AT_NPSMR				"AT+NPSMR=1\r\n" //提示休眠状态
#define AT_PSM_GET				"AT+CPSMS?\r\n"
#define AT_COPS_CLOSE			"AT+COPS=2\r\n"  //关闭网络

//其他定义 	
#define SOCKET_TYPE				'U'

//BC28 工作步骤
enum
{
	E_BC28_STEP_INIT = 0, // 初始化步骤
	E_BC28_STEP_SETUP, //基础设置
	E_BC28_STEP_GET_INFO, //获取信息
	E_BC28_STEP_CGATT, //查询网络附着
	E_BC28_STEP_GET_NET_INFO, //查询网络信息
	E_BC28_STEP_DNS, //域名解析
	E_BC28_STEP_DNS_STATUS, //域名解析状态
	E_BC28_STEP_FD, //创建套接字
	E_BC28_STEP_FD_STATUS, //套接字状态
	E_BC28_STEP_CONNECT, //连接服务器
	E_BC28_STEP_CONNECT_STATUS, //连接状态
	E_BC28_STEP_END,
};

/********************************************
基本数据区
*********************************************/
static struct{
	T_U32 u32Step; //工作步骤
	T_U32 u32Status; //工作状态
	
	T_U32 u32BC28SleepFlg; //模块休眠状态 0:未休眠 1:休眠
	T_U32 u32UartEn; //串口是否使能用的时候串口才使能,不用的时候设置成输入  0:非使能 1:使能
	T_U8 u8RxCache[1];
	
}g_stThisCtl; //相应芯片的控制数据
static S_NBInfo g_stNBInfo ; //存储NB信息
static struct{
	T_S8 s8Domain1[50]; //域名1
	T_S8 s8Port1[10]; //端口1
	T_S8 s8Domain2[50]; //域名2
	T_S8 s8Port2[10]; //端口2
}g_stServerInfo; //存储服务器信息
static struct{
	T_S8 s8IP1[20]; //IP1
	T_S8 s8Fd1;
	T_S8 s8IP2[20]; //IP2
	T_S8 s8Fd2;
}g_stSocketInfo ; //socket信息
static T_U8 g_u8ServerData[NET_READ_CACHE_SIZE]; //接收缓冲
static T_S8 g_s8AtCache[300]; //AT指令缓存
static T_S8 g_s8SeverDataHead[30]; //服务器数据头

//应用层访问数据定义
static S_DriverDatas g_DriverDatas; //应用层读取数据
static T_U8 g_u8ReadDataCache[sizeof(S_DriverReadNet)]; //数据缓冲,根据实际需要定制大小
//static T_U8 g_u8NetStatus __attribute__((section("retention_mem_area0"), zero_init));  //这个变量要在休眠后保持

/********************************************
内部函数声明区
*********************************************/
static T_VOID _Pop(
	T_U8 u8Type,
	T_U8 *pu8Data,
	T_U32 u32Len);

static T_VOID BC28_RxHandler(T_S8 *ps8Data, T_U32 u32Len);
static T_VOID BC28_Rst(T_VOID);
static void BC28_RxCb(uint8_t status);
//static void BC28_TxCb(uint8_t status);
static T_VOID BC28_StartRevData(T_S8 s8Fd);

/********************************************
自定义函数区
*********************************************/

/********************************************
串口操作函数
*********************************************/

//串口数据定义
static S_UartRx g_stUartRx; //串口接收数据,主要这个数据初始化后不要把数据地址清除了
static T_U8 g_u8RxCache[NET_READ_CACHE_SIZE]; //接收缓冲

/********************************************
 *功能:串口接收数据
 *输入:u8RxData: 接收的数据
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID UART_Rx(T_U8 u8RxData)
{
	g_stUartRx.u8RxFlag = 1;
	g_stUartRx.u32RxChkFullTime = 0;
	
	//数据入缓冲,不要越界
	if(g_stUartRx.u32RxLen < sizeof(g_u8RxCache))
	{
		g_stUartRx.pu8RxData[g_stUartRx.u32RxLen++] = u8RxData;
	}
}

/********************************************
 *功能:串口发生数据
 *输入:pu8TxData: 发送的数据
        u32Len: 发送的长度
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID UART_Tx(T_U8 *pu8TxData, T_U32 u32Len)
{
	//uart2_write((uint8_t *)pu8TxData, u32Len, BC28_TxCb);
	T_U32 u32i = 0;
	for(u32i = 0; u32i < u32Len; u32i++)
	{
		uart2_txdata_setf(pu8TxData[u32i]);
		while(0 == uart2_txfifo_full_getf());
		uart2_thr_empty_setf(0);
	}
}

/********************************************
 *功能:串口接收数据清除
 *输入:无
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID UART_RxClear(T_VOID)
{
	g_stUartRx.u8RxFlag = 0;
	g_stUartRx.u32RxLen = 0;
	g_stUartRx.u32RxChkFullTime = 0;
}

/********************************************
 *功能:串口接收任务
 *输入:pvData: 任务数据
 *输出:无
 *条件:无
 *返回:成功:RET_SUCCESS 
 		失败:RET_FAILED 
 注意:
*********************************************/
static T_VOID UART_RxTaskHandler(T_VOID *pvData)
{  
	//接收数据处理部分
	if(1 == g_stUartRx.u8RxFlag)
	{
		g_stUartRx.u32RxChkFullTime += UART_RX_TASK_PEOD;
		
		if(g_stUartRx.u32RxChkFullTime >= UART_RX_FULL_TIME)
		{
			BC28_RxHandler((T_S8 *)g_stUartRx.pu8RxData, g_stUartRx.u32RxLen);
			//接收完一条后清除数据
			UART_RxClear();
		}		
	}

	MDL_DRVTIMER_Add(UART_RxTaskHandler, T_NULL, UART_RX_TASK_PEOD, 0);
}

/********************************************
 *功能:串口初始化
 *输入:无
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID UART_Init(T_VOID)
{
	//引脚任务初始化
	GPIO_ConfigurePin(BC28_TX_PORT, BC28_TX_PIN, OUTPUT, PID_UART2_TX, false);
    GPIO_ConfigurePin(BC28_RX_PORT, BC28_RX_PIN, INPUT, PID_UART2_RX, false);
	SetBits16(CLK_PER_REG, UART2_ENABLE, 1); 
	uart2_init(UART_BAUDRATE_9K6, UART_FRAC_BAUDRATE_9K6, UART_CHARFORMAT_8);
	uart2_read((uint8_t *)g_stThisCtl.u8RxCache, 1, BC28_RxCb);
	
	//数据清零并初始化
	memset(&g_stUartRx, 0, sizeof(g_stUartRx));
	memset(&g_u8RxCache, 0, sizeof(g_u8RxCache));
	g_stUartRx.pu8RxData = g_u8RxCache; //指向缓存地址,其他地方不要再动这个变量
	
	//接收任务启动
	MDL_DRVTIMER_Add(UART_RxTaskHandler, T_NULL, UART_RX_TASK_PEOD, 0);
}

/********************************************
BC28 操作函数
*********************************************/
static void BC28_RxCb(uint8_t status)
{
	UART_Rx(g_stThisCtl.u8RxCache[0]);
	uart2_read((uint8_t *)g_stThisCtl.u8RxCache, 1, BC28_RxCb);
}
#if 0
static void BC28_TxCb(uint8_t status)
{
}
#endif
static T_VOID BC28_UARTConfInput(T_VOID)
{
	GPIO_ConfigurePin(BC28_TX_PORT, BC28_TX_PIN, INPUT, PID_GPIO, false);
	GPIO_ConfigurePin(BC28_RX_PORT, BC28_RX_PIN, INPUT, PID_GPIO, false);	
	
	g_stThisCtl.u32UartEn = 0;
}
static T_VOID BC28_UARTConfUart(T_VOID)
{
	if(0 == g_stThisCtl.u32UartEn)
	{
		UART_Init();
		g_stThisCtl.u32UartEn = 1;
	}
}

/********************************************
 *功能:串口发生数据
 *输入:pu8TxData: 发送的数据
        u32Len: 发送的长度
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_Tx(T_U8 *pu8TxData, T_U32 u32Len)
{
	BC28_UARTConfUart();
	if(g_stThisCtl.u32BC28SleepFlg)
	{
		//唤醒模块
		UART_Tx(AT, sizeof(AT)-1);
		g_stThisCtl.u32BC28SleepFlg = 0;
		
		T_U32 u32Delay = 10000;
		while(u32Delay--);
	}

	UART_Tx(pu8TxData, u32Len);
}

/********************************************
 *功能:发送数据到服务器
 *输入:pu8Buf: 发送的数据
        u32Len: 发送的长度
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_SendToSever(T_U8 *pu8Buf, T_U32 u32Len)
{  
	T_U32 u32Poi = 0;
	
	if(E_NET_STATUS_SERVER_CONNECTED == g_stThisCtl.u32Status)
	{
		//发送到服务器1
		if('\0' != g_stSocketInfo.s8Fd1)
		{
			memset(g_s8AtCache, 0, sizeof(g_s8AtCache));
			u32Poi = 0;
			memcpy(&g_s8AtCache[u32Poi], "AT+NSOST=", sizeof("AT+NSOST=")-1);
			u32Poi += sizeof("AT+NSOST=") - 1;
			g_s8AtCache[u32Poi++] = g_stSocketInfo.s8Fd1;
			g_s8AtCache[u32Poi++] = ',';
			memcpy(&g_s8AtCache[u32Poi], g_stSocketInfo.s8IP1, strlen(g_stSocketInfo.s8IP1));
			u32Poi += strlen(g_stSocketInfo.s8IP1);
			g_s8AtCache[u32Poi++] = ',';
			memcpy(&g_s8AtCache[u32Poi], g_stServerInfo.s8Port1, strlen(g_stServerInfo.s8Port1));
			u32Poi += strlen(g_stServerInfo.s8Port1);
			g_s8AtCache[u32Poi++] = ',';
			g_s8AtCache[u32Poi++] = u32Len/100 +'0';
			g_s8AtCache[u32Poi++] = u32Len/10%10 +'0';
			g_s8AtCache[u32Poi++] = u32Len%10 +'0';
			g_s8AtCache[u32Poi++] = ',';
			if((u32Poi + 2*u32Len) < sizeof(g_s8AtCache))
			{
				GetBufHexString(&g_s8AtCache[u32Poi], pu8Buf, u32Len, 0);
				u32Poi += 2*u32Len;
			}
			memcpy(&g_s8AtCache[u32Poi], ",1\r\n", sizeof(",1\r\n")-1);
			u32Poi += sizeof(",1\r\n")-1;
			
			BC28_Tx((T_U8 *)g_s8AtCache, u32Poi);
			
		}
	}
}

/********************************************
 *功能:域名解析
 *输入:ps8Domain: 域名
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_DNS(T_S8 *ps8Domain)
{
	T_U32 u32Poi = 0;
	
	memset(g_s8AtCache, 0, sizeof(g_s8AtCache));
	u32Poi = 0;
	memcpy(&g_s8AtCache[u32Poi], "AT+QDNS=0,", sizeof("AT+QDNS=0,")-1);
	u32Poi += sizeof("AT+QDNS=0,") - 1;
	memcpy(&g_s8AtCache[u32Poi], ps8Domain, strlen(ps8Domain));
	u32Poi += strlen(ps8Domain);
	memcpy(&g_s8AtCache[u32Poi], "\r\n", sizeof("\r\n")-1);
	u32Poi += sizeof("\r\n")-1;
	
	BC28_Tx((T_U8 *)g_s8AtCache, u32Poi);
}

/********************************************
 *功能:连接套接字
 *输入:s8Fd: 套接字编号
        s8Type:协议类型 'U':UDP 'T':TCP
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_CreateSocket(T_S8 s8Fd, T_S8 s8Type)
{
	T_U32 u32Poi = 0;
	
	memset(g_s8AtCache, 0, sizeof(g_s8AtCache));
	u32Poi = 0;
	memcpy(&g_s8AtCache[u32Poi], "AT+NSOCR=DGRAM,17,4587,1,AF_INET\r\n", sizeof("AT+NSOCR=DGRAM,17,4587,1,AF_INET\r\n")-1);
	u32Poi += sizeof("AT+NSOCR=DGRAM,17,4587,1,AF_INET\r\n") - 1;
	
	BC28_Tx((T_U8 *)g_s8AtCache, u32Poi);
}
#if 0
/********************************************
 *功能:查询套接字连接状态
 *输入:s8Fd: 套接字编号
        s8Type:协议类型 'U':UDP 'T':TCP
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_QuerySocket(T_S8 s8Fd, T_S8 s8Type)
{
	
}
#endif
/********************************************
 *功能:连接套接字
 *输入:s8Fd: 套接字编号
        s8Type:协议类型 'U':UDP 'T':TCP
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_DeleteSocket(T_S8 s8Fd, T_S8 s8Type)
{
	T_U32 u32Poi = 0;
	
	memset(g_s8AtCache, 0, sizeof(g_s8AtCache));
	u32Poi = 0;
	memcpy(&g_s8AtCache[u32Poi], "AT+NSOCL=1\r\n", sizeof("AT+NSOCL=1\r\n")-1);
	u32Poi += sizeof("AT+NSOCL=1\r\n") - 1;
	g_s8AtCache[9] = s8Fd;
	
	BC28_Tx((T_U8 *)g_s8AtCache, u32Poi);
}

/********************************************
 *功能:连接服务器
 *输入:s8Fd:套接字 
        ps8Ip: IP
        ps8Port:端口
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_ConnectServer(T_S8 s8Fd, T_S8 *ps8Ip, T_S8 *ps8Port)
{
	
}

/********************************************
 *功能:启动接收数据
 *输入:s8Fd: 套接字编号
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_StartRevData(T_S8 s8Fd)
{
	T_U32 u32Poi = 0;
	
	memset(g_s8AtCache, 0, sizeof(g_s8AtCache));
	u32Poi = 0;
	memcpy(&g_s8AtCache[u32Poi], "AT+NSORF=1,1024\r\n", sizeof("AT+NSORF=1,1024\r\n")-1);
	u32Poi += sizeof("AT+NSORF=1,1024\r\n") - 1;
	g_s8AtCache[9] = s8Fd;
	
	BC28_Tx((T_U8 *)g_s8AtCache, u32Poi);
}
/********************************************
 *功能:组合服务器数据接收头
 *输入:s8Fd:套接字 
        ps8Ip: IP
        ps8Port:端口
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_GetServerDataHead(T_S8 s8Fd, T_S8 *ps8Ip, T_S8 *ps8Port)
{
	T_U32 u32Poi = 0;
	
	memset(g_s8SeverDataHead, 0, sizeof(g_s8SeverDataHead));
	g_s8SeverDataHead[u32Poi++] = s8Fd;
	g_s8SeverDataHead[u32Poi++] = ',';
	memcpy(&g_s8SeverDataHead[u32Poi], ps8Ip, strlen(ps8Ip));
	u32Poi += strlen(ps8Ip);
	g_s8SeverDataHead[u32Poi++] = ',';
	memcpy(&g_s8SeverDataHead[u32Poi], ps8Port, strlen(ps8Port));
	u32Poi += strlen(ps8Port);
	g_s8SeverDataHead[u32Poi++] = ',';
}

/********************************************
 *功能:任务处理
 *输入:pvData:参数
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_TaskHandler(T_VOID *pvData)
{	
	T_U32 u32Delay = 0; //重复执行延时 单位 MS
	static T_U32 u32StepAtCnt = 0;
	
	switch(g_stThisCtl.u32Step)
	{
		//初始化第一步
		case E_BC28_STEP_INIT:
		{
			BC28_RST_DI();
			g_stThisCtl.u32Step = E_BC28_STEP_SETUP;
			u32Delay = 3000;
			u32StepAtCnt = 0;
		}
		break;
		//基础设置
		case E_BC28_STEP_SETUP:
		{
			u32StepAtCnt++;
			
			if(1 == u32StepAtCnt)
			{
				BC28_Tx(AT_QREGSWT, sizeof(AT_QREGSWT)-1);
				u32Delay = 1000;
			}else if(2 == u32StepAtCnt)
			{
				BC28_Tx("AT+NCONFIG=PCO_IE_TYPE,PCO\r\n", sizeof("AT+NCONFIG=PCO_IE_TYPE,PCO\r\n")-1);
				u32Delay = 1000;
			}else if(3 == u32StepAtCnt)
			{
				BC28_Tx("AT+NCONFIG?\r\n", sizeof("AT+NCONFIG?\r\n")-1);
				u32Delay = 1000;
			}else if(4 == u32StepAtCnt)
			{
				BC28_Tx(AT_NRB, sizeof(AT_NRB)-1);
				u32Delay = 5000;
				g_stThisCtl.u32Step = E_BC28_STEP_GET_INFO;
				u32StepAtCnt = 0;
			}
		}
		break;
		//获取基本信息
		case E_BC28_STEP_GET_INFO:
		{
			u32StepAtCnt++;
			if(1 == u32StepAtCnt)
			{
				BC28_Tx(ATI, sizeof(ATI)-1);
				u32Delay = 100;
			}else if(2 == u32StepAtCnt)
			{
				BC28_Tx(AT_NPSMR, sizeof(AT_NPSMR)-1);
				u32Delay = 100;
			}else if(3 == u32StepAtCnt)
			{
				BC28_Tx(AT_CGSN, sizeof(AT_CGSN)-1);
				u32Delay = 100;
			}else if(4 == u32StepAtCnt)
			{
				BC28_Tx(AT_ICCID, sizeof(AT_ICCID)-1);
				u32Delay = 100;
			}else if(5 == u32StepAtCnt)
			{
				BC28_Tx(AT_CIMI, sizeof(AT_CIMI)-1);
				u32Delay = 100;
			}else if(6 == u32StepAtCnt)
			{
				BC28_Tx(AT_CPSMS, sizeof(AT_CPSMS)-1);
				u32Delay = 100;
			}else if(7 == u32StepAtCnt)
			{
				BC28_Tx(AT_PSM_GET, sizeof(AT_PSM_GET)-1);
				u32Delay = 100;
			}else if(8 == u32StepAtCnt)
			{
				BC28_Tx(AT_COPS, sizeof(AT_COPS)-1);
				u32Delay = 100;
			}else if(9 == u32StepAtCnt)
			{
				BC28_Tx("AT+COPS?\r\n", sizeof("AT+COPS?\r\n")-1);
				u32Delay = 100;
				g_stThisCtl.u32Step = E_BC28_STEP_CGATT;
				u32StepAtCnt = 0;
			}
		}
		break;
		//查询网络附着
		case E_BC28_STEP_CGATT:
		{
			if(E_NET_STATUS_GATE_CONNECTED != g_stThisCtl.u32Status)
			{
				g_stThisCtl.u32Status = E_NET_STATUS_GATE_CONNECTING; //连接网关中
				BC28_Tx(AT_CGATT, sizeof(AT_CGATT)-1);
				g_stThisCtl.u32Step = E_BC28_STEP_CGATT;
				u32Delay = 1000;
			}else
			{
				g_stThisCtl.u32Step = E_BC28_STEP_GET_NET_INFO;
				u32Delay = 100;
				u32StepAtCnt = 0;
			}
		}
		break;
		//查询APN
		case E_BC28_STEP_GET_NET_INFO:
		{
			u32StepAtCnt++;
			if(1 == u32StepAtCnt)
			{
				BC28_Tx(AT_CGDCONT, sizeof(AT_CGDCONT)-1);
				u32Delay = 100;
			}else if(2 == u32StepAtCnt)
			{
				BC28_Tx(AT_CSQ, sizeof(AT_CSQ)-1);
				u32Delay = 100;
				u32StepAtCnt = 0;
				g_stThisCtl.u32Step = E_BC28_STEP_DNS;
			}
		}
		break;
		//查询DNS
		case E_BC28_STEP_DNS:
		{
			if('\0' != g_stServerInfo.s8Domain1[0])
			{
				BC28_DNS(g_stServerInfo.s8Domain1);
			}
			g_stThisCtl.u32Step = E_BC28_STEP_DNS_STATUS;
			u32Delay = 3000;
		}
		break;
		//查询解析域名状态
		case E_BC28_STEP_DNS_STATUS:
		{
			g_stThisCtl.u32Step = E_BC28_STEP_FD;
			u32Delay = 1000;
			if('\0' != g_stServerInfo.s8Domain1[0]
				&&'\0' == g_stSocketInfo.s8IP1[0])
			{
				//解析域名失败重新复位模块
				BC28_Rst(); 
			}
		}
		break;
		//创建套接字
		case E_BC28_STEP_FD:
		{
			g_stThisCtl.u32Step = E_BC28_STEP_FD_STATUS;
			u32Delay = 1000;
			
			if('\0' != g_stSocketInfo.s8IP1[0])
			{	
				BC28_CreateSocket('1', SOCKET_TYPE);
			}
		}
		break;
		//查询套接字状态
		case E_BC28_STEP_FD_STATUS:
		{
			g_stThisCtl.u32Step = E_BC28_STEP_CONNECT;
			u32Delay = 100;
			
			if('\0' == g_stSocketInfo.s8Fd1)
			{
				//创建套接字失败重新复位模块
				BC28_Rst(); 
			}
		}
		break;
		//连接服务器
		case E_BC28_STEP_CONNECT:
		{
			g_stThisCtl.u32Step = E_BC28_STEP_CONNECT_STATUS;
			u32Delay = 100;
			
			if('\0' != g_stSocketInfo.s8IP1[0]
				&& '\0' != g_stSocketInfo.s8Fd1)
			{
				BC28_ConnectServer(g_stSocketInfo.s8Fd1, g_stSocketInfo.s8IP1, g_stServerInfo.s8Port1);
			}
		}
		break;
		//获取连接状态
		case E_BC28_STEP_CONNECT_STATUS:
		{
			static T_U32 u32Flg = 0;
			if('\0' != g_stSocketInfo.s8Fd1)
			{
				g_stThisCtl.u32Status = E_NET_STATUS_SERVER_CONNECTED; //连接上服务器
				if(0 == u32Flg)
				{
					_Pop(E_NET_READ_TYPE_CONNECT, T_NULL, 0);
					u32Flg = 1;
				}
			}	
		}
		break;
		//结束
		case E_BC28_STEP_END:
		{
		}
		break;
		
	}
	
	if(u32Delay)
	{
		MDL_DRVTIMER_Add(BC28_TaskHandler, T_NULL, u32Delay, 0);
	}
}
/********************************************
 *功能:设置任务步骤
 *输入:无
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_SetTaskStep(T_U32 u32Step)
{
	g_stThisCtl.u32Step = u32Step;
	MDL_DRVTIMER_Add(BC28_TaskHandler, T_NULL, 100, 0);
}
/********************************************
 *功能:复位
 *输入:无
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_Rst(T_VOID)
{	
	BC28_RST_EN();
	
	BC28_SetTaskStep(E_BC28_STEP_INIT);
	g_stThisCtl.u32Status = E_NET_STATUS_INIT;
	
	memset(&g_stSocketInfo, 0, sizeof(g_stSocketInfo));
}

/********************************************
 *功能:接收一条数据处理
 *输入:ps8Data:数据
        u32Len:数据长度
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_RxOnePiece(T_S8 *ps8Data, T_U32 u32Len)
{
	T_S8 s8Status;
	
	if(0 == strncmp(ps8Data, "OK", sizeof("OK")-1))
	{
		
	}
	
	if(0 == strncmp(ps8Data, "ERROR", sizeof("ERROR")-1))
	{
		static T_U32 g_u32ErrCnt = 0;
		
		g_u32ErrCnt++; //记录错误次数
		
		if(g_u32ErrCnt > 10)
		{
			g_u32ErrCnt = 0;
			
		}
	}
	//解析IMEI
	if(0 == strncmp(ps8Data, "+CGSN:", sizeof("+CGSN:")-1))
	{
		GetDoubleMarkData(g_stNBInfo.s8IMEI, ps8Data, "+CGSN:");
	}
	//解析IMSI
	if(0 == strncmp(ps8Data, "46", sizeof("46")-1))
	{
		memcpy(g_stNBInfo.s8IMSI, ps8Data, 15);
	}
	//解析ICCID
	if(0 == strncmp(ps8Data, "+NCCID:", sizeof("+NCCID:")-1))
	{
		memcpy(g_stNBInfo.s8ICCID, ps8Data+sizeof("+NCCID:")-1, 20);
	}
	//网络附着
	if(0 == strncmp(ps8Data, "+CGATT:", sizeof("+CGATT:")-1))
	{
		s8Status = *(ps8Data + sizeof("+CGATT:")-1);
		if('1' == s8Status)
		{
			g_stThisCtl.u32Status = E_NET_STATUS_GATE_CONNECTED;
		}
	}
	//解析CSQ
	if(0 == strncmp(ps8Data, "+CSQ:", sizeof("+CSQ:")-1))
	{
		memcpy(g_stNBInfo.s8CSQ, ps8Data+sizeof("+CSQ:")-1, 2);
	}
	//解析IP
	if(0 == strncmp(ps8Data, "+QDNS:", sizeof("+QDNS:")-1))
	{			
		if(E_BC28_STEP_DNS_STATUS == g_stThisCtl.u32Step
			&& 0 != strncmp(ps8Data, "+QDNS:FAIL", sizeof("+QDNS:FAIL")-1))
		{
			T_S8 *ps8P1,*ps8P2;
			ps8P1 = ps8Data + sizeof("+QDNS:")-1;
			ps8P2 = strchr(ps8P1, '\r');
			memcpy(g_stSocketInfo.s8IP1, ps8P1, (ps8P2-ps8P1));
			//GetDoubleMarkData(g_stSocketInfo.s8IP1, ps8Data, "+QDNS:");
		}
	}
	//模块休眠状态
	if(0 == strncmp(ps8Data, "+NPSMR:", sizeof("+NPSMR:")-1))
	{	
		s8Status = *(ps8Data + sizeof("+NPSMR:")-1);		
		if('0' == s8Status)
		{
			g_stThisCtl.u32BC28SleepFlg = 0;
		}else if('1' == s8Status)
		{
			g_stThisCtl.u32BC28SleepFlg = 1;
		}
	}
	//解析Sokcet返回句柄
	if(0 == strncmp(ps8Data, "0\r\n", sizeof("0\r\n")-1)
		|| 0 == strncmp(ps8Data, "1\r\n", sizeof("1\r\n")-1)
		|| 0 == strncmp(ps8Data, "2\r\n", sizeof("2\r\n")-1)
		|| 0 == strncmp(ps8Data, "3\r\n", sizeof("3\r\n")-1))
	{
		if(E_BC28_STEP_FD_STATUS == g_stThisCtl.u32Step)
		{
			s8Status = *(ps8Data);
			g_stSocketInfo.s8Fd1 = s8Status;
			BC28_GetServerDataHead(g_stSocketInfo.s8Fd1, g_stSocketInfo.s8IP1, g_stServerInfo.s8Port1);
		}
	}
	//数据通知
	if(0 == strncmp(ps8Data, "+NSONMI:", sizeof("+NSONMI:")-1))
	{
		s8Status = *(ps8Data + sizeof("+NSONMI:")-1);
		BC28_StartRevData(s8Status);
	}
	//解析数据
	if(0 == strncmp(ps8Data, g_s8SeverDataHead, strlen(g_s8SeverDataHead)))
	{	
		T_S8 *ps8HexStringHead = GetNCharPos(ps8Data, 4, ',');//+strlen(g_s8SeverDataHead)+1;
		T_S8 *ps8HexStringEnd = strchr(ps8HexStringHead, ',');
		T_U32 u32HexStringLen = (ps8HexStringEnd - ps8HexStringHead); //字符串长度
		
		if(T_NULL != ps8HexStringHead
			&& T_NULL != ps8HexStringEnd)
		{
			GetHexStringBuf(ps8HexStringHead, u32HexStringLen, g_u8ServerData, sizeof(g_u8ServerData), 0);
			_Pop(E_NET_READ_TYPE_DATA, g_u8ServerData, u32HexStringLen/2);
		}
	}
	
}

/********************************************
 *功能:串口接收处理
 *输入:ps8Data:数据
        u32Len:数据长度
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID BC28_RxHandler(T_S8 *ps8Data, T_U32 u32Len)
{
	T_S8 *ps8Head = ps8Data; //字符串位置
	T_S8 *ps8NextPoi = T_NULL;
	
	while(1)
	{
		BC28_RxOnePiece(ps8Head, u32Len - (ps8Head - ps8Data)); //这里先解析数据 因为有些数据不是"\r\n"结尾
		
		ps8NextPoi = strstr(ps8Head, "\r\n");
		
		if(ps8NextPoi == T_NULL
			|| ps8NextPoi > (ps8Data +u32Len))
		{
			break;
		}
		
		ps8Head = ps8NextPoi + 2;
	}
	
}


/********************************************
 *功能:提取域名跟端口
 *输入:ps8Data:服务器信息数据 格式:Domain:"xxx",Port:"xxx"
        ps8OutDomain:输出的Domain
        ps8Port:输出的端口
 *输出:无
 *条件:无
 *返回:无
 注意: 
*********************************************/
static T_VOID BC28_SetDomainPort(T_S8 *ps8Data, T_S8 *ps8OutDomain, T_S8 *ps8OutPort)
{	
	GetDoubleMarkData(ps8OutDomain, ps8Data, "Domain");
	GetDoubleMarkData(ps8OutPort, ps8Data, "Port");
}

/********************************************
驱动模板函数区
*********************************************/

/********************************************
 *功能:引脚初始化函数
 *输入:无
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID _GpioInit(T_VOID)
{	
	BC28_UARTConfInput();
	
	GPIO_ConfigurePin(BC28_RST_PORT, BC28_RST_PIN, OUTPUT, PID_GPIO, false);
}

/********************************************
 *功能:芯片初始化函数
 *输入:无
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID _ChipInit(T_VOID)
{	
	memset(&g_stNBInfo, 0, sizeof(g_stNBInfo));
	memset(&g_stServerInfo, 0, sizeof(g_stServerInfo));
	memset(&g_stSocketInfo, 0, sizeof(g_stSocketInfo));
	memcpy(g_s8SeverDataHead, "1,119.23.36.50,10001,", sizeof("1,119.23.36.50,10001,"));
	g_stThisCtl.u32BC28SleepFlg = 1;
}

/********************************************
 *功能:休眠处理函数
 *输入:无
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID _PowerSaving(T_VOID)
{	
	if(E_NET_STATUS_SERVER_CONNECTED == g_stThisCtl.u32Status)
	{
#if 1		
		//如果连接上网络,则不断电,删除socket,发数据时再重新连接socket
		if('\0' != g_stSocketInfo.s8Fd1)
		{	
			BC28_DeleteSocket(g_stSocketInfo.s8Fd1, SOCKET_TYPE);
			g_stSocketInfo.s8Fd1 = '\0';
			MDL_TIME_Delay(50);
		}
		g_stThisCtl.u32Status = E_NET_STATUS_SERVER_DISCONNECT;
#endif		
		/*
		如果没断电源,把串口设置成输入
		*/
		BC28_UARTConfInput();
		print_msg("g_stThisCtl.u32Status=E_NET_STATUS_SERVER_CONNECTED\r\n");
	}else
	{
		if(g_stThisCtl.u32Status != E_NET_STATUS_POWER_OFF)
		{
			BC28_Tx(AT_COPS_CLOSE, sizeof(AT_COPS_CLOSE)-1); //关闭入网
			T_U32 u32Delay = 100000;
			while(u32Delay--);
			
			BC28_SetTaskStep(E_BC28_STEP_END);
		}
		g_stSocketInfo.s8Fd1 = '\0';
		g_stSocketInfo.s8Fd2 = '\0';
		
		g_stThisCtl.u32Status = E_NET_STATUS_SERVER_DISCONNECT;
#if 0		
		g_stThisCtl.u32Status = E_NET_STATUS_POWER_OFF; //设备发数据不重新连接网络
#endif		
		/*
		如果未连接上网络,则断电, 
		断电之前需要把串口设置成输入,
		避免断模块电源的时候导致串口IO
		串大电流到模块导致芯片异常
		*/
		BC28_UARTConfInput();
		
		print_msg("g_stThisCtl.u32Status=E_NET_STATUS_POWER_OFF\r\n");
	}
	
	g_stThisCtl.u32BC28SleepFlg = 1;
	
#if 0	
	//测试
	CFB801_UARTConfInput();
	CFB801_WAKE_H();
#endif		
}

/********************************************
 *功能:唤醒处理函数
 *输入:无
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID _WakeUp(T_VOID)
{	
	_GpioInit();
}

/********************************************
 *功能:初始化函数
 *输入:无
 *输出:无
 *条件:无
 *返回:无
 注意:
*********************************************/
static T_VOID _Init(T_VOID)
{
	//数据初始化
	memset(&g_stThisCtl, 0, sizeof(g_stThisCtl));
	//IO初始化
	_GpioInit();
	//芯片初始化
	_ChipInit();
}

/********************************************
 *功能:应用层消息填充函数
 *输入:根据具体数据
 *输出:无
 *条件:无
 *返回:成功:RET_SUCCESS 
 		失败:RET_FAILED 
 注意:
*********************************************/
static T_VOID _Pop(
	T_U8 u8Type,
	T_U8 *pu8Data,
	T_U32 u32Len)
{
	S_DriverReadNet *pstDriverReadClass = (S_DriverReadNet *)g_u8ReadDataCache;
	
	pstDriverReadClass->u8Type |= u8Type;
	if(E_NET_READ_TYPE_DATA == u8Type)
	{
		pstDriverReadClass->pu8Data = pu8Data;
		pstDriverReadClass->u32Len = u32Len;
	}
	
	g_DriverDatas.u32ReadLen = sizeof(S_DriverReadNet);
	g_DriverDatas.u8PopFlag = 1;
}

/********************************************
 *功能:打开函数
 *输入:无
 *输出:无
 *条件:无
 *返回:成功:RET_SUCCESS 
 		失败:RET_FAILED 
 注意:
*********************************************/
static T_S32 _Open(T_VOID)
{
	//数据初始化
	memset(&g_DriverDatas, 0, sizeof(g_DriverDatas));
	memset(&g_u8ReadDataCache, 0, sizeof(g_u8ReadDataCache));
	g_DriverDatas.pu8ReadData = g_u8ReadDataCache;
	//驱动初始化
	_Init();
	
	return RET_SUCCESS;
}

/********************************************
 *功能:控制接口
 *输入:s32Cmd :命令类型
 		pvData:控制数据或返回数据
 *输出:无
 *条件:无
 *返回:成功:RET_SUCCESS 
 		失败:RET_FAILED 
*********************************************/
static T_S32 _Ioctl(T_S32 s32Cmd, T_VOID *pvData)
{
	switch(s32Cmd)
	{
		//进入低功耗
		case E_IOCTL_CMD_POWER_SAVING:
		{		
			_PowerSaving();
		}
		break;
		//唤醒处理
		case E_IOCTL_CMD_WAKE_UP:
		{
			_WakeUp();
		}
		break;
		//复位模块
		case E_IOCTL_CMD_RST:
		{		
			BC28_Rst();
		}
		break;
		//重建socket
		case E_NET_IOCTL_CMD_REBUID_SOCKET:
		{
			//BC28_SetTaskStep(E_BC28_STEP_FD);
			BC28_Rst();
		}
		break;
		//获取网络状态
		case E_NET_IOCTL_CMD_GET_STATUS:
		{
			T_U32 *pu32Status = (T_U32 *)pvData;
			
			*pu32Status = g_stThisCtl.u32Status;
		}
		break;
		//获取信号强度
		case E_NET_IOCTL_CMD_GET_CSQ:
		{
			S_NetCSQ *pstCsq = (S_NetCSQ *)pvData;
			memcpy(pstCsq->csq, g_stNBInfo.s8CSQ, sizeof(pstCsq->csq));
		}
		break;
		//设置域名
		case E_NET_IOCTL_CMD_SET_DOMAIN:
		{
			BC28_SetDomainPort((T_S8 *)pvData, g_stServerInfo.s8Domain1, g_stServerInfo.s8Port1);
		}
		break;
		//设置域名2
		case E_NET_IOCTL_CMD_SET_DOMAIN2:
		{
			BC28_SetDomainPort((T_S8 *)pvData, g_stServerInfo.s8Domain2, g_stServerInfo.s8Port2);
		}
		break;
		//获取信息
		case E_NET_IOCTL_CMD_GET_INFO:
		{
			memcpy(pvData, &g_stNBInfo, sizeof(g_stNBInfo));
		}
		break;
		//IO 口锁定
		case E_IOCTL_CMD_IO_LOCK:
		{
			GPIO_ConfigurePin(BC28_RST_PORT, BC28_RST_PIN, OUTPUT, PID_GPIO, false);
			GPIO_ConfigurePin(BC28_TX_PORT, BC28_TX_PIN, INPUT, PID_GPIO, false);
			GPIO_ConfigurePin(BC28_RX_PORT, BC28_RX_PIN, INPUT, PID_GPIO, false);	
		}
		break;
	}
	
	return RET_SUCCESS;
}

/********************************************
 *功能:写入函数
 *输入:ps8DataBuf: 写的数据
        s32BufLen: 写的数据长度
 *输出:无
 *条件:无
 *返回:成功:RET_SUCCESS 
 		失败:RET_FAILED 
 		或者长度
 注意:
*********************************************/
static T_S32 _Write(T_S8 *ps8DataBuf, T_S32 s32BufLen)
{	
	BC28_SendToSever((T_U8 *)ps8DataBuf, s32BufLen);
	
	return RET_SUCCESS;
}

//驱动操作函数
static const S_DriverOperations g_stDriverOperations = {
	.open = _Open,
	.ioctl = _Ioctl,
	.write = _Write,
};

//驱动操作
static const S_DriverModule g_stDriverModule = {
	.pstOperations = (S_DriverOperations *)&g_stDriverOperations,
	.pstData = &g_DriverDatas,
};

/********************************************
 *功能:返回驱动操作指针
 *输入:无
 *输出:无
 *条件:无
 *返回:当前驱动操作指针
 注意:
*********************************************/
S_DriverModule *BC28_DriverModuleReturn(T_VOID)
{
	return (S_DriverModule *)&g_stDriverModule;
}

 

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值