当前位置: 移动技术网 > IT编程>开发语言>C/C++ > BC35 NB模块AT指令开发总结

BC35 NB模块AT指令开发总结

2020年08月11日  | 移动技术网IT编程  | 我要评论



一.BC35 NB模块简介

BC35-G 是一款高性能、低功耗的 NB-IoT 模块,支持如下表格中所列的六个频段。通过 NB-IoT 无线电通信协议(3GPP Rel. 14),BC35-G 模块可与网络运营商的基础设备建立通信。
在这里插入图片描述
供电 :
VBAT 供电电压范围:3.1V~4.2V
典型供电电压:3.6V

发射功率:
23dBm±2dB

串口:
主串口:用于 AT 命令通信和数据传输,支持的波特率为 4800bps、9600bps(默认)、57600bps、115200bps、230400bps 和 460800bps,用于固件升级,支持的波特率为 115200bps 和 921600bps
调试串口:用于软件调试,仅支持波特率 921600bps

网络协议特性 :
支持 IPv4/IPv6/UDP/CoAP/LwM2M/Non-IP/DTLS/TCP/MQTT 协议

天线接口:
50Ω 特性阻抗

二.TCP传输数据流程

1.模块上电开机----->2.模块联网----->3.建立TCP连接----->4.TCP发送数据----->5.等待返回数据并处理----->6.模块断电关机。

详细程序流程:

相关支持函数: //串口1,printf 函数 //确保一次发送数据不超过USART1_MAX_SEND_LEN字节 void nb_printf(char* fmt,...) { u16 i; va_list ap; va_start(ap,fmt); vsprintf((char*)USART1_TX_BUF,fmt,ap); va_end(ap); i=strlen((const char*)USART1_TX_BUF);//此次发送数据的长度 /*采用串口寄存器操作发送数据*/ // for(j=0;j<i;j++)//循环发送数据 // { //  while((USART1->ISR&0X40)==0);    //循环发送,直到发送完毕  //  USART1->TDR=USART1_TX_BUF[j];  // } /*采用串口HAL库函数发送数据*/ //    HAL_UART_Transmit(&huart1, (uint8_t*)USART1_TX_BUF,i, 1000); //发送接收到的数据 //    while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) != SET);  //等待发送结束 /*采用DMA方式发送数据*/ HAL_USART1_DMA_TX(&USART1TxDMA_Handler,DMA_FLAG_TC2,&huart1,USART1_TX_BUF,i);//使用DMA发送数据 memset(USART1_TX_BUF,0,sizeof(USART1_TX_BUF));//清空缓存 } //NB_MODULE发送命令后,检测接收到的应答 //str:期待的应答结果 //返回值:0,没有得到期待的应答结果 //    其他,期待应答结果的位置(str的位置) u8* nb_send_check_cmd(u8 *str) { char *strx=0; USART1_RX_BUF[USART1_RX_COUNT]=0;//添加结束符 strx=strstr((const char*)USART1_RX_BUF,(const char*)str); return (u8*)strx; } //向NB_MODULE发送指定数据 //data:发送的数据(不需要添加回车了) //ack:期待的应答结果,如果为空,则表示不需要等待应答 //waittime:等待时间(单位:100ms) //返回值:0,发送成功(得到了期待的应答结果) //       1,发送失败 u8 nb_send_cmd(u8 *data,u8 *ack,u16 waittime) { waittime=waittime*100; nb_printf("%s\r\n",data); //需要发送的是命令 if(ack&&waittime) //需要等待应答 { while(--waittime) //等待倒计时 { delay_ms(1); if(USART1_IDLE_FLAG) //接收到期待的应答结果 { if(nb_send_check_cmd(ack)) { //printf("%s ack:  %s\r\n",data,(u8*)ack); Feed_Dog(); //喂狗 memset(USART1_RX_BUF,0,sizeof(USART1_RX_BUF));//清空USART1缓存 USART1_IDLE_FLAG=0; USART1_RX_COUNT=0; //串口1接受数据清零 return 0; //ack正确,返回1 } memset(USART1_RX_BUF,0,sizeof(USART1_RX_BUF));//清空USART1缓存 USART1_IDLE_FLAG=0; USART1_RX_COUNT=0;//串口1接受数据清零 } } } return 1; //ack错误,返回0 } //向NB_MODULE发送指定数据,并读取返回参数值 //data:发送的数据(不需要添加回车了) //ack:期待的应答结果,如果为空,则表示不需要等待应答 //waittime:等待时间(单位:100ms) //返回值:0,发送成功(得到了期待的应答结果) //       1,发送失败 u8 nb_send_cmd_return(u8 *data,u8 *ack,u16 waittime,u8 *parameter) { nb_printf("%s\r\n",data); //需要发送的是命令 if(ack&&waittime) //需要等待应答 { while(--waittime) //等待倒计时 { delay_ms(100); if(USART1_IDLE_FLAG) //接收到期待的应答结果 { if(nb_send_check_cmd(ack)) { *parameter=USART1_RX_BUF[2]; printf("%s ack:  %s\r\n",data,(u8*)ack); Feed_Dog(); //喂狗 memset(USART1_RX_BUF,0,sizeof(USART1_RX_BUF));//清空USART1缓存 USART1_IDLE_FLAG=0; USART1_RX_COUNT=0; //串口1接受数据清零 return 0; //ack正确,返回1 } memset(USART1_RX_BUF,0,sizeof(USART1_RX_BUF));//清空USART1缓存 USART1_IDLE_FLAG=0; USART1_RX_COUNT=0;//串口1接受数据清零 } } } return 1; //ack错误,返回0 } 2.模块联网 /**
 * @brief NB模块联网
 *          参考手册:p160 手动网络连接
 *
 * @param   void
 *
 * @return  0:连接成功
 *          1:连接失败        
 */ u8 NB_Connect_To_Internet(void) { u8 i=0; for(i=0;i<3;i++) if(nb_send_cmd((u8 *)"AT+NRB",(u8 *)"REBOOT_CAUSE_APPLICATION_AT",100)==0)break; if(i==3) { printf("模块重启失败...\r\n\r\n"); return 1; //失败,返回1 } else printf("模块重启成功...\r\n\r\n"); for(i=0;i<3;i++) if(nb_send_cmd((u8 *)"AT+NBAND=5",(u8 *)"OK",10)==0)break; if(i==3) { printf("设置频段失败...\r\n\r\n"); return 1; //失败,返回1 } else printf("设置频段成功...\r\n\r\n"); for(i=0;i<3;i++) if(nb_send_cmd((u8 *)"AT+CFUN=1",(u8 *)"OK",40)==0)break; if(i==3) { printf("设置最大功能模式失败...\r\n\r\n"); return 1; //失败,返回1 } else printf("设置最大功能模式成功...\r\n\r\n"); i=0; for(i=0;i<3;i++) if(nb_send_cmd((u8 *)"AT+CEDRXS=0,5",(u8 *)"OK",10)==0)break; if(i==3) { printf("关闭模组eDRX功能失败...\r\n\r\n"); return 1; //失败,返回1 } else printf("关闭模组eDRX功能成功...\r\n\r\n"); for(i=0;i<3;i++) if(nb_send_cmd((u8 *)"AT+CGATT=1",(u8 *)"OK",20)==0)break; if(i==3) { printf("附着网络失败...\r\n\r\n"); return 1; //失败,返回1 } else printf("附着网络成功...\r\n\r\n"); for(i=0;i<10;i++) if(nb_send_cmd((u8 *)"AT+CGATT?",(u8 *)"+CGATT:1",20)==0)break; if(i==10) { printf("网络连接失败...\r\n\r\n"); return 1; } else printf("网络连接成功...\r\n\r\n"); return 0; } 3.建立TCP连接 /**
 * @brief 建立TCP连接
 *
 * @param   ip:需要连接的ip地址
 *          port:需要连接的端口
 *          socket:连接成功后返回创建的socket值
 *
 * @return  0:发送成功
 *          1:发送失败        
 */ u8 NB_TCP_Connect(const u8* ip,const u8* port,u8* socket) { u8 i=0; u8 p[50]; for(i=0;i<3;i++) if(nb_send_cmd_return((u8 *)"AT+NSOCR=STREAM,6,0,1",(u8 *)"OK",100,socket)==0)break; if(i<3)printf("创建socket成功...\r\n\r\n"); else { printf("创建socket失败...\r\n\r\n"); return 1; } *socket=*socket-48; printf("tcp_socket=%d\r\n",*socket); sprintf((char*)p,"AT+NSOCO=%d,%s,%s",*socket,ip,port); for(i=0;i<3;i++) if(nb_send_cmd((u8 *)p,(u8 *)"OK",100))break; if(i<3)printf("TCP连接成功...\r\n\r\n"); else { printf("TCP连接失败...\r\n\r\n"); return 1; } return 0; } 4.TCP发送数据 /**
 * @brief TCP发送数据
 *
 * @param   socket:套接字号
 *          data:发送的数据
 *          len:发送的数据长度
 *
 * @return  0:发送成功
 *          1:发送失败        
 */ u8 tx_buffer[2000]={0}; //定义最终发送数据缓存区 u8 p[2000]; //封装成最终要发送的帧格式 u8 NB_TCP_Send_Data(u8 socket,u8* data,u16 len) { u8 i=0; HexArrayToString(data,(char*)USART1_TX_BUF,len); //先将原始数据转成字符串 HexArrayToString(USART1_TX_BUF,(char*)tx_buffer,2*len); //再讲字符串转成ASCII码 sprintf((char*)p,"AT+NSOSD=%d,%d,%s,%s,%s",socket,2*len,(char*)tx_buffer,"0x100","101"); memset(USART1_TX_BUF,0,sizeof(USART1_TX_BUF));//清空缓存,因为下面nb_send_cmd()也需要用到USART1_TX_BUF,因此需要清空 memset(tx_buffer,0,sizeof(tx_buffer)); //清空缓存,因为下面nb_send_cmd()也需要用到USART1_TX_BUF,因此需要清空 for(i=0;i<3;i++) if(nb_send_cmd((u8 *)p,(u8 *)"101,1",50)==0)break; memset(p,0,sizeof(p));//清空缓存 if(i<3) { printf("TCP发送数据成功,且确认被服务器收到...\r\n\r\n"); return 0; } else { printf("TCP发送数据失败...\r\n\r\n"); return 1; } } 5.等待返回数据并处理(部分程序) while(1) //等待云端回数据倒计时 { delay_ms(5); //延时5ms判断是否收到数据 if(USART1_IDLE_FLAG) //串口1接收数据完毕,与NB模块通信 { /*判断是否有来自服务器的数据*/ str1=nb_send_check_cmd((u8 *)"+NSONMI:");//判断接受到的数据是否有+NSONMI: if(str1) //确定接收到了+NSONMI: { receive_socket=*(str1+8)-48; //获得当前socket编号 if(USART1_RX_COUNT-14==1)receive_num=*(str1+10)-48; else if(USART1_RX_COUNT-14==2)receive_num=(*(str1+10)-48)*10+*(str1+11)-48; //获得当前收到的字节数 sprintf((char*)q,"%d,%s,%s,%d",receive_socket,IP_address,portnum,receive_num);//组成一个包 receive_data_flag=1; //接收到数据标志位置位 } /*判断是否收到服务器的数据*/ str2=nb_send_check_cmd((u8*)q); //判断接受到的数据是否有+NSONMI: if(str2) //确定接收到了数据 { HexStrToByte(str2+strlen(q)+1,Receive_Buffer,2*receive_num); //将字符装成HEX并存在Receive_Buffer中,待处理 read_data_flag=1; //数据处理标志位置位 } memset(USART1_RX_BUF,0,sizeof(USART1_RX_BUF));//清空缓存 USART1_RX_COUNT=0; //将接受字节数清零 USART1_IDLE_FLAG=0; //空闲中断标志复位 } if(receive_data_flag) //确认模块接收到来自服务器的数据 { sprintf((char*)p,"AT+NSORF=%d,%d",receive_socket,200); nb_printf("%s\r\n",p); //发送接收数据指令 receive_data_flag=0; //接收到数据标志位复位 } /*需要进行数据处理了*/ if(read_data_flag) //确认需要进行数据处理 { for(i=0;i<receive_num;i++) printf("%x ",Receive_Buffer[i]); printf("\r\n"); waittime=4000; //接收到一次数据后恢复计时时间 break; } }

三.UDP传输数据流程

1.模块上电开机----->2.模块联网----->3.建立UDP连接----->4.UDP发送数据----->5.等待返回数据并处理----->6.模块断电关机。

详细程序流程:

相关支持函数:
同上面TCP一致 2.模块联网
同上面TCP一致 3.建立UDP连接 /**
 * @brief 建立UDP连接
 *
 * @param   ip:需要连接的ip地址
 *          port:需要连接的端口
 *          socket:连接成功后返回创建的socket值
 *
 * @return  0:发送成功
 *          1:发送失败        
 */ u8 NB_UDP_Creat_socket(u8* socket) { u8 i=0; for(i=0;i<3;i++) if(nb_send_cmd_return((u8 *)"AT+NSOCR=DGRAM,17,0,1",(u8 *)"OK",100,socket)==0)break; if(i<3) { printf("创建socket成功...\r\n\r\n"); *socket=*socket-48; printf("udp_socket=%d\r\n",*socket); return 0; } else printf("创建socket失败...\r\n\r\n"); return 1; } 4.UDP发送数据 /**
 * @brief UDP发送数据
 *
 * @param   socket:套接字号
 *          data:发送的数据
 *          len:发送的数据长度
 *
 * @return  0:发送成功
 *          1:发送失败        
 */ u8 NB_UDP_Send_Data(u8 socket,const u8* ip,const u8* port,u8* data,u16 len) { u16 i=0; HexArrayToString(data,(char*)USART1_TX_BUF,len); //先将原始数据转成字符串 HexArrayToString(USART1_TX_BUF,(char*)tx_buffer,2*len); //再讲字符串转成ASCII码 sprintf((char*)p,"AT+NSOST=%d,%s,%s,%d,%s,%d",socket,ip,port,2*len,(char*)tx_buffer,100); memset(USART1_TX_BUF,0,sizeof(USART1_TX_BUF));//清空缓存,因为下面nb_send_cmd()也需要用到USART1_TX_BUF,因此需要清空 memset(tx_buffer,0,sizeof(tx_buffer)); //清空缓存,因为下面nb_send_cmd()也需要用到USART1_TX_BUF,因此需要清空 for(i=0;i<3;i++) if(nb_send_cmd((u8 *)p,(u8 *)"100,1",100)==0)break; memset(p,0,sizeof(p));//清空缓存 if(i<3) { printf("UDP发送数据成功...\r\n\r\n"); return 0; } else { printf("UDP发送数据失败...\r\n\r\n"); return 1; } } 5.等待返回数据并处理
同上面TCP一致

本文地址:https://blog.csdn.net/weixin_42700740/article/details/107907024

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网