4. SIM卡检测与初始化
任务说明
本案例面向LTE Cat1/Cat4模块(以移远EC200U/EC200S系列为例),实现以下目标:检测SIM卡是否存在、读取ICCID与IMSI、完成SIM卡初始化设置。最终通过串口日志输出检测结果与卡信息。
硬件连接与前置条件
- 模块SIM卡座已正确安装,支持1.8V/3.0V SIM卡
- 模块通过USB转串口连接PC,供电正常
- 使用AT指令通过串口调试工具发送命令
SIM卡检测与初始化流程
SIM卡操作遵循以下状态顺序:上电后模块自动检测SIM卡热插拔状态,通过AT+CPIN?查询PIN码状态确认卡是否就绪;使用AT+CIMI读取IMSI;使用AT+ICCID读取ICCID。初始化设置包括设置SIM卡为默认USIM模式、配置PIN码验证为关闭(若需要)、设置SIM卡热插拔检测功能。
AT指令实现
通过串口发送以下AT指令序列完成SIM卡检测与初始化。每条指令后需等待模块返回结果,以OK或具体数据作为成功标志。
// 步骤1: 查询SIM卡PIN码状态(检测卡是否存在)
AT+CPIN?
// 预期返回: +CPIN: READY (表示卡已就绪)
// 若返回 +CME ERROR: SIM not inserted 则卡未插入
// 步骤2: 读取IMSI(国际移动用户识别码)
AT+CIMI
// 预期返回: 460011234567890 (15位数字)
// 步骤3: 读取ICCID(集成电路卡识别码)
AT+ICCID
// 预期返回: +ICCID: 89860123456789012345 (20位数字)
// 步骤4: 开启SIM卡热插拔检测(初始化设置)
AT+QSIMSTAT=1
// 预期返回: OK
// 步骤5: 设置PIN码验证关闭(可选,根据需求)
AT+CPIN=1234 // 若卡启用PIN码,需输入正确PIN
// 预期返回: OK
// 步骤6: 查询SIM卡状态确认初始化完成
AT+CPIN?
// 预期返回: +CPIN: READY
嵌入式C代码实现(MCU侧)
以下代码展示MCU通过UART与模块交互,完成SIM卡检测与信息读取的完整逻辑。代码使用标准库函数,适用于STM32等常见MCU平台。
/* sim_card_check.c - SIM卡检测与初始化 */
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
// UART发送与接收函数声明(需根据平台实现)
extern void UART_SendString(const char* str);
extern void UART_ReceiveLine(char* buffer, uint16_t maxLen, uint32_t timeoutMs);
// 解析AT指令响应
bool CheckResponse(const char* response, const char* expected) {
return (strstr(response, expected) != NULL);
}
// 读取SIM卡ICCID
bool GetICCID(char* iccid, uint8_t len) {
char rxBuffer[128] = {0};
UART_SendString("AT+ICCID\r\n");
UART_ReceiveLine(rxBuffer, sizeof(rxBuffer), 1000);
// 解析响应格式: +ICCID: 89860123456789012345
char* ptr = strstr(rxBuffer, "+ICCID:");
if (ptr != NULL) {
ptr += 7; // 跳过"+ICCID: "
while (*ptr == ' ') ptr++;
uint8_t i = 0;
while (*ptr >= '0' && *ptr <= '9' && i < len - 1) {
iccid[i++] = *ptr++;
}
iccid[i] = '\0';
return (i == 20); // ICCID固定20位
}
return false;
}
// 读取SIM卡IMSI
bool GetIMSI(char* imsi, uint8_t len) {
char rxBuffer[64] = {0};
UART_SendString("AT+CIMI\r\n");
UART_ReceiveLine(rxBuffer, sizeof(rxBuffer), 1000);
// 响应直接为IMSI号码(15位数字)
uint8_t i = 0;
while (rxBuffer[i] >= '0' && rxBuffer[i] <= '9' && i < len - 1) {
imsi[i] = rxBuffer[i];
i++;
}
imsi[i] = '\0';
return (i == 15); // IMSI固定15位
}
// SIM卡初始化主函数
bool SIMCard_Init(void) {
char rxBuffer[64] = {0};
// 1. 检测SIM卡是否存在
UART_SendString("AT+CPIN?\r\n");
UART_ReceiveLine(rxBuffer, sizeof(rxBuffer), 1000);
if (!CheckResponse(rxBuffer, "+CPIN: READY")) {
printf("[ERROR] SIM卡未就绪或未插入\r\n");
return false;
}
printf("[INFO] SIM卡检测成功,状态READY\r\n");
// 2. 开启热插拔检测(初始化设置)
UART_SendString("AT+QSIMSTAT=1\r\n");
UART_ReceiveLine(rxBuffer, sizeof(rxBuffer), 1000);
if (!CheckResponse(rxBuffer, "OK")) {
printf("[WARN] 热插拔检测设置失败\r\n");
} else {
printf("[INFO] 热插拔检测已开启\r\n");
}
// 3. 读取ICCID
char iccid[21] = {0};
if (GetICCID(iccid, sizeof(iccid))) {
printf("[INFO] ICCID: %s\r\n", iccid);
} else {
printf("[ERROR] ICCID读取失败\r\n");
return false;
}
// 4. 读取IMSI
char imsi[16] = {0};
if (GetIMSI(imsi, sizeof(imsi))) {
printf("[INFO] IMSI: %s\r\n", imsi);
} else {
printf("[ERROR] IMSI读取失败\r\n");
return false;
}
printf("[INFO] SIM卡初始化完成\r\n");
return true;
}
// 主函数调用示例
int main(void) {
// 系统初始化(UART、GPIO等)
SystemInit();
// 执行SIM卡检测与初始化
if (SIMCard_Init()) {
printf("[OK] SIM卡初始化成功,可以执行网络注册\r\n");
} else {
printf("[FAIL] SIM卡初始化失败,请检查SIM卡\r\n");
}
while (1) {
// 主循环
}
}
验证方法与判定标准
验证步骤:
- 将SIM卡正确插入模块卡座,连接串口调试工具
- 模块上电,等待3秒启动完成
- 依次发送上述AT指令,观察返回结果
- 运行嵌入式代码,观察串口日志输出
判定标准:
AT+CPIN?返回+CPIN: READY,表明SIM卡存在且未锁定AT+ICCID返回20位数字ICCID,且与卡面印刷号码一致AT+CIMI返回15位数字IMSI,以460开头(中国运营商)- 嵌入式代码串口输出包含
[OK] SIM卡初始化成功字样 - 拔出SIM卡后重新检测,
AT+CPIN?应返回错误提示,验证检测功能有效
预期输出示例(基于代码逻辑):
[INFO] SIM卡检测成功,状态READY
[INFO] 热插拔检测已开启
[INFO] ICCID: 89860123456789012345
[INFO] IMSI: 460011234567890
[INFO] SIM卡初始化完成
[OK] SIM卡初始化成功,可以执行网络注册
以上输出为代码逻辑直接推出的确定性结果,实际运行时ICCID和IMSI数值取决于插入的SIM卡。