基于FreeRTOS与MQTT的物联网技术应用系列——步进电机控制(五)MQTT的移植和步进电机控制的实现

本文介绍了如何在FreeRTOS系统中移植MQTT协议并实现步进电机控制。首先,详细讲解了MQTT协议的移植过程,包括源码添加、连接处理等步骤,并提供了测试验证的方法。接着,文章描述了步进电机的控制,包括驱动器的接线、设置和硬件定时器的使用。最后,展示了初步的控制效果,为后续的PC或移动端控制应用打下基础。
摘要由CSDN通过智能技术生成

本文在前一篇的基础上进行MQTT的移植,并实现对步进电机驱动器的控制。

分两步完成:
1、移植MQTT协议栈,并进行验证;
2、对步进电机进行控制。

一,移植MQTT协议

参考实现:https://github.com/baoshi/ESP-RTOS-Paho/tree/63c2c74dfe978f215b3bb05f7e1258454908c4fb

以前一篇文章完成的代码为基础,在工程目录下的APP文件夹中新建一个文件夹命名为MQTTClient,
把paho.mqtt.embedded-c源码包中的
paho.mqtt.embedded-c\MQTTPacket\src下的:


    MQTTConnect.h
    MQTTConnectClient.c
    MQTTDeserializePublish.c
    MQTTFormat.h
    MQTTPacket.c
    MQTTPacket.h
    MQTTPublish.h
    MQTTSerializePublish.c
    MQTTSubscribe.h
    MQTTSubscribeClient.c
    MQTTUnsubscribe.h
    MQTTUnsubscribeClient.c
    StackTrace.h

拷贝到MQTTClient文件夹中。
接下来,就是实现两个层面的连接处理:
1、tcp/ip建立连接,或由socket连接完成。
这部分放在

    MQTTFreeRTOSImpl.c
    MQTTFreeRTOSImpl.h

2、MQTT连接。
这部分放在:

    MQTTClient.c
    MQTTClient.h

MQTTFreeRTOSImpl.h的代码如下:

#ifndef MQTTFREERTOSIMPL_H
#define MQTTFREERTOSIMPL_H

#include "FreeRTOS.h"
#include "portmacro.h"

typedef struct Timer Timer;

struct Timer
{
    portTickType end_time;
};

typedef struct Network Network;

struct Network
{
    int my_socket;
    int (*mqttread) (Network*, unsigned char*, int, int);
    int (*mqttwrite) (Network*, unsigned char*, int, int);
};

char expired(Timer*);
void countdown_ms(Timer*, unsigned int);
void countdown(Timer*, unsigned int);
int left_ms(Timer*);

void InitTimer(Timer*);

int FreeRTOS_MQTT_read(Network*, unsigned char*, int, int);
int FreeRTOS_MQTT_write(Network*, unsigned char*, int, int);
void FreeRTOS_MQTT_disconnect(Network*);

void NewNetwork(Network* n);
int ConnectNetwork(Network* n, const char* host, int port);
int DisconnectNetwork(Network* n);


#endif /* MQTTFREERTOSIMPL_H */
MQTTFreeRTOSImpl.c的代码如下:


/*
²Î¿¼https://github.com/baoshi/ESP-RTOS-Paho/tree/63c2c74dfe978f215b3bb05f7e1258454908c4fb
*/

#include <string.h>  
#include "FreeRTOS.h"
#include "portmacro.h"
#include "lwip/sockets.h"
#include "lwip/inet.h"
#include "lwip/netdb.h"
#include "lwip/sys.h"

#include "MQTTFreeRTOSImpl.h"

#define _DEBUG
#include "dprintf.h"

char  expired(Timer* timer)
{
    portTickType now = xTaskGetTickCount();
    int32_t left = timer->end_time - now;
    return (left < 0);
}


void  countdown_ms(Timer* timer, unsigned int timeout)
{
    portTickType now = xTaskGetTickCount();
    timer->end_time = now + timeout / portTICK_RATE_MS;
}


void  countdown(Timer* timer, unsigned int timeout)
{
    countdown_ms(timer, timeout);
}


int  left_ms(Timer* timer)
{
    portTickType now = xTaskGetTickCount();
    int32_t left = timer->end_time - now;
    return (left < 0) ? 0 : left / portTICK_RATE_MS;
}


void  InitTimer(Timer* timer)
{
    timer->end_time = 0;
}

#include "task.h"
#include "timers.h"

__asm void _nop(void)
{   
    nop     
}
void delay(int i)
{
    for(;i>0;i--)
        _nop();
}

int  FreeRTOS_MQTT_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
{
    TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
    TimeOut_t xTimeOut;
    int recvLen = 0;

    vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
    do
    {
        int rc = 0;
        lwip_setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, &xTicksToWait, sizeof(TickType_t));
        rc = recv(n->my_socket, buffer + recvLen, len - recvLen, 0);
        //dprintf("rc=%d\n",rc);
        delay(50);//must delay enough,otherwise,it will be  blocked
        if (rc >= 0)
            recvLen += rc;  
        else if (rc <0)
        {   
            recvLen = rc;
            break;
        }
    } while (recvLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);

    return recvLen;
}


int  FreeRTOS_MQTT_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
{
    TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
    TimeOut_t xTimeOut;
    int sentLen = 0;

    vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
    do
    {
        int rc = 0;

        lwip_setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, &xTicksToWait, sizeof(xTicksToWait));
        rc = send(n->my_socket, buffer + sentLen, len - sentLen, 0);
        if (rc > 0)
            sentLen += rc;
        else if (rc < 0)
        {
            sentLen = rc;
            break;
        }
    } while (sentLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);

    return sentLen;
}



void  NewNetwork(Network* n)
{
    n->my_socket = -1;
    n->mqttread = FreeRTOS_MQTT_read;
    n->mqttwrite = FreeRTOS_MQTT_write;
}


int  host2addr(const char *hostname , struct in_addr *in)
{
    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_in *h;
    int rv;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    rv = getaddrinfo(hostname, 0 , &hints , &servinfo);
    if (rv != 0)
    {
        return rv;
    }

    // loop through all the results and get the first resolve
    for (p = servinfo; p != 0; p = p->ai_next)
    {
        h = (struct sockaddr_in *)p->ai_addr;
        in->s_addr = h->sin_addr.s_addr;
    }
    freeaddrinfo(servinfo); // all done with this structure
    return 0;
}


int  ConnectNetwork(Network* n, const char* host, int port)
{
    struct sockaddr_in addr;
    int ret;

    if (host2addr(host, &(addr.sin_addr)) != 0)
    {
        return -1;
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);

    n->my_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if( n->my_socket < 0 )
    {
        // error
        return -1;
    }
    ret = connect(n->my_socket, ( struct sockaddr *)&addr, sizeof(struct sockaddr_in));
    if( ret < 0 )
    {
        // error
        lwip_close(n->my_socket);
        return ret;
    }

    return ret;
}


int  DisconnectNetwork(Network* n)
{
    lwip_close(n->my_socket);
    n->my_socket = -1;
    return 0;
}

MQTTClient.h代码如下:

/*******************************************************************************
 * Copyright (c) 2014 IBM Corp.
 *
 * All rights reserved. This program and t
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值