嵌入式开发|基于STM32+移远EC200S(Cat.1 4G模组)AT指令实现多路MQTT和TCP同时连接

近期有小伙伴请求帮忙封装一下移远EC200s(cat.1)模组 AT指令驱动,要求同时实现tcp和mqtt连接通信,可以断线自动重连。

前言

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 封装,以满足不同行业产品应用需求。

EC200s 模块具有嵌入式 TCP/IP堆栈,使主机可以通过 AT 命令直接上网。可以实现TCP客户端、UDP客户端、MQTT客户端。

本次封装驱动直接采用AT指令实现MQTT连接,不在单独移植mqtt代码。这样可以节省ram空间。

硬件准备

  • MCU: STM32L07
  • 模组:移远EC200s
  • IDE:Keil MDK

设计思想

  • 1.EC200s驱动采用状态机
  • 2.数据缓冲区采用FreeRTOS的heap4
  • 3.程序框架:cola os

功能要求

  • 同时建立1路mqtt连接和4路tcp连接
  • 支持断线自动重连

代码设计

头文件实现

  • 1.ec200s初始化
  • 2.TCP数据发送
#define SOCKET_MAX_NUM         0x05//
#define MQTT_MAX_SUBTOPIC_NUM  0x01//
typedef enum conncet_method
{
    CONNECT_TCP = 0x00,
    CONNECT_UDP,
    CONNECT_MQTT,
}conncet_method;
struct ec200s_client
{
    struct       connect_unit unit[SOCKET_MAX_NUM];
    callback     connected;
    callback     disconnected;
    datacallback databack;
    callback     connerror;
};
//ec200sc初始化
int ec200c_init(struct ec200s_client * c);
//TCP数据发送
int ec200s_send_data(uint8_t *in,int len,uint8_t chn,uint8_t type);
//mqtt数据发送
int ec200s_mqtt_send_data(char topic[],uint8_t qos,uint8_t *in,int len,uint8_t chn);

源文件实现

int ec200c_init(struct ec200s_client * c)
{
    client = c;
    dev_init();
    cola_timer_create(&machine_timer,master_state_machine_timer_handle);
    cola_task_create(&machine_task,master_loop);
    master_state_machine_change(STATE_HAL_POWER);
    master_state_machine.state_cnt = 0;
    machine_task.isBusy            = TASK_BUSY;
    int i;
    for(i=0;i<SOCKET_MAX_NUM;i++)
    {
        master_state_machine.alive_timer[i].usr = (void *)i;
        cola_timer_create(&master_state_machine.alive_timer[i],alive_timer_cb);
        con_mag[i].idx   = i;
        con_mag[i].state = STATE_DISCONNECTED;
        con_mag[i].reconnect = 1;
    }
    cola_timer_create(&reconn_timer,reconn_timer_cb);
}

int ec200s_send_data(uint8_t *in,int len,uint8_t chn,uint8_t type)
{
    struct ec200s_data *ec= (struct ec200s_data *)g_frame_buf ;
    ec->len  = len;
    ec->chn  = chn;
    memcpy(ec->data,in,len);
    return cola_mem_write(&ec200_tx,(uint8_t *)ec,len+sizeof(struct ec200s_data)-1, type);
}

int ec200s_mqtt_send_data(char topic[],uint8_t qos,uint8_t *in,int len,uint8_t chn)
{
    struct ec200s_mqtt_data *ec= (struct ec200s_mqtt_data *)g_frame_buf ;
    ec->len  = len;
    ec->chn  = chn;
    ec->qos  = qos;
    ec->topic = (uint32_t)&topic[0];
    memcpy(ec->data,in,len);
    os_log("ec->len = %d,%d,%d,%d\r\n",len,chn,qos,ec->topic);
    return cola_mem_write(&ec200_tx,(uint8_t *)ec,len+sizeof(struct ec200s_mqtt_data)-1, DATA_MQTT);
}

程序应用

char usr_topic[]  = "substopic";
char usr_topic2[] = "substopic2";
char pub_topic[]  = "pubtopic";
char pub_data[]   = "0987654321";

static uint8_t link      = 0;
static uint32_t link_cnt = 0;
static uint32_t  eror      = 0;
char pubdata[128] = {0};
void mqtt_pub_cb(void *arg,uint32_t event)
{
    if(link == 0)
        return ;
    link_cnt++;

    sprintf(pubdata,"mqtt publish count:%d,error:%d\r\n",link_cnt,eror);
    ec200s_mqtt_send_data(pub_topic,0, (uint8_t *)pubdata, strlen(pubdata), 0);
}

static uint8_t index = 0;
void test_cb(void *args,uint32_t event)
{

    uint8_t send[50] = {0};
    int i,ret;
    for(i=0;i<sizeof(send);i++)
    {
        send[i] = index+0x30;
    }
   ret = ec200s_send_data(send,sizeof(send) ,1,1);
   os_log("tcp send=%d,%d\r\n",sizeof(send),ret);
}

int net_connect_cb(void *args)
{
    struct connect_msg * msg = (struct connect_msg *)args;
    os_log("[net] tcp:%d connected \r\n",msg->idx);
    if(msg->idx == 1)
    {
        cola_timer_start(&test_timer,TIMER_ALWAYS,300000);
        
    }
    
    if(msg->idx == 0)
    {
        link = 1;
        
    }
    return 0;
}
int net_disconnect_cb(void *args)
{
    struct connect_msg * msg = (struct connect_msg *)args;
    os_log("[net] tcp:%d disconnected \r\n",msg->idx);
    cola_timer_stop(&test_timer);
    if(msg->idx == 0)
    {
        link = 0;
        link_cnt=0;
        eror ++;
    }
    return 1;

}
void net_data_cb(void *args, const char* topic, uint32_t topic_len,  char *data, uint32_t lengh)
{
    struct connect_msg * msg = (struct connect_msg *)args;
    data[lengh] = 0;
    os_log("[net] tcp:%d recv :%d,%s \r\n",msg->idx,lengh,data);
   
}


static struct ec200s_client net_client= {0} ;

static char *tcp_url = "39.105.215.75";
static uint16_t tcp_port1 = 8019;
static uint16_t tcp_port2 = 8029;
static uint16_t tcp_port3 = 8039;
static uint16_t tcp_port4= 8049;
static uint16_t tcp_port5= 8059;

static char * mqtt_url   = "test.jmqtt.io";
static uint16_t mqtt_port= 1883;

void mqtt_client_init(void)
{
    net_client.unit[0].url    = mqtt_url;
    net_client.unit[0].port   = mqtt_port;
    net_client.unit[0].method = CONNECT_MQTT;
    net_client.unit[0].keepalive = 10;
    net_client.unit[0].password  = "12345678";
    net_client.unit[0].username  = "mqttsa";
    net_client.unit[0].clientID  = "mqtt";
    net_client.unit[0].subtopic[0].topic  = "pubtopic678";
    net_client.unit[0].subtopic[0].qos = 0;
    net_client.unit[0].timeout   = 60;
    net_client.unit[0].willFlag  = 0;
    net_client.unit[0].will_message = "delat";
    net_client.unit[0].will_qos    = 0;
    net_client.unit[0].will_retained = 0;
    net_client.unit[0].will_topicname ="pubtopic678";
    
    net_client.unit[1].url = tcp_url;
    net_client.unit[1].port = tcp_port2;
    net_client.unit[1].method = CONNECT_TCP;
    net_client.unit[1].keepalive = 20;
    
    net_client.unit[2].url = tcp_url;
    net_client.unit[2].port = tcp_port3;
    net_client.unit[2].method = CONNECT_TCP;
    net_client.unit[2].keepalive = 20;
    
    net_client.connected = net_connect_cb;
    net_client.databack  = net_data_cb;
    net_client.disconnected = net_disconnect_cb;
    
    cola_timer_create(&test_timer,test_cb);
    cola_timer_create(&mqtt_timer,mqtt_pub_cb);
    cola_timer_start(&mqtt_timer,TIMER_ALWAYS,300000);
      
}

结论

由于代码是小伙伴定制,暂不方便开放全部代码,敬请谅解!
有问题可私信。

  • 5
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值