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;
}