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Ω 特性阻抗
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;
}
}
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一致