EC20/EC25 4G模块AT指令开发总结

文章目录

  • 一.EC25/20 4G模块简介
  • 二.AT指令总结
    • 1.通用AT指令
    • 2.建立TCP/UDP连接相关AT指令
  • 三.TCP传输数据流程
  • 四.UDP传输数据流程
  • 五.总结

一.EC25/20 4G模块简介

  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指令总结

1.通用AT指令

 AT:测试指令,返回OK。
 ATE0:关闭回显,返回OK。
 AT+CCLK?:获取网络时间,返回格式详见参考手册。(注意此处返回的时间是基站本地时间,可能需要自己转换成北京时间)
 AT+QCCID:获取SIM卡号。返回格式详见参考手册。
 AT+CSQ:获取信号强度,返回0-31,返回99为无信号。
 AT+QPOWD:模块关机。

2.建立TCP/UDP连接相关AT指令

 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指令开启)。

三.TCP传输数据流程

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;
}

四.UDP传输数据流程

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作为主流的传输协议,本文提供了详细的开发流程,可作为参考。

你可能感兴趣的:(无线通信)