During the development process, I used the 4G and 5G compatible card provided by China Unicom. After debugging the code and analyzing the output results, I found that when sending the AT+CSQ command to query the signal quality, the response was +CSQ: 99, 99. By sending the AT+CREG command to query the network registration status, the response is always +CREG:0,2. Could you please tell me what the reason is that prevents me from registering on the network?I will provide my test code.
/**
@file RAK5860_Network_Registration_Test.ino
@brief RAK5860 BG77 网络注册专项测试
@note 专门解决 +CEREG:0,2 网络注册问题
*/
#include <Arduino.h>
#include <Adafruit_USBD_CDC.h>
#include <SoftwareSerial.h>
#define BG77_POWER_KEY WB_IO1
// 联通APN列表 - 按优先级排序
const String APN_LIST[] = {
"3GNET", // 联通3G/4G通用APN(推荐)
"UNINET", // 联通原始APN
"LTENET", // 联通LTE专用APN
"WONET", // 联通物联网APN
"CMNET" // 如果是移动卡的话
};
const int APN_COUNT = 5;
// 测试配置
#define REGISTRATION_TIMEOUT 180000 // 3分钟注册超时
#define AT_TIMEOUT 5000
#define CHECK_INTERVAL 10000 // 每10秒检查一次状态
int currentAPNIndex = 0;
unsigned long testStartTime = 0;
// 简化的调试输出
void debugLog(String message) {
Serial.print("[");
Serial.print(millis()/1000);
Serial.print("s] ");
Serial.println(message);
}
// 读取BG77响应
String readBG77Response(int timeout) {
String response = "";
unsigned long startTime = millis();
while (millis() - startTime < timeout) {
if (Serial1.available()) {
char c = Serial1.read();
response += c;
Serial.print(c); // 实时显示响应
}
}
return response;
}
// 发送AT命令并等待OK
bool sendATCommand(String command, int timeout = AT_TIMEOUT) {
debugLog("发送: " + command);
// 清空接收缓冲区
while (Serial1.available()) Serial1.read();
Serial1.println(command);
String response = readBG77Response(timeout);
return response.indexOf("OK") >= 0;
}
// 发送AT命令并等待特定响应
String sendATCommandGetResponse(String command, int timeout = AT_TIMEOUT) {
debugLog("查询: " + command);
while (Serial1.available()) Serial1.read();
Serial1.println(command);
return readBG77Response(timeout);
}
// 初始化BG77模块
bool initializeBG77() {
debugLog("=== BG77模块初始化 ===");
// 配置电源引脚
pinMode(BG77_POWER_KEY, OUTPUT);
digitalWrite(BG77_POWER_KEY, HIGH);
// 初始化串口
Serial1.begin(115200);
delay(2000);
// 检查模块是否响应
debugLog("检查模块响应...");
Serial1.println("ATI");
String response = readBG77Response(3000);
if (response.length() < 10) {
debugLog("模块无响应,尝试唤醒...");
// 执行唤醒序列
digitalWrite(BG77_POWER_KEY, LOW);
delay(1000);
digitalWrite(BG77_POWER_KEY, HIGH);
delay(2000);
digitalWrite(BG77_POWER_KEY, LOW);
delay(3000);
// 再次检查
Serial1.println("ATI");
response = readBG77Response(5000);
if (response.length() < 10) {
debugLog("模块唤醒失败!");
return false;
}
}
debugLog("模块响应正常");
return true;
}
// 基本配置
bool basicConfiguration() {
debugLog("=== 基本配置 ===");
// 基本AT测试
if (!sendATCommand("AT")) {
debugLog("基本AT命令失败!");
return false;
}
// 关闭回显
sendATCommand("ATE0");
// 设置错误报告格式
sendATCommand("AT+CMEE=2");
// 检查SIM卡状态
debugLog("检查SIM卡...");
String simResponse = sendATCommandGetResponse("AT+CPIN?");
if (simResponse.indexOf("+CPIN: READY") < 0) {
debugLog("SIM卡未就绪! 请检查SIM卡插入和状态");
debugLog("SIM卡响应: ");
Serial.println(simResponse);
return false;
}
debugLog("SIM卡状态正常");
return true;
}
// 查询基本信息
void queryBasicInfo() {
debugLog("=== 查询基本信息 ===");
// IMEI
debugLog("IMEI:");
sendATCommandGetResponse("AT+CGSN");
// IMSI
debugLog("IMSI:");
sendATCommandGetResponse("AT+CIMI");
// 信号质量
debugLog("信号质量:");
String csqResponse = sendATCommandGetResponse("AT+CSQ");
// 解析信号质量
int rssiStart = csqResponse.indexOf("+CSQ: ") + 6;
if (rssiStart > 5) {
int rssi = csqResponse.substring(rssiStart, csqResponse.indexOf(",", rssiStart)).toInt();
debugLog("RSSI值: " + String(rssi) + " (" + String(-113 + rssi * 2) + " dBm)");
if (rssi < 10) {
debugLog("警告: 信号质量较差,可能影响网络注册");
}
}
}
// 网络配置
bool configureNetwork(String apn) {
debugLog("=== 配置网络 (APN: " + apn + ") ===");
// 设置全功能模式
debugLog("设置全功能模式...");
if (!sendATCommand("AT+CFUN=1", 15000)) {
debugLog("设置全功能模式失败");
return false;
}
delay(3000);
// 查询当前运营商
debugLog("查询运营商:");
sendATCommandGetResponse("AT+COPS?", 5000);
// 设置网络选择为自动
debugLog("设置网络选择模式...");
sendATCommand("AT+COPS=0", 30000); // 自动选择网络,可能需要较长时间
// 配置APN
debugLog("配置APN: " + apn);
String apnCommand = "AT+CGDCONT=1,\"IP\",\"" + apn + "\"";
if (!sendATCommand(apnCommand)) {
debugLog("APN配置失败");
return false;
}
// 附着到GPRS网络
debugLog("附着到GPRS网络...");
sendATCommand("AT+CGATT=1", 10000);
return true;
}
// 检查网络注册状态
int checkRegistrationStatus() {
// 检查CS域注册
String creg = sendATCommandGetResponse("AT+CREG?");
// 检查PS域注册
String cgreg = sendATCommandGetResponse("AT+CGREG?");
// 检查EPS注册
String cereg = sendATCommandGetResponse("AT+CEREG?");
// 解析状态
int csStatus = parseRegStatus(creg, "+CREG:");
int psStatus = parseRegStatus(cgreg, "+CGREG:");
int epsStatus = parseRegStatus(cereg, "+CEREG:");
debugLog("注册状态 - CS:" + getStatusText(csStatus) +
" PS:" + getStatusText(psStatus) +
" EPS:" + getStatusText(epsStatus));
// 返回最好的注册状态
if (csStatus == 1 || psStatus == 1 || epsStatus == 1) return 1; // 已注册
if (csStatus == 5 || psStatus == 5 || epsStatus == 5) return 5; // 漫游注册
if (csStatus == 2 || psStatus == 2 || epsStatus == 2) return 2; // 正在搜索
if (csStatus == 3 || psStatus == 3 || epsStatus == 3) return 3; // 注册被拒绝
return 0; // 未知状态
}
// 解析注册状态
int parseRegStatus(String response, String prefix) {
int prefixPos = response.indexOf(prefix);
if (prefixPos < 0) return -1;
int commaPos = response.indexOf(",", prefixPos);
if (commaPos < 0) return -1;
int status = response.substring(commaPos + 1, commaPos + 2).toInt();
return status;
}
// 状态文本转换
String getStatusText(int status) {
switch (status) {
case 0: return "未搜索";
case 1: return "已注册";
case 2: return "搜索中";
case 3: return "被拒绝";
case 4: return "未知";
case 5: return "漫游";
default: return "错误";
}
}
// 网络注册测试主流程
bool testNetworkRegistration() {
debugLog("=== 开始网络注册测试 ===");
for (currentAPNIndex = 0; currentAPNIndex < APN_COUNT; currentAPNIndex++) {
String currentAPN = APN_LIST[currentAPNIndex];
debugLog("测试APN " + String(currentAPNIndex + 1) + "/" + String(APN_COUNT) + ": " + currentAPN);
// 配置网络
if (!configureNetwork(currentAPN)) {
debugLog("APN " + currentAPN + " 配置失败,尝试下一个");
continue;
}
// 等待网络注册
debugLog("等待网络注册 (最长3分钟)...");
unsigned long startTime = millis();
while (millis() - startTime < REGISTRATION_TIMEOUT) {
int status = checkRegistrationStatus();
if (status == 1 || status == 5) {
debugLog("✓ 网络注册成功! APN: " + currentAPN + " 状态: " + getStatusText(status));
// 验证网络连接
debugLog("验证网络连接...");
sendATCommandGetResponse("AT+CGPADDR=1");
return true;
} else if (status == 3) {
debugLog("✗ 网络注册被拒绝,APN可能不正确");
break; // 尝试下一个APN
}
debugLog("等待中... 状态: " + getStatusText(status));
delay(CHECK_INTERVAL);
}
debugLog("✗ APN " + currentAPN + " 注册超时");
}
debugLog("✗ 所有APN测试失败");
return false;
}
void setup() {
// 初始化串口
Serial.begin(115200);
while (!Serial && millis() < 5000) delay(100);
Serial.println("==========================================");
Serial.println("RAK5860 BG77 网络注册专项测试");
Serial.println("目标: 解决 +CEREG:0,2 网络注册问题");
Serial.println("==========================================");
testStartTime = millis();
// 1. 初始化模块
if (!initializeBG77()) {
Serial.println("✗ 模块初始化失败,测试终止");
while (1) delay(1000);
}
// 2. 基本配置
if (!basicConfiguration()) {
Serial.println("✗ 基本配置失败,测试终止");
while (1) delay(1000);
}
// 3. 查询基本信息
queryBasicInfo();
// 4. 网络注册测试
bool success = testNetworkRegistration();
// 测试结果
Serial.println("==========================================");
if (success) {
Serial.println("✓ 网络注册测试成功!");
Serial.println("成功APN: " + APN_LIST[currentAPNIndex]);
} else {
Serial.println("✗ 网络注册测试失败");
Serial.println("建议:");
Serial.println("1. 检查SIM卡是否支持数据业务");
Serial.println("2. 确认所在地区有足够的信号覆盖");
Serial.println("3. 联系运营商确认正确的APN设置");
Serial.println("4. 尝试在不同位置测试");
}
unsigned long testDuration = (millis() - testStartTime) / 1000;
Serial.println("测试耗时: " + String(testDuration) + " 秒");
Serial.println("==========================================");
}
void loop() {
// 如果注册成功,定期检查状态
static unsigned long lastCheck = 0;
if (millis() - lastCheck > 30000) { // 每30秒检查一次
debugLog("定期状态检查:");
checkRegistrationStatus();
// 查询信号质量
sendATCommandGetResponse("AT+CSQ");
lastCheck = millis();
}
// 处理用户输入的AT命令
if (Serial.available()) {
String userInput = Serial.readStringUntil('\n');
userInput.trim();
if (userInput.length() > 0) {
if (userInput.startsWith("AT")) {
// 直接转发AT命令
Serial1.println(userInput);
readBG77Response(5000);
} else if (userInput.equals("STATUS")) {
// 快速状态检查
checkRegistrationStatus();
sendATCommandGetResponse("AT+CSQ");
} else if (userInput.equals("RESTART")) {
// 重启测试
Serial.println("重启网络注册测试...");
testNetworkRegistration();
} else {
Serial.println("可用命令: STATUS, RESTART, 或任何AT命令");
}
}
}
delay(1000);
}