NB模块连接网络顺序
移柯NBL260模块
NB卡: 联通 默认波特率 115200
//UDP 链接方式:
AT //判断模组是否上电开机成功
AT+CIMI //读取 IMSI, 判断 SIM 卡初始化是否成功
AT+CESQ 检查信号质量
AT+CEREG? //判断 PS 域附着(是否注册网络)状态,标识位返回 1 或 5 表示附着正常
AT+CIPMUX=0 //切换到单个链接
AT+CIPSTART="UDP","101.95.153.110",60110 // 配置服务器及上产方式
AT+QLWOPEN=0 // 连接网络
AT+CIPSEND =5 //固定发送数据长度位5(长度大小可自由设定)
12345 //直接上传数据
AT+CIPRXGET=1,100 // get data
移远NB BC26模块
链接移远平台(COAP协议)
NB卡: 联通 默认波特率 115200
手动检查:
AT //同步波特率直到回复OK
AT+CIMI //读取 IMSI, 判断 SIM 卡初始化是否成功
AT+CESQ //检查信号质量 推荐15 -31
AT+CFUN? //是否返回1 检查 UE的功能等级 1代表全部功能
AT+CEREG? 返回0,1表示入网成功,0,0 0,2正在找网 300S
AT+CGPADDR=1 检查IP
AT+CGSN=1 // 获取IMEI号码 在绑定平台的时候需要发送IMEI号
自动检查部分:
URC:
+CPIN: READY
+IP:XXXXXXX
//网络,格式配置
AT+NCDP=southbound.quectel.com,5683 //设置服务器端口和 地址
AT+QLWCONF="IMEI" 例如: AT+QLWCONF="866971033147948"
AT+QLWADDOBJ=19,1,1,"0" //配置:LWM2M
AT+QLWADDOBJ=19,0,1, "0" //配置1:LWM2M
AT+QLWOPEN=0 //Register to the IoT platform in direct push mode
AT+QLWCFG="dataformat",1,1 //Configure hex string mode for sending and received data.
AT+QLWDATASEND=19,0,0,2,3132,0x0100 . //send data 1和2 datalength 2 CON数据
AT+SM=LOCK指令来阻止模块进入PSM //调试的时候可以使用到
说明: 模块上电启动会自动连接网络,若模块返回+CPIN: READY 说明模块本身的基本配置已经完成,返回+IP:XXXXXXX,表示模块已经自动联网。若自动联网即可直接进入网络配置一块,后即可发送数据。具体案例最下图所示。
移远NB 广州联通平台
https://device1-portal.10646.cn
user = "dyson.zhang@whoareyou.live";
password = "way123!@#";
coAP接入方式LwM2M链接
AT
AT+CESQ
AT+CFUN?
AT+CEREG?
AT+CGPADDR=1
AT+QLWSERV="device1-api.10646.cn",5683 等价 AT+NCDP=device1-api.10646.cn,5683
AT+QLWCONF="866971033147948"
AT+QLWADDOBJ=19,1,1,"0"
AT+QLWADDOBJ=19,0,1,"0"
AT+QLWOPEN=0
AT+QLWCFG="dataformat",1,1
AT+QLWDATASEND=19,0,0,2,3132,0x0100 // con数据
注意事项:模块开机后会自动调整工作模式,不需额外干预,若一段时间不操作,模块会自进入PSM模式。如想再次操作,需从PSM唤醒。
AT指令发送时需要回车键
include "App_Main.h"
#include "NBIot_BC26.h"
#include "Drv_Usart.h"
#include "fifo.h"
static void StartingUp(void);
extern char gaucUsart1Buff[RXBUFSIZE];
char *gcBC26CmdBuff=0 ; // 存放BN26模块返回的状态指令
void NB_BC26_init(void)
{
// NB Vcc
GPIO_SetMode(NB_VCCPort, NB_VCCPin, GPIO_MODE_OUTPUT);
GPIO_SetMode(PWRKEY_Port, PWRKEY_Pin, GPIO_MODE_OUTPUT);
GPIO_SetMode(PSM_EINT_port, PSM_EINT_pin, GPIO_MODE_OUTPUT);
GPIO_SetMode(Reset_Port, Reset_Pin, GPIO_MODE_OUTPUT);
NB_VCCEN;
Reset_Disable;
// Reset_BC26();
Drv_SysDelayMs(50);
StartingUp();
// PSM_wake();
}
// 从psm 唤醒
static void PSM_wake(void)
{
PSM_EINT_Disable;
Drv_SysDelayMs(10);
PSM_EINT_EN;
Drv_SysDelayMs(5);
PSM_EINT_Disable;
}
//上电启动
static void StartingUp(void)
{
PWRKEY_Disable;
Drv_SysDelayMs(10);
PWRKEY_EN;
Drv_SysDelayMs(800);
PWRKEY_Disable;
}
//断电关机
void Shutdown(void)
{
NB_VCCDisable;
}
// reset
void Reset_BC26(void)
{
Reset_Disable;
Drv_SysDelayMs(10);
Reset_EN;
Drv_SysDelayMs(100);
Reset_Disable;
}
/*发送 AT 指令给NBiot
返回: 1 代表成功 0 代表失败
*/
uint8_t Send_AT_CMD(UART_T* uart,uint8_t *cmdBuffer)
{
uint8_t utReturn = 0;
while(*cmdBuffer != '\0')
{
utReturn = UART_Write(uart,cmdBuffer++,1);
}
return utReturn;
}
/* function : 判断返回数据
@param :
*String: 接受到的与之对比的命令
*InBuffer: 输入的数据缓存(IN)
* OutBuffer : 在InBuffer 中截取的String及以后的数据
ucLen 对比之后首次出现是首地址
*/
extern volatile uint32_t gudComRFlag;
extern uint8_t guRX_num;
char *RX_BC26_CMD(char *InBuffer,char *String)
{
char *INdex=0;
INdex = strstr(InBuffer,String);
return INdex;
}
/* function : 发送指令
@param :uart 串口号
cmd 发送命令
*String: 接受到的与之对比的预知命令
waittime : 超时时间
Index_location 对比之后首次出现是首地址
return : sucess or fail
*/
uint8_t BC26_send_cmd(UART_T* uart,uint8_t *cmd,char *String,char **Index_location,uint16_t waittime)
{
uint8_t res = TA_FAIL;
guRX_num =0;
memset(gaucUsart1Buff,0,sizeof(gaucUsart1Buff));
Send_AT_CMD(uart,cmd); //发送出去命令
Drv_SysDelayMs(300);
while(waittime--)
{
Drv_SysDelayMs(20);//串口在一个字节一个字节的接收,这块每接收一个字节就检测接收到的整个数据是否符合要求
if(gudComRFlag) //收到数据,检查数据是否是想要的
{
*Index_location = RX_BC26_CMD(gaucUsart1Buff,String);
if( RX_BC26_CMD(gaucUsart1Buff,String))
{
res = TA_SUCCESS;
break; //是想要的,发送结束,跳出
}
gudComRFlag=0;
}
}
return res;
}
/*
function: BC26模块上电自检
return : sucess or fail
*/
//uint8_t Power_ONCheckself(void)
//{
// uint32_t Time_out = 0;
// //NB_BC26_init();
// while(RX_BC26_CMD(gaucUsart1Buff,"Leaving"))
// {
// memset(gaucUsart1Buff,0,sizeof(gaucUsart1Buff));
// return TA_SUCCESS;
// }
// else
// {
// Shutdown();
// Drv_SysDelayMs(10);
// NB_BC26_init();
// if(TA_SUCCESS == RX_BC26_CMD(gaucUsart1Buff,"Leaving"))
// {
// memset(gaucUsart1Buff,0,sizeof(gaucUsart1Buff));
// return TA_SUCCESS;
// }
// else
// {
// return TA_FAIL;
// }
// }
//
//}
//将普通字符串转化成Hex字符串
uint8_t str2hex(char* str, char* hex)
{
const char* cHex = "0123456789ABCDEF";
int i=0,j=0;
for( j =0; j < strlen(str); j++)
{
unsigned int a = (unsigned int) str[j];
hex[i++] = cHex[(a & 0xf0) >> 4];
hex[i++] = cHex[(a & 0x0f)];
}
hex[i] ='\0';
return i;
}
//NBiot模块上网流程
uint8_t BC26_DataProcess(uint8_t *NB_buffer,uint8_t NB_Length)
{
uint32_t time_out = 5;
uint8_t Signal_Strength = 0;
uint8_t Statue = NB_Start;
uint16_t Hex_Data_Length = 0;
uint8_t New_Satrt_count = 3 ; //启动的次数
uint8_t Hex_buffer[100]={0}; // 存储转化为hex的数据
char *Data_Location =0;
char *AT_cmd1= 0; // 存储 AD—cmd
char *AT_cmd2= 0;
// if(TA_SUCCESS != Power_ONCheckself())// 自检失败,直接退出
// {
// return TA_FAIL;
// }
while(1)
{
if(0 == New_Satrt_count)
return TA_FAIL;
switch(Statue)
{
case NB_Start:
time_out = 40;
// NB_VCCDisable;
Drv_SysDelayMs(1000);
NB_BC26_init();
while(time_out--)
{
if( RX_BC26_CMD(gaucUsart1Buff,"Leaving"))
break;
Drv_SysDelayMs(10);
}
Statue = AT;
break;
case AT: //同步波特率
time_out=4;
while(time_out--)
{
if(TA_SUCCESS == BC26_send_cmd(UART1,"AT\r\n","OK",&Data_Location,100)) // 超时时间2S
{
break;
}
if( RX_BC26_CMD(gaucUsart1Buff,"+CPIN: READY"))
break;
if(time_out<2) // 若失败两次,则重启模块
{
Statue = NB_Start;
New_Satrt_count--;
break;
}
}
if(RX_BC26_CMD(gaucUsart1Buff,"+IP:"))
{
Statue = AT_NCDP;
break;
}
else
{
Statue = AT_CESQ;
break;
}
case AT_CESQ: // 检查信号强度
time_out =50;
while(time_out--)
{
if( RX_BC26_CMD(gaucUsart1Buff,"+CPIN: READY"))
{
break;
}
Drv_SysDelayMs(100);
}
time_out = 3;
while(time_out--)
{
if(RX_BC26_CMD(gaucUsart1Buff,"+IP:"))
{
Statue = AT_NCDP;
break;
}
if(TA_SUCCESS == BC26_send_cmd(UART1,"AT+CESQ\r\n","+CESQ: ",&Data_Location,100)) // 超时时间2S
{
Signal_Strength = 10*(*(Data_Location+7) - 48) + (*(Data_Location+8) - 48);
if(((*(Data_Location+7) - 48) == 0) || ((*(Data_Location+7) - 48) == 9))
{
New_Satrt_count--;
Statue = NB_Start;
break;
}
else
{
Statue = AT_CFUN;
break;
}
}
if(time_out<2)
{
Statue = NB_Start;
New_Satrt_count--;
break;
}
}
break;
case AT_CFUN: // 检查UE功能等级 最长15S
time_out = 2;
while(time_out--)
{
if(RX_BC26_CMD(gaucUsart1Buff,"+IP:"))
{
Statue = AT_NCDP;
break;
}
if(TA_SUCCESS == BC26_send_cmd(UART1,"AT+CFUN?\r\n","+CFUN: ",&Data_Location,750)) // 超时时间15S
{
Signal_Strength = (*(Data_Location+7) - 48);
if((Signal_Strength != 1))
{
continue;
}
else
{
Statue = AT_CEREG;
break;
}
}
else
{
PSM_wake();
}
if(time_out<1)
{
Statue = NB_Start;
New_Satrt_count--;
break;;
}
}
break;
case AT_CEREG: // 检查是否入网成功
time_out = 3;
while(time_out--)
{
if(RX_BC26_CMD(gaucUsart1Buff,"+IP: "))
{
Statue = AT_NCDP;
break;
}
if(TA_SUCCESS == BC26_send_cmd(UART1,"AT+CEREG?\r\n","+CEREG: ",&Data_Location,400)) // 超时时间2S
{
if(*(Data_Location+10) == '1')// join in internet sucess
{
Statue = AT_CGPADDR;
break;
}
else if((*(Data_Location+10) == '2') || (*(Data_Location+10) == '0') ) //looking for internet
{
Drv_SysDelayMs(500);
}
}
if(time_out<2)
{
Statue = NB_Start;
New_Satrt_count--;
break;
}
}
break;
case AT_CGPADDR: // Get IP adress
time_out = 3;
while(time_out--)
{
if(TA_SUCCESS == BC26_send_cmd(UART1,"AT+CGPADDR=1\r\n","+CGPADDR: 1",&Data_Location,100)) // 超时时间2S
{
Statue = AT_NCDP;
break;
}
if(time_out<2)
{
Statue = NB_Start;
New_Satrt_count--;
break;
}
}
break;
// case AT_CGSN: // get IMEI
case AT_NCDP: // configure network adress
// Drv_SysDelayMs(7000);
time_out = 2;
while(time_out--)
{
if (TA_SUCCESS == BC26_send_cmd(UART1,"AT+NCDP=southbound.quectel.com,5683\r\n","OK",&Data_Location,100)) // 超时时间2S
{
Statue = AT_QLWCONF;
break;
}
else
{
if(time_out<1)
{
Statue = NB_Start;
New_Satrt_count--;
break;
}
}
}
break;
case AT_QLWCONF: // 配置设备的IMEI
time_out = 2;
AT_cmd1 = "AT+QLWCONF=";
AT_cmd2 = "866971033234043";
memset(Hex_buffer,0,sizeof(Hex_buffer));
Hex_Data_Length = Cmd_connect(AT_cmd1,AT_cmd2,Hex_buffer,11,15);
Hex_buffer[Hex_Data_Length] = 0x0D;
Hex_buffer[Hex_Data_Length+1] = 0x0A;
// UART_Write(UART1,QLWCONF_buffer,sizeof(QLWCONF_buffer)); //发送出去命令
while(time_out--)
{
if (TA_SUCCESS == BC26_send_cmd(UART1,Hex_buffer,"OK",&Data_Location,100)) // 超时时间2S
{
Statue = AT_QLWADDOBJ;
break;
}
else
{
if(time_out<1)
{
Statue = NB_Start;
New_Satrt_count--;
break;
}
}
}
break;
case AT_QLWADDOBJ: // 配置1
time_out = 2;
AT_cmd1 = "AT+QLWADDOBJ=19,1,1,";
AT_cmd2 = "0";
memset(Hex_buffer,0,sizeof(Hex_buffer));
Hex_Data_Length = Cmd_connect(AT_cmd1,AT_cmd2,Hex_buffer,20,1);
Hex_buffer[Hex_Data_Length]= 0x0D; //回车
Hex_buffer[Hex_Data_Length+1] = 0x0A;
while(time_out--)
{
if (TA_SUCCESS == BC26_send_cmd(UART1,Hex_buffer,"OK",&Data_Location,100)) // 超时时间2S
{
Statue = AT_QLWADDOBJ1;
break;
}
else
{
if(time_out<1)
{
Statue = NB_Start;
New_Satrt_count--;
break;
}
}
}
break;
case AT_QLWADDOBJ1: // 配置2
time_out = 2;
AT_cmd1 = "AT+QLWADDOBJ=19,0,1,";
AT_cmd2 = "0";
memset(Hex_buffer,0,sizeof(Hex_buffer));
Hex_Data_Length = Cmd_connect(AT_cmd1,AT_cmd2,Hex_buffer,20,1);
Hex_buffer[Hex_Data_Length]= 0x0D; //回车
while(time_out--)
{
if (TA_SUCCESS == BC26_send_cmd(UART1,Hex_buffer,"OK",&Data_Location,100)) // 超时时间2S
{
Statue = AT_QLWOPEN;
break;
}
else
{
if(time_out<1)
{
Statue = NB_Start;
New_Satrt_count--;
break;
}
}
}
break;
case AT_QLWOPEN: // Register to the IoT platform in direct push mode
time_out = 2;
while(time_out--)
{
if (TA_SUCCESS == BC26_send_cmd(UART1,"AT+QLWOPEN=0\r\n","+QLWOBSERVE:",&Data_Location,300)) // 超时时间6S
{
break;
}
else
{
if(time_out<1)
{
return TA_FAIL;
}
}
}
Statue = AT_QLWCFG; // 16进制
break;
case AT_QLWCFG:
time_out = 2;
AT_cmd1 = "AT+QLWCFG=";
AT_cmd2 = "dataformat";
memset(Hex_buffer,0,sizeof(Hex_buffer));
Hex_Data_Length = Cmd_connect(AT_cmd1,AT_cmd2,Hex_buffer,10,10);
Hex_buffer[Hex_Data_Length] = 0x2c; //,
Hex_buffer[Hex_Data_Length+1] = 0x31; //1
Hex_buffer[Hex_Data_Length+2] = 0x2c;//,
Hex_buffer[Hex_Data_Length+3] = 0x31; //1
Hex_buffer[Hex_Data_Length+4]= 0x0D; //回车
while(time_out--)
{
if (TA_SUCCESS == BC26_send_cmd(UART1,Hex_buffer,"OK",&Data_Location,100)) // 超时时间2S
{
Statue = AT_QLWDATASEND;
break;
}
else
{
if(time_out<1)
{
return TA_FAIL;
}
}
}
break;
case AT_QLWDATASEND: // updata
time_out = 3;
memset(Hex_buffer,0,sizeof(Hex_buffer));
Hex_Data_Length = NB_Settle_Data(Hex_buffer,NB_buffer,NB_Length);//数据整合
Hex_buffer[Hex_Data_Length++] = 0x2c;//,
Hex_buffer[Hex_Data_Length++] = 0x30;//0
Hex_buffer[Hex_Data_Length++] = 0x78;//x
Hex_buffer[Hex_Data_Length++] = 0x30;//0
Hex_buffer[Hex_Data_Length++] = 0x31;//1
Hex_buffer[Hex_Data_Length++] = 0x30;//0
Hex_buffer[Hex_Data_Length++] = 0x30;//0
Hex_buffer[Hex_Data_Length++]= 0x0D; //回车
Hex_buffer[Hex_Data_Length++] = 0x0A;
while(time_out--)
{
//Drv_SysDelayMs(2000);
if (TA_SUCCESS == BC26_send_cmd(UART1,Hex_buffer,"SEND OK",&Data_Location,200)) // 超时时间4S
{
return TA_SUCCESS;
}
else
{
if(time_out<1)
{
return TA_FAIL;
}
}
}
}
}
}
/*
功能,整理数据成NB 可以识别的正常数据
Outbuffer [OUT] 输出数据
INbuf : 输入的 开门信息
Len : 开门信息数据长度
*/
uint8_t NB_Settle_Data(uint8_t *Outbuffer,uint8_t *INbuf,uint8_t Len)
{
uint16_t length0=0,i=0;
char *AT_P = "AT+QLWDATASEND=19,0,0,";
length0 = AT_Conversion_HEX(AT_P,Outbuffer,22);
if(2*Len >9)
{
Outbuffer[length0++] = (2*Len)/10 + 0x30;
Outbuffer[length0++] = (2*Len)%10 + 0x30;
}
else
{
Outbuffer[length0++] = Len + 0x30;
}
Outbuffer[length0++] = 0x2c; //,
// data
for(i=0;i<Len;i++)
{
Outbuffer[length0++] = 0x33;
// if(INbuf[i]>9)
// {
Outbuffer[length0++] = INbuf[i]/10+0x30;
Outbuffer[length0++] = 0x33;
Outbuffer[length0++] = INbuf[i]%10+0x30;
// }
// else
// Outbuffer[length0++] = INbuf[i]%10+0x30;
}
return length0;
}
/* function: AT TO Hex
@param IN_buffer AT_cmd (IN)
length the length of IN_buffer
Outbuffer Hex (out)
*/
uint16_t AT_Conversion_HEX(char *IN_buffer,uint8_t *Outbuffer,uint16_t length)
{
char temp=0;
uint16_t i=0;
uint16_t Cmd_length = 0;
Cmd_length = length ;
while(Cmd_length--)
{
Outbuffer[i]= IN_buffer[i];
i++;
}
return i;
}
/*链接两个CMD
@param:*IN_buffer1 【IN】 cmd 1
*IN_buffer2 【IN】 cmd 2
*Outbuffer 【out】 输出 hex
length1 [IN] IN_buffer1 length
length2 [IN] IN_buffer2 length
*/
uint16_t Cmd_connect(char *IN_buffer1,char *IN_buffer2,uint8_t *Outbuffer,uint16_t length1,uint16_t lengt2)
{
uint16_t len1 = 0;
uint16_t len2 = 0;
len1 = AT_Conversion_HEX(IN_buffer1,Outbuffer,length1);
len2 = AT_Conversion_HEX(IN_buffer2, Outbuffer + len1+1 ,lengt2);
Outbuffer[len1] =0x22;
Outbuffer[len1+len2+1] = 0x22;
return (len1+len2+2);
}