一、简介

BC26 是一款高性能、低功耗、多频段 LTE Cat NB1/Cat NB2*无线通信模块。其尺寸仅为 17.7 mm × 15.8 mm × 2.0 mm,能最大限度地满足终端设备对小尺寸模块产品的需求,同时有效帮助客户减小产品尺寸并优化产品成本.BC26 在封装设计上兼容移远通信 GSM/GPRS 系列 M26 模块以及 NB-IoT 系列 BC28/BC25/BC260Y-CN 模块,方便客户快速、灵活的进行产品设计和升级。BC26 提供丰富的外部接口和协议栈,同时可支持中国移动 OneNET/Andlink、中国电信 IoT/ AEP以及阿里云IoT等物联网云平台,为客户的应用提供极大的便利。

BC26 采用更易于焊接的 LCC 封装,可通过标准 SMT 设备实现模块的快速生产,为客户提供可靠的连接方式,并满足复杂环境下的应用需求。

凭借紧凑的尺寸、超低功耗和超宽工作温度范围,BC26 成为 IoT 应用领域的理想选择,常被用于烟感、无线抄表、共享单车、智能停车、智慧城市、安防、资产追踪、智能家电、可穿戴设备、农业和环境监测以及其它诸多行业,以提供完善的短信和数据传输服务。

BC26资料:链接:https://pan.baidu.com/s/1n8rcRCna8wnMPFwikY3l0g?pwd=vgcm 提取码:vgcm

二、AT指令

发送数据时务必勾选:“加回车换行符”。否则模块不会响应。在本文中,仅显示响应,省略回车换行符。

2.1 AT

测试AT指令功能是否正常,等待模块返回 OK。

ATOK

2.2 AT+CIMI

该命令用于查询(U)SIM 卡的国际移动用户识别码(IMSI,无双引号的字符串)。IMSI 允许 TE 识别连
接到 MT 的 USIM。

AT+CIMI460001357924680OK

2.3 AT+CGATT=1

设置命令用于将 MT 附着于 PS 域。命令完成后,MT 保持在 V.250 命令状态。如果 MT 已经处于请求状态,则忽略该命令,并且仍将响应 OK。如果 MT 无法实现请求状态,将响应 ERROR 或+CME ERROR。

AT+CGATT=1OK

2.4 AT+CGATT?

查询命令返回当前 PS 域服务状态。

AT+CGATT=?+CGATT: <state>
如:+CGATT: 1OK

整型。PDP 上下文激活状态。

  • 0 去附着
  • 1 附着

2.5 AT+CEREG?

AT+CEREG?+CEREG: <n>,<stat>
如:+CEREG: 0,1
如:+CEREG: 1,1OK

整型。禁止或允许上报网络注册状态等信息。

  • 0 禁止上报网络注册状态 URC
  • 1 允许上报网络注册状态 URC +CEREG:
  • 2 允许上报网络注册状态和位置信息 URC +CEREG: [,[],[],[]]
  • 3 允许上报网络注册状态、位置信息和 EMM 原因值 URC +CEREG: [,[],[],[][,<cause_type>,<reject_cause>]]
  • 4 对于请求 PSM 的 UE,允许上报网络注册状态和位置信息 URC +CEREG: [,[],[],[][,[,[],[]]]]
  • 5 对于请求 PSM 的 UE,允许上报网络注册状态、位置信息和 EMM 原因值 URC +CEREG: [,[],[],[][,[<cause_type>],[<reject_cause>][,[, []]]]

整型。EPS 注册状态。

  • 0 未注册,MT 当前未搜索网络
  • 1 已注册,归属网络
  • 2 未注册,但 MT 当前正在尝试附着或搜索网络以进行注册
  • 3 注册被拒绝
  • 4 未知(例如:超出 E-UTRAN 覆盖范围)
  • 5 已注册,漫游状态

2.6 AT+QIPADDR

查询 UE 的 IP 地址

AT+QIPADDR+QIPADDR: fe80:0:0:0:3c:ffb8:f4c9:1207+QIPADDR: 2001:14bb:170:4c91:3c: ffh8:f4c9:1207+QIPADDR: 178.55.211.180+QIPADDR: 127.0.0.1OK

2.7 AT+QIOPEN

该命令用于打开套接字服务。

  • AT+QIOPEN=?:查询命令参数。
  • AT+QIOPEN=,,<service_type>,<IP_address>/<domain_name>,<remote_port>[,<local_po CONNECTrt>[,<access_mode>]] :打开 Socket 服务。
    • :整数类型。上下文ID。范围是1-16。
    • :整数类型。套接字服务索引。范围是0-11。
    • <SERVICE_TYPE>:字符串类型。套接字服务类型。
      • “ TCP ” :作为客户端启动TCP连接
      • “ UDP ”:作为客户端启动UDP连接
      • “TCP LISTENER” :启动TCP服务器以侦听TCP连接
      • “UDP SERVICE” :启动UDP服务
    • <IP_address>:字符串类型。
      • 如果<service_type>是TCP或UDP ,则表示远程服务器的IP地址,例如 “220.180.239.212”。
      • 如果<service_type>是TCP LISTENER或UDP SERVICE 地址,请输入“127.0.0.1”。
    • <domain_name>:字符串类型。远程服务器的域名地址。
    • <remote_port> :远程服务器的端口,仅在<service_type>为“TCP”或“UDP”时有效。范围是0-65535。
    • <LOCAL_PORT> :本地端口。范围是0-65535。
      • 如果<service_type>是“TCP LISTENER”或“UDP SERVICE”,则此参数必须指定。
      • 如果<service_type>是“TCP”或“UDP”。如果<local_port>为0,那么本地端口将是自动分配。否则,将按指定分配本地端口。
    • <access_mode> :整数类型。套接字服务的数据访问模式。
      • 0: 缓冲区访问模式
      • 1:直推模式
      • 2:透明访问模式
    • :整数类型。操作的错误代码。请参阅第4章。
AT+QIOPEN=1,0,\"TCP\",\"180.97.81.180\",53540,0,1OK+QIOPEN: 0,0

Buffer模式,Push模式,透传模式。通过参数<access_mode>进行配置。





2.8 AT + QISEND

如果指定套接字服务的<access_mode>是缓冲区访问模式或直接推送模式,则数据可以是通过AT + QISEND发送。如果数据成功发送到模块,将返回“ SEND OK ” 。否则它将返回“ SEND FAIL ” 或“ ERROR ” 。“ SEND FAIL ” 表示发送缓冲区已满客户可以尝试重新发送数据。“ERROR”表示在发送过程中遇到错误 数据。客户应该延迟一段时间来发送数据。最大数据长度为1460字。“SEND OK”并不意味着数据已成功发送到服务器。客户可以查询数据是否通过AT + QISEND = ,0命令到达服务器。透传模式下不需要AT指令发送数据

三、TCP应用时序图

四、复位模块

通过拉低 RESET 引脚至少 50ms 可以使模块复位。

五、移植文件

5.1 board_bc26.c

/********************************************************************** INCLUDES*/
#include "stdlib.h"
#include "string.h"
#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h" #include "board_bc26.h" static uint8_t sendCmd(char *pCmd, char *pRes, char *pRes2, uint32_t timeOut, uint8_t sendNum);
static void clearBuffer(void);
static void reset(void);/********************************************************************** GLOBAL VARIABLES*/
uint8_t g_usart2RecvFinish = 0;                                                 // 串口2接收标志串口接收完成标志
char g_bc26Buf[1024] = {0};                                                     // 接收缓存
volatile uint32_t g_bc26Cnt;                                                    // 接收计数                                 /********************************************************************** PUBLIC FUNCTIONS*/
/**@brief 初始化@param 无@return 1 - 成功;0 - 失败
*/
uint8_t BC26_Init(void)
{       printf("BC26_Init\r\n");uint8_t result = 0;uint8_t step = 0;switch(step){case 0:if(sendCmd("AT\r\n", "OK", NULL, 10, 6))                            // 测试AT指令功能是否正常{step++;}else{printf("Err:AT\r\n");reset();break;} case 1:if(sendCmd("AT+CIMI\r\n", "OK", NULL, 20, 1))                       // 查询SIM卡是否正常,返回OK则表示SIM卡正常{step++;}else{printf("Err:AT+CIMI\r\n");                                      // 20秒内,无法识别SIM状态,重启模块reset();break;}case 2:if(sendCmd("AT+CGATT=1\r\n", "OK", "+IP:", 60, 1))                  // 激活PDP场景{step++;                                                 }else{printf("Err:AT+CGATT=1\r\n");        step++;                                                         }case 3:if(sendCmd("AT+CEREG?\r\n", "+CEREG: 0,1", "+CEREG: 1,1", 60, 3))   // 查询模组是否注册上EPS网络{step++;                                                 }else{printf("Err:AT+CEREG?\r\n");      step++;                                                         }case 4:if(sendCmd("AT+CGATT?\r\n", "+CGATT: 1", NULL, 85, 3))              // 查询当前PS域服务状态{step++;}else{printf("Err:AT+CGATT?\r\n");                                    // 如果3次都没停止成功或超过85秒没有回应,则重启模块reset();break;}case 5:if(sendCmd("AT+QIPADDR\r\n", "+QIPADDR:", NULL, 60, 3))             // 查询本机IP地址{BC26_Connect();result = 1;}else{printf("Err:AT+QIPADDR\r\n");                                   // 如果3次都没停止成功或超过60秒没有回应,则重启模块reset();break;}}return result;
}/**@brief 复位引脚配置@param 无@return 无
*/
void BC26_GpioConfig(void)
{GPIO_InitTypeDef gpioInitStructure;        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);                       // 使能GPIOgpioInitStructure.GPIO_Pin = GPIO_Pin_8;                                    // 选择要初始化的GPIOB引脚PB8gpioInitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                             // 设置引脚工作模式为通用推挽输出       gpioInitStructure.GPIO_Speed = GPIO_Speed_50MHz;                            // 设置引脚输出最大速率为50MHzGPIO_Init(GPIOB, &gpioInitStructure);       GPIO_SetBits(GPIOB, GPIO_Pin_8);
}/**@brief 连接TCP服务器@param 无@return 无
*/
void BC26_Connect(void)
{if(sendCmd("AT+QICLOSE=0\r\n", "OK", NULL, 20, 1))                          // 关闭TCP连接{if(sendCmd("AT+QIOPEN=1,0,\"TCP\",\"180.97.81.180\",53540,0,1\r\n", "+QIOPEN:", 150, 5))    {printf("Connect Success\r\n");}      else{printf("Err:AT+QIOPEN=1,0\r\n");reset();                                                            // 没有响应重启模块}       }
}/**@brief 发送数据到TCP服务器@param pString -[in] 发送数据@return 无
*/
void BC26_Send(char *pString)
{if(sendCmd("AT+QISEND=0\r\n", ">", NULL, 30, 2))                            // 等待60秒,没有响应重启模块                            {vTaskDelay(500);                                                        // 等待500mschar sendBuf[1024] = {0};sprintf(sendBuf, "%s\r\n\x1A", pString);if(sendCmd(sendBuf, "SEND OK", "OK", 30, 2)){if(sendCmd("AT+QISEND=0,0\r\n", "+QISEND:", NULL, 5, 24))           // 2分钟后(每5秒查询一次,共24次){    /* 发送数据成功,对方收到数据 */}else{printf("Err:AT+QISEND=0\r\n");                                      if(sendCmd("AT+QICLOSE=0\r\n", "OK", NULL, 20, 1))              // TCP连接出现异常,关闭TCP连接{printf("AT+QICLOSE\r\n");BC26_Connect();}}}else{BC26_Reset();                                                       // 等待60秒,没有响应重启模块} }else{BC26_Reset();                                                           // 等待60秒,没有响应重启模块    }
}/**@brief 从TCP服务器接收数据@param pRecvDataBuf -[out] 接收数据@return 接收数据长度
*/
uint32_t EC200S_Receive(char *pRecvDataBuf)
{uint32_t recvDataLen = 0;if(g_isUsart2RecvFinish)                                                    // 如果串口接收完成{if(strstr((const char *)g_bc26Buf, "+QIURC: \"recv\",0,") != NULL)      // 如果检索到关键词{memcpy(pRecvDataBuf, g_bc26Buf, g_bc26Cnt);recvDataLen = g_bc26Cnt;}else if(strstr((const char *)g_bc26Buf, "+QIURC: \"closed\",0,") != NULL){BC26_Reset();}clearBuffer();} return recvDataLen;
}/**@brief 重启模块@param 无@return 无
*/
void BC26_Reset(void)
{reset();
}/********************************************************************** LOCAL FUNCTIONS*/
/**@brief 发送AT命令@param pCmd -[in] 命令字符串@param pRes -[in] 需要检测的返回命令字符串@param pRes2 -[in] 需要检测的返回命令字符串@param timeOut -[in] 等待时间@param sendNum -[in] 命令发送次数@return 1 - 成功;0 - 失败
*/
static uint8_t sendCmd(char *pCmd, char *pRes, char *pRes2, uint32_t timeOut, uint8_t sendNum)
{uint8_t i = 0;uint32_t time;clearBuffer();                                                              // 清空缓存   for(i = 0; i < sendNum; i++){time = timeOut * 10;USART_SendString(USART2, pCmd);while(time--){if(g_usart2RecvFinish)                                              // 如果串口接收完成{if(strstr((const char *)g_bc26Buf, pRes) != NULL)               // 如果检索到关键词{printf("%s", g_bc26Buf);return 1;}else if(strstr((const char *)g_bc26Buf, pRes2) != NULL))       // 如果检索到关键词2{printf("%s", g_bc26Buf);return 1;}}    vTaskDelay(100);                                                   // 等待100毫秒}clearBuffer();}return 0;
}/**@brief 清空缓存@param 无@return 无
*/
void clearBuffer(void)
{memset(g_bc26Buf, 0, sizeof(g_bc26Buf));g_bc26Cnt = 0;g_usart2RecvFinish = 0;
}/**@brief 重启模块@param 无@return 无
*/
void reset(void)
{printf("reset\n");GPIO_ResetBits(GPIOB, GPIO_Pin_8);vTaskDelay(60);GPIO_SetBits(GPIOB, GPIO_Pin_8);
}/****************************************************END OF FILE****************************************************/

5.2 board_bc26.h

#ifndef _BOARD_BC26_H_
#define _BOARD_BC26_H_/********************************************************************** INCLUDES*/
#include "stm32f10x.h"/********************************************************************** GLOBAL VARIABLES*/
extern uint8_t g_usart2RecvFinish;      // 串口2接收标志串口接收完成标志
extern char g_bc26Buf[1024];            // 接收缓存
extern uint32_t g_bc26Cnt;              // 接收计数/********************************************************************** API FUNCTIONS*/
uint8_t BC26_Init(void);
void BC26_GpioConfig(void);
void BC26_Connect(void);
void BC26_Send(char *pString);
uint32_t BC26_Receive(char *pRecvDataBuf);
void BC26_Reset(void);#endif /* _BOARD_BC26_H_ */

六、使用方法

BC26_GpioConfig();
BC26_Init();
while(1)                                                            // 任务都是一个无限循环,不能返回
{BC26_Send("TEST");vTaskDelay(10000);  char recvDataBuf[256] = {0};int recvDataLen = BC26_Receive(recvDataBuf);
}
/**@brief 串口2收发中断@param 无@return 无
*/
void USART2_IRQHandler(void)
{if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)                           // 接收中断{g_usart2RecvFinish = 1;                                                   // 串口2接收标志if(g_bc26Cnt >= sizeof(g_bc26Buf)){g_bc26Cnt = 0;                                                        // 防止串口被刷爆}g_bc26sBuf[g_bc26Cnt++] = USART2->DR;USART_ClearFlag(USART2, USART_FLAG_RXNE);}
}

• 由 Leung 写于 2022 年 8 月 26 日

• 参考:移远BC35-G模组(NB-IoT 通信模组)AT指令测试 UDP 通信过程
    NB-IOT(BC26)相关AT指令——UDP/TCP传输
    NB260软件设计手册

STM32F103学习笔记(9)——NB-IoT模块BC26使用相关推荐

  1. STM32F103学习笔记(2)——收音机模块TEA5767使用

    一.简介 TEA5767是由菲利普公司推出的一款低功耗立体声收音机接收器芯片.频率范围从76-108MHz自动数字调谐.高灵敏度,高稳定性,低噪音,收音模块.一片低功耗电调谐调频立体声收音机电路,其内 ...

  2. 【物联网学习笔记——人人学IoT系列】三、窄带无线,海量物联

    目录 1. NB-IoT 1.1 NB-IoT背景知识 1.2 NB-IoT的网络总体架构 2. NB-IoT中的Niubility技术 2.1 NB-IoT物理层 2.1.1 NB-IoT上行技术 ...

  3. Python学习笔记:常用第三方模块3

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  4. Python学习笔记:常用第三方模块(1)

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  5. Python学习笔记:常用内建模块7XML

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  6. Python学习笔记:常用内建模块5

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  7. Python学习笔记:常用内建模块2:collections

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  8. STM32F103学习笔记(5)——数码管驱动TM1650使用

    一.简介 TM1650 是一种带键盘扫描接口的 LED(发光二极管显示器)驱动控制专用电路.内部集成有 MCU 输入输出控制数字接口.数据锁存器.LED 驱动.键盘扫描.辉度调节等电路.TM1650 ...

  9. 【物联网学习笔记——人人学IoT系列】二、IoT平台,能力开放

    目录 1. 解锁物联网平台,与OceanConnect相识 1.1 物联网发展的挑战 1.1.1 新业务上线周期长 1.1.2 标准不统一.集成困难 1.1.3 网络联接复杂 1.2 应对挑战的方案 ...

  10. 【物联网学习笔记——人人学IoT系列】一、初识物联网

    目录 1. 物联网初探 1.1 物联网(Internet of Things)早期概念定义 1.2 物联网概念发展历程 1.3 发展历史时期划分 1.3.1 概念期 1.3.2 发展期 1.3.3 成 ...

最新文章

  1. MySQL数据库高可用集群搭建-PXC集群部署
  2. 判断三角形java代码_小猿圈Java循环嵌套语法的使用介绍
  3. react16 渲染流程
  4. aidl使用_借助 AIDL 理解 Android Binder 机制——Binder 来龙去脉
  5. 对DbRuleAuthorizationProvider的修改
  6. python循环五角星做法_python实现while循环打印星星的四种形状
  7. 32位linux运行64位jdk,linux64位操作系统装32位jdk解决方法
  8. SQL:在使用分组函数统计并进行分组时,发现有两条除了统计数据不一样,其他都一样的数据
  9. 2019 ICPC Asia Yinchuan Regional(9 / 13)
  10. Python rabbitmq的使用(五)
  11. php检查函数是否存在,php判断类是否存在函数class_exists用法分析
  12. C#中的文件流和文本流
  13. 如何将分表汇总到总表_总表输入数据,自动拆分到分表,你会吗?
  14. 解决部分控件,自动获取焦点的情况
  15. Spring的线程安全
  16. 全志A31编译脚本 .
  17. Android版添加phonegap--融云即时通讯插件教程
  18. 阿里云的图片在小程序内不显示
  19. 迅雷看看引领高清内容多屏合一新趋势
  20. [转]firefox浏览器油猴脚本-让网页背景成苹果蓝,保护眼睛

热门文章

  1. dhcp、tftp基础
  2. 前端开发者的必备好书:CSS世界三部曲,你都知道吗?
  3. WPS安装自定义项安装程序出错问题
  4. 随机梯度下降SGD算法原理和实现
  5. 软件工程——软件详细设计
  6. OBS 录制简单操作说明
  7. UDS诊断基础知识简介-ISO14229
  8. Win10安装ST-Link驱动--无需下载驱动
  9. STM32CubeIDE更新ST LINK驱动失败解决方法
  10. idea运行java项目js中文乱码如何解决