EC25 是一系列带分集接收功能的 LTE-FDD/LTE-TDD/WCDMA/GSM 无线通信模块。
1.供电 :
VBAT 供电电压范围:3.3V~4.3V
典型供电电压:3.8V
2.网络协议特性:
支持TCP/UDP/PPP/FTP/FTPS/HTTP/HTTPS/NTP/PING/
QMI/NITZ/SMTP/SSL/MQTT/CMUX/SMTPS/MMS*/FILE*协议
支持 PAP (Password Authentication Protocol) 和 CHAP (Challenge Handshake Authentication Protocol)协议。
3.主串口:
用于 AT 命令传送和数据传输。
波特率最大为 921600bps,默认为 115200bps(可通过AT指令配置修改波特率)。
支持 RTS 和 CTS 硬件流控。
4.开关机与复位:
开机:可以通过拉低 PWRKEY 至少 500ms 使模块开机。
关机: 通过 PWRKEY 引脚控制模块关机。
发送 AT+QPOWD 命令关机。
复位:RESET_N 引脚可用于模块复位。拉低 RESET_N 引脚 150ms~460ms 后可使模块复位。
AT:测试指令,返回OK。
ATE0:关闭回显,返回OK。
AT+CCLK?:获取网络时间,返回格式详见参考手册。(注意此处返回的时间是基站本地时间,可能需要自己转换成北京时间)
AT+QCCID:获取SIM卡号。返回格式详见参考手册。
AT+CSQ:获取信号强度,返回0-31,返回99为无信号。
AT+QPOWD:模块关机。
AT+CPIN?:判断SIM状态是否正常,正常返回READY。
AT+CREG?:查询网络是否注册成功,成功返回OK。
AT+QICSGP=1,1,“MOBILE”,"","",1:配置TCP/IP环境,成功返回OK。
AT+QIACT=1:激活TCP/IP环境,成功返回OK。
AT+QIOPEN=1,0,“TCP”,“ip”,port,0,2:建立TCP连接(透传模式),其中ip和port要替换成实际要连接的网络值。连接成功返回CONNECT。(至此已将建立了TCP连接,可以直接透传发数据了)
AT+QIOPEN=1,2,“UDP SERVICE”,“127.0.0.1”,0,3030,1:创建UDP服务器。成功返回OK。(至此还未建立UDP连接,不可以发数据)
AT+QISEND=2,len,“ip”,port :UDP准备发送数据指令,此处发送数据长度len,目的ip地址和端口号port要根据实际给定,收到">"后将数据发送出去,发送成功收到SEND OK。
+++ :退出TCP透传模式(发送数据完成要退出透传)。
AT+QICLOSE=0/2 :关闭连接(此处的0/2是连接号,由之前的AT+QIOPEN指令开启)。
1.POWERKEY开机----->2.模块联网----->3.建立TCP连接----->4.TCP发送数据----->5.等待返回数据并处理----->6.模块关机(POWERKEY或AT指令)。
详细程序:
相关支持函数:
//串口1,printf 函数
//确保一次发送数据不超过USART1_MAX_SEND_LEN字节
void fg_printf(char* fmt,...)
{
u16 i=0;
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
// {
// 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));//清空缓存
}
//4G_MODULE发送命令后,检测接收到的应答
//str:期待的应答结果
//返回值:0,没有得到期待的应答结果
// 其他,期待应答结果的位置(str的位置)
u8* fg_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;
}
//向4G_MODULE发送指定数据
//data:发送的数据(不需要添加回车了)
//ack:期待的应答结果,如果为空,则表示不需要等待应答
//waittime:等待时间(单位:100ms)
//返回值:0,发送成功(得到了期待的应答结果)
// 1,发送失败
u8 fg_send_cmd(u8 *data,u8 *ack,u16 waittime)
{
waittime=waittime*100;
fg_printf("%s\r\n",data); //需要发送的是命令
if(ack&&waittime) //需要等待应答
{
while(--waittime) //等待倒计时
{
delay_ms(1);
if(USART1_IDLE_FLAG) //接收到期待的应答结果
{
if(fg_send_check_cmd(ack))
{
printf("%s ack: %s\r\n",data,(u8*)ack);
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
}
//1.4G开机
void FourG_Power_On(void)
{
POWERKEY(1);
delay_ms(600);
POWERKEY(0);
}
//2.模块联网
/**
* @brief 4G模块联网
*
* @param void
*
* @return 0:连接成功
* 1:连接失败
*/
u8 FourG_Connect_To_Internet(void)
{
u8 i=0;
for(i=0;i<3;i++)
if(fg_send_cmd((u8 *)"AT",(u8 *)"OK",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(fg_send_cmd((u8 *)"ATE0",(u8 *)"OK",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(fg_send_cmd((u8 *)"AT+CPIN?",(u8 *)"READY",10)==0)break;
if(i==3)
{
printf("SIM卡状态不正常...\r\n\r\n");
return 1; //失败,返回1
}
else printf("SIM卡状态正常...\r\n\r\n");
for(i=0;i<3;i++)
if(fg_send_cmd((u8 *)"AT+CREG?",(u8 *)"OK",10)==0)break;
if(i==3)
{
printf("CS网络注册失败...\r\n\r\n");
return 1; //失败,返回1
}
else printf("CS网络注册成功...\r\n\r\n");
return 0;
}
//3.建立TCP连接
/**
* @brief 4G模块建立TCP连接
*
* @param ip:需要连接的ip地址
* port:需要连接的端口
*
* @return 0:建立TCP连接成功
* 1:建立TCP连接失败
*/
u8 FG_TCP_Connect(const u8* ip,const u8* port)
{
u8 i=0;
char p[50]={0};
for(i=0;i<3;i++)
if(fg_send_cmd((u8 *)"AT+QICSGP=1,1,\"MOBILE\",\"\",\"\",1",(u8 *)"OK",10)==0)break;
if(i==3)
{
printf("配置TCP/IP环境失败...\r\n\r\n");
return 1; //失败,返回1
}
else printf("配置TCP/IP环境成功...\r\n\r\n");
for(i=0;i<3;i++)
if(fg_send_cmd((u8 *)"AT+QIACT=1",(u8 *)"OK",10)==0)break;
if(i==3)
{
printf("激活TCP/IP环境失败...\r\n\r\n");
return 1; //失败,返回1
}
else printf("激活TCP/IP环境成功...\r\n\r\n");
sprintf((char*)p,"AT+QIOPEN=1,0,\"TCP\",\"%s\",%s,0,2",ip,port);
for(i=0;i<3;i++)
if(fg_send_cmd((u8 *)p,(u8 *)"CONNECT",10)==0)break;
if(i==3)
{
printf("设置TCP透传模式失败...\r\n\r\n");
return 1; //失败,返回1
}
else printf("设置TCP透传模式成功...\r\n\r\n");
return 0; //成功,返回0
}
//4.TCP发送数据
/**
* @brief TCP发送数据
*
* @param data:发送的数据
* len:发送的数据长度
*
* @return void
*/
void FG_TCP_Send_Data(u8* data,u16 len)
{
/*采用DMA方式发送数据*/
HexArrayToString(data,(char*)USART1_TX_BUF,len); //先将原始数据转成字符串
HAL_USART1_DMA_TX(&USART1TxDMA_Handler,DMA_FLAG_TC2,&huart1,USART1_TX_BUF,2*len);//使用DMA发送数据
memset(USART1_TX_BUF,0,sizeof(USART1_TX_BUF)); //清空缓存
}
//5.等待返回数据并处理(部分代码)
if(USART1_IDLE_FLAG) //串口1接收数据完毕,与NB模块通信
{
for(i=0;i<USART1_RX_COUNT;i++) //打印出接收到的数据
printf("%x ",USART1_RX_BUF[i]);
printf("\r\n");
memset(USART1_RX_BUF,0,sizeof(USART1_RX_BUF)); //清空缓存,以备下一次使用
USART1_RX_COUNT=0; //将接受字节数清零
USART1_IDLE_FLAG=0; //空闲中断标志复位
}
//6.模块关机
//4G关机
void FourG_Power_Off(void)
{
POWERKEY(1);
delay_ms(600);
POWERKEY(0);
// fg_printf("AT+QPOWD\r\n"); //发送关机指令
}
EC20/25 4G模块的默认串口波特率是115200,有时需要修改波特率,函数如下:
/**
* @brief FG模块设置波特率
*
* @param void
*
* @return 0:设置成功
* 1:设置失败
*/
u8 FourG_SET_Bund(void)
{
u8 i=0;
for(i=0;i<3;i++)
if(fg_send_cmd((u8 *)"AT",(u8 *)"OK",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(fg_send_cmd((u8 *)"AT+IPR=9600;&W",(u8 *)"OK",50)==0)break; //设置波特率为9600并永久保存在模块中,此处波特率可根据需要修改
if(i==3)
{
printf("设置9600波特率失败...\r\n\r\n");
return 1; //失败,返回1
}
else printf("设置9600波特率成功...\r\n\r\n");
return 0;
}
1.POWERKEY开机----->2.模块联网----->3.建立UDP连接----->4.UDP发送数据----->5.等待返回数据并处理----->6.模块关机(POWERKEY或AT指令)。
详细程序:
//相关支持函数:同上TCP
//1.4G开机:同上TCP
//2.模块联网:同上TCP
//3.建立UDP连接
/**
* @brief 4G建立UDP连接
*
* @param ip:需要连接的ip地址
* port:需要连接的端口
* socket:连接成功后返回创建的socket值
*
* @return 0:UDP连接成功
* 1:UDP连接失败
*/
u8 FG_UDP_Connect(void)
{
u8 i=0;
for(i=0;i<3;i++)
if(fg_send_cmd((u8 *)"AT+QICSGP=1,1,\"MOBILE\",\"\",\"\",1",(u8 *)"OK",10)==0)break;
if(i==3)
{
printf("配置TCP/IP环境失败...\r\n\r\n");
return 1; //失败,返回1
}
else printf("配置TCP/IP环境成功...\r\n\r\n");
for(i=0;i<3;i++)
if(fg_send_cmd((u8 *)"AT+QIACT=1",(u8 *)"OK",10)==0)break;
if(i==3)
{
printf("激活TCP/IP环境失败...\r\n\r\n");
return 1; //失败,返回1
}
else printf("激活TCP/IP环境成功...\r\n\r\n");
for(i=0;i<3;i++)
if(fg_send_cmd((u8 *)"AT+QIOPEN=1,2,\"UDP SERVICE\",\"127.0.0.1\",0,3030,1",(u8 *)"OK",10)==0)break;
if(i==3)
{
printf("设置UDP透传模式失败...\r\n\r\n");
return 1; //失败,返回1
}
else printf("设置UDP透传模式成功...\r\n\r\n");
return 0; //成功,返回0
}
//4.UDP发送数据
/**
* @brief UDP发送数据
*
* @param ip:ip地址
* port:端口号
* data:发送的数据
* len:发送的数据长度
*
* @return 0:UDP发送成功
* 1:UDP发送失败
*/
u8 FG_UDP_Send_Data(const u8* ip,const u8* port,u8* data,u16 len)
{
u8 i=0;
u16 waittime=1000;
char p[50]={0};
sprintf((char*)p,"AT+QISEND=2,%d,\"%s\",%s",2*len,ip,port);
for(i=0;i<3;i++)
if(fg_send_cmd((u8 *)p,(u8 *)">",10)==0)break;
if(i==3)
{
printf("没有收到>发送数据失败...\r\n\r\n");
return 1; //失败,返回1
}
else printf("确认收到>开始发送数据....\r\n\r\n");
/*采用DMA方式发送数据*/
HexArrayToString(data,(char*)USART1_TX_BUF,len); //先将原始数据转成字符串
HAL_USART1_DMA_TX(&USART1TxDMA_Handler,DMA_FLAG_TC2,&huart1,USART1_TX_BUF,2*len);//使用DMA发送数据
memset(USART1_TX_BUF,0,sizeof(USART1_TX_BUF)); //清空缓存
while(--waittime) //等待倒计时
{
delay_ms(1);
if(USART1_IDLE_FLAG) //接收到期待的应答结果
{
if(fg_send_check_cmd((u8 *)"SEND OK"))
{
printf("ack: %s\r\n",(u8*)"SEND OK");
memset(USART1_RX_BUF,0,sizeof(USART1_RX_BUF));//清空USART1缓存
USART1_IDLE_FLAG=0;
USART1_RX_COUNT=0; //串口1接受数据清零
return 0; //ack正确,返回0
}
memset(USART1_RX_BUF,0,sizeof(USART1_RX_BUF));//清空USART1缓存
USART1_IDLE_FLAG=0;
USART1_RX_COUNT=0; //串口1接受数据清零
}
}
return 1; //ack错误,返回1
}
//5.等待返回数据并处理,由于UDP不是透传模式,因此需要最接收到的数据进行处理,具体可自行处理
if(USART1_IDLE_FLAG) //串口1接收数据完毕,与NB模块通信
{
received_length=0;
printf("接收到的UDP数据是:%s\r\n",USART1_RX_BUF);
/*判断是否有来自服务器的数据*/
str1=fg_send_check_cmd(portnum); //判断接受到的数据是否有+NSONMI:
str2=str1+portlen+2; //获得数据区域的首地址
while(str2!=&USART1_RX_BUF[USART1_RX_COUNT-2]) //未到倒数第二位
{
str2++; //接收缓存区向下进一个位置
received_length++; //接收字节数加一
if(received_length>180)break; //如果接收数据大于180,则判断接收错误,退出while()循环
}
printf("received_length=%d\r\n",received_length);
memmove(USART1_RX_BUF,str1+portlen+2,received_length);
USART1_RX_COUNT=received_length;
USART1_RX_BUF[USART1_RX_COUNT]=0;
for(i=0;i<USART1_RX_COUNT;i++)
printf("%x ",USART1_RX_BUF[i]);
printf("\r\n");
}
//6.模块关机:同上TCP
4G通信作为如今的主流通信方式有着十分广泛的用途,移远公司的EC20/25作为主流的4G通信模块有很广泛的使用,另外此模块还具有其他很多强大的功能,如低功耗模式,GNSS定位功能,可自己开发。TCP/UDP作为主流的传输协议,本文提供了详细的开发流程,可作为参考。