EC200S-CN 是移远通信最近推出的 LTE Cat 1 无线通信模块,支持最大下行速率 10Mbps 和最大上行速率 5Mbps,具有超高的性价比;同时在封装上兼容移远通信多网络制式 LTE Standard EC2x(EC25、EC21、EC20 R2.0、EC20 R2.1)和 EC200T/EG25-G/EG21-G 模块以及 UMTS/HSPA+ UC20/UC200T 模块,实现了 3G 网络与 4G 网络之间的无缝切换。EC200S-CN 还支持标准的 Mini PCIe 封装,以满足不同行业产品应用需求。
Quectel EC2x 模块具有嵌入式 TCP/IP堆栈,使主机可以通过 AT 命令直接上网。可以实现TCP客户端、UDP客户端、TCP服务器和UDP服务器。
测试AT指令功能是否正常,等待模块返回 OK。
AT
OK
查询 SIM 卡状态,返回 READY 则表示SIM卡正常,如果 20 秒后还无法识别 SIM 卡,重新启动模块。
AT+CPIN?
+CPIN: READY
OK
查询模组是否注册上GSM网络,如果 90秒后未能在 CS 上注册域名服务,重新启动模块。
如果返回 1 或 5 ,代表 CS 服务注册成功。
+CREG:0,1 表示已注册上本地网,+CREG:0,5表示注册上漫游网。
AT+CREG?
+CREG: 0,1
OK
查询模组是否注册上GPRS网络,+CGREG:0,1 表示已注册上本地网,+CGREG:0,5表示注册上漫游网。
AT+CGREG?
+CGREG: 0,1
OK
该命令可用于配置
AT+QICSGP=1,1,\"CMNET\",\"\",\"\",1
OK
在激活GPRS场景之前先关闭GPRS场景,确保连接正确
AT+QIDEACT=1
OK
激活移动场景
AT+QIACT=1
OK
该命令用于打开套接字服务。
AT+QIOPEN=1,0,\"TCP\",\"180.97.81.180\",53540,0,1
OK
+QIOPEN: 0,0
Buffer模式,Push模式,透传模式。通过参数
如果指定套接字服务的
RESET_N 引脚可用于使模块复位。拉低 RESET_N 引脚至少 300 ms 后释放可使模块复位。RESET_N
信号对干扰比较敏感,因此建议在模块接口板上的走线应尽量的短,且需包地处理。
/*********************************************************************
* INCLUDES
*/
#include "stdlib.h"
#include "string.h"
#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"
#include "board_ec200s.h"
uint8_t sendCmd(char *pCmd, char *pRes, uint32_t timeOut, uint8_t sendNum);
void clearBuffer(void);
void reset(void);
/*********************************************************************
* GLOBAL VARIABLES
*/
uint8_t g_usart2RecvFinish = 0; // 串口2接收标志串口接收完成标志
char g_ec200sBuf[1024] = {0}; // 接收缓存
uint32_t g_ec200sCnt = 0; // 接收计数
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief 初始化
@param 无
@return 1 - 成功;0 - 失败
*/
uint8_t EC200S_Init(void)
{
printf("EC200S_Init\r\n");
uint8_t result = 0;
uint8_t step = 0;
switch(step)
{
case 0:
if(sendCmd("AT\r\n","OK", 10, 5)) // 测试AT指令功能是否正常
{
step++;
}
else
{
printf("Err:AT\r\n");
reset();
break;
}
case 1:
if(sendCmd("AT+CPIN?\r\n","+CPIN: READY", 20, 2)) // 查询SIM卡是否正常,返回ready则表示SIM卡正常
{
step++;
}
else
{
printf("Err:AT+CPIN?\r\n"); // 20秒内,无法识别SIM状态,重启模块
reset();
break;
}
case 2:
if(sendCmd("AT+CREG?\r\n","+CREG: 0,1", 90, 2)) // 查询模组是否注册上GSM网络
{
step++;
}
else
{
printf("Err:AT+CREG?\r\n"); // 90秒内,没有注册上CS业务,重启模块
reset();
break;
}
case 3:
if(sendCmd("AT+CGREG?\r\n","+CGREG: 0,1", 60, 2)) // 查询模组是否注册上GPRS网络
{
step++;
}
else
{
printf("Err:AT+CGREG?\r\n"); // 60秒内,没有注册上PS业务
reset();
break;
}
case 4:
if(sendCmd("AT+QICSGP=1,1,\"CMNET\",\"\",\"\",1\r\n", "OK", 40, 3)) // 查询模组是否注册上GPRS网络
{
result = EC200S_NetConfig();
}
else
{
printf("Err:AT+QICSGP=1,1\r\n"); // 如果3次都没停止成功或超过40秒没有回应,则重启模块
reset();
break;
}
}
return result;
}
/**
@brief 网络配置
@param 无
@return 无
*/
void EC200S_GpioConfig(void)
{
GPIO_InitTypeDef gpioInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能GPIO
gpioInitStructure.GPIO_Pin = GPIO_Pin_8; // 选择要初始化的GPIOB引脚PB8
gpioInitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 设置引脚工作模式为通用推挽输出
gpioInitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置引脚输出最大速率为50MHz
GPIO_Init(GPIOB, &gpioInitStructure);
}
/**
@brief 网络配置
@param 无
@return 1 - 成功;0 - 失败
*/
uint8_t EC200S_NetConfig(void)
{
uint8_t result = 0;
if(sendCmd("AT+QIDEACT=1\r\n", "OK", 40, 1)) // 在激活GPRS场景之前先关闭GPRS场景,确保连接正确
{
if(sendCmd("AT+QIACT=1\r\n", "OK", 150, 1)) // 激活移动场景
{
EC200S_Connect();
}
else // 等待150秒后,没有响应重启模块
{
printf("Err:AT+QIACT=1\r\n"); // 重启模块
reset();
}
}
else // 等待40秒后,没有响应重启模块
{
printf("Err:AT+QIDEACT=1\r\n"); // 重启模块
reset();
}
}
/**
@brief 连接TCP服务器
@param 无
@return 无
*/
void EC200S_Connect(void)
{
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");
}
}
/**
@brief 发送数据到TCP服务器
@param pString -[in] 发送数据
@return 无
*/
void EC200S_Send(char *pString)
{
if(sendCmd("AT+QISEND=0\r\n", ">", 60, 1))
{
if(sendCmd("AT+QISEND=0,0\r\n", "OK", 5, 24)) // 2分钟后(每5秒查询一次,共24次)
{
/* 发送数据成功,对方收到数据 */
}
else
{
printf("Err:AT+QISEND=0\r\n");
if(sendCmd("AT+QICLOSE=0\r\n", "OK", 10, 1)) // TCP连接出现异常,关闭TCP连接
{
printf("AT+QICLOSE\r\n");
EC200S_Connect();
}
else
{
reset(); // 等待10秒,没有响应重启模块
}
}
}
else
{
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_ec200sBuf, "+QIURC: \"recv\",0,") != NULL) // 如果检索到关键词
{
memcpy(pRecvDataBuf, g_ec200sBuf, g_ec200sCnt);
recvDataLen = g_ec200sCnt;
}
clearBuffer();
}
return recvDataLen;
}
/*********************************************************************
* LOCAL FUNCTIONS
*/
/**
@brief 发送AT命令
@param pCmd -[in] 命令字符串
@param pRes -[in] 需要检测的返回命令字符串
@param timeOut -[in] 等待时间
@param sendNum -[in] 命令发送次数
@return 1 - 成功;0 - 失败
*/
uint8_t sendCmd(char *pCmd, char *pRes, 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_ec200sBuf, pRes) != NULL) // 如果检索到关键词
{
printf("%s", g_ec200sBuf);
return 1;
}
}
vTaskDelay(100); // 等待100毫秒
}
clearBuffer();
}
return 0;
}
/**
@brief 清空缓存
@param 无
@return 无
*/
void clearBuffer(void)
{
memset(g_ec200sBuf, 0, sizeof(g_ec200sBuf));
g_ec200sCnt = 0;
g_usart2RecvFinish = 0;
}
/**
@brief 重启模块
@param 无
@return 无
*/
void reset(void)
{
printf("reset\n");
GPIO_ResetBits(GPIOB, GPIO_Pin_8);
vTaskDelay(2000);
GPIO_SetBits(GPIOB, GPIO_Pin_8);
}
/****************************************************END OF FILE****************************************************/
#ifndef _BOARD_EC200S_H_
#define _BOARD_EC200S_H_
/*********************************************************************
* INCLUDES
*/
#include "stm32f10x.h"
/*********************************************************************
* GLOBAL VARIABLES
*/
extern uint8_t g_usart2RecvFinish; // 串口2接收标志串口接收完成标志
extern char g_ec200sBuf[1024]; // 接收缓存
extern uint32_t g_ec200sCnt; // 接收计数
/*********************************************************************
* API FUNCTIONS
*/
uint8_t EC200S_Init(void);
void EC200S_GpioConfig(void);
uint8_t EC200S_NetConfig(void);
void EC200S_Connect(void);
void EC200S_Send(char *pString);
uint32_t EC200S_Receive(char *pRecvDataBuf);
#endif /* _BOARD_EC200S_H_ */
EC200S_GpioConfig();
EC200S_Init();
while(1) // 任务都是一个无限循环,不能返回
{
EC200S_Send("TEST");
vTaskDelay(10000);
char recvDataBuf[256] = {0};
int recvDataLen = EC200S_Receive(recvDataBuf);
}
/**
@brief 串口2收发中断
@param 无
@return 无
*/
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) // 接收中断
{
g_usart2RecvFinish = 1; // 串口2接收标志
if(g_ec200sCnt >= sizeof(g_ec200sBuf))
{
g_ec200sCnt = 0; // 防止串口被刷爆
}
g_ec200sBuf[g_ec200sCnt++] = USART2->DR;
USART_ClearFlag(USART2, USART_FLAG_RXNE);
}
}