IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> pahoMQTT移植 -> 正文阅读

[嵌入式]pahoMQTT移植

MQTT移植

一、移植平台:
pahoMQTT,stm32f103,Keil5,要想使用官方封装好MQTT函数 MQTTClient.h ,做如下移植
二、移植过程
1.将在MQTT三个文件中,如下图
在这里插入图片描述
找到如下MQTT文件(下图),加入到工程中。
在这里插入图片描述
2.打开 MQTTClient.h 头文件,在其中定义如下程序(下图),定时器接口,网络接口,定时器的5个函数,如果已有,屏蔽已有的。
在这里插入图片描述

#define int_ValMax 0xffffffff//int stm32 32位
typedef struct Timer Timer;//定时器接口 对外
struct Timer {
unsigned int StartVal;//定时初值
unsigned int end_time;//定时时间
};

typedef struct Network Network;//网络接口 对外
struct Network
{
int my_socket;//当前连接的TCP socket号
//参数要求(c->ipstack, &i, 1, timeout) 返回读到的数据长度
int (mqttread) (Network ipstack, unsigned char* R_buffer, int R_buffer_Lenth, int timeoutMS);//对服务器读 函数需要自己实现
int (mqttwrite) (Network, unsigned char*, int, int);//对服务器写 参数同上 返回写入数据长度
void (disconnect) (Network);//断开TCP连接
};

/* The Timer structure must be defined in the platform specific header,//下面5个函数需要自己实现

  • and have the following functions to operate on it. /
    extern void TimerInit(Timer
    );//定时器初始化
    extern char TimerIsExpired(Timer*);//返回定时器是否超时
    extern void TimerCountdownMS(Timer*, unsigned int);//设置定时时间 单位ms
    extern void TimerCountdown(Timer*, unsigned int);//设置定时时间 单位s
    extern int TimerLeftMS(Timer*);//返回剩余定时时间 单位ms

3.我们要自己实现这些接口函数,还有topic处理的回调函数的实现
3.1定时器的接口函数实现
在这里插入图片描述
//以下函数可以外部调用
void TimerInit(Timer* timer)//定时器初始化
{
timer->StartVal = 0;
timer->end_time = 0;
}
//#define int_ValMax 0xffffffff//int stm32 32位
volatile unsigned int MQTT_sysTime = 0;//全局变量 放定时器中
char TimerIsExpired(Timer* timer)//返回定时器是否超时
{
if(MQTT_sysTime >=timer->StartVal)
return((MQTT_sysTime -timer->StartVal) >timer->end_time);
else
return((MQTT_sysTime +int_ValMax -timer->StartVal) >timer->end_time);
}

void TimerCountdownMS(Timer* timer, unsigned int time)//设置定时时间 单位ms
{
timer->StartVal = MQTT_sysTime;
timer->end_time = time;
}

void TimerCountdown(Timer* timer, unsigned int time)//设置定时时间 单位s
{
timer->StartVal = MQTT_sysTime;
timer->end_time = (time *1000);
}

int TimerLeftMS(Timer* timer)//返回剩余定时时间 单位ms
{
if(MQTT_sysTime >=timer->StartVal)
return(timer->end_time -(MQTT_sysTime -timer->StartVal));
else
return(timer->end_time -(MQTT_sysTime +int_ValMax -timer->StartVal));
}

将全局变量MQTT_sysTime放入SysTick_Handler中断函数中,SysTick中断时间1毫秒
在这里插入图片描述
3.2网络接口函数的实现有,如下图,由于我采用DMA进行1个完整数据帧的接收,所以对数据接收部分源程序进行了重写,源程序是通过不断的查询方式进行接收。
在这里插入图片描述
#define MqttNetwork_USART2 1
int myMqttread(Network* Network, unsigned char* R_buffer, int R_buffer_Lenth, int timeoutMS)//对服务器读 函数需要自己实现
{
// if(Network->my_socket ==MqttNetwork_USART2)
// {
// HAL_UART_Receive(&huart2, R_buffer,R_buffer_Lenth,timeoutMS);
// return R_buffer_Lenth;
// }
if(Network->my_socket ==MqttNetwork_USART2)//UART 采用DMA接收1帧完整数据
{
if(ESP8266_uartRx_f == 1)//接收到数据
{ESP8266_uartRx_f = 0;return 1; }
}
return 0;
}
int myMqttwrite(Network* Network, unsigned char* W_buffer, int W_buffer_Lenth, int timeoutMS)//对服务器写 参数同上 返回写入数据长度
{
if(Network->my_socket ==MqttNetwork_USART2)
{
HAL_UART_Transmit(&huart2,W_buffer,W_buffer_Lenth,timeoutMS);
return W_buffer_Lenth;
}
return 0;
}

UART接收部分程序,DMA初始化,如下图
在这里插入图片描述
HAL_UART_Receive_DMA(&huart1,UpgradeCode_array,array_size);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart2,ESP8266_uartRx,array_size);
__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);

UART接收部分程序,UART中断对接收数据的处理,注意:用的UART2来接收的数据,UART1用做调试,如下图
在这里插入图片描述
if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
{
Uart_R_flog = 1;
HAL_UART_DMAStop(&huart1);
HAL_UART_Receive_DMA(&huart1,UpgradeCode_array,array_size);
uint16_t lenth = mystrlen_Inc0((char*)UpgradeCode_array,sizeof(UpgradeCode_array));
HAL_UART_Transmit(&huart2,UpgradeCode_array,lenth,50);
Clear_array(UpgradeCode_array,lenth);//接收清零
}
__HAL_UART_CLEAR_IDLEFLAG(&huart1);

3.3 打开 MQTTClient.c 对MQTT源程序进行重写,如下图
在这里插入图片描述
static int readPacket(MQTTClient* c, Timer* timer)//由于UART采用DMA接收1帧完整数据 有冲突 对此函数进行重写
{
MQTTHeader header = {0};
int rc = c->ipstack->mqttread(c->ipstack, c->readbuf, 1, TimerLeftMS(timer));//读第一个字节 辨别信息类型
if (rc == 0)//没有接收到数据
goto exit;

header.byte = c->readbuf[0];//取出MQTT固定报头
rc = header.bits.type;//固定报头类型
if (c->keepAliveInterval > 0)
    TimerCountdown(&c->last_received, c->keepAliveInterval); // record the fact that we have successfully received a packet

exit:
return rc;
}

3.4 Topic处理回调函数的实现,如下图三个函数需要Topic处理回调函数,MQTT接收到数据后将会调用相应的Topic处理回调函数
在这里插入图片描述
在这里插入图片描述

回调函数的实现,如下图
在这里插入图片描述
my_u8* pPayload = NULL;//接收Json数据
my_u16 Payload_Lenyh = 0;//接收Json数据长度

extern my_u16 myStrlen_Inc0(my_u8 pStr,my_u16 pStr_Lenth);//数组可以包含0
extern void Clear8266_array(uint8_t array,uint16_t array_lenth);//数组清零
void Device_Upgrade(MessageData
MgData)//MQTT设备升级处理回调函数
{
printf("\nDeviceUpgrade Message is Rsave\n");
printf(“TopicName:\n”);
HAL_UART_Transmit(&huart1,(my_u8
)(MgData->topicName->lenstring.data),MgData->topicName->lenstring.len,1000);
printf("\nPayload:\n");
pPayload = (my_u8*)(MgData->message->payload);
Payload_Lenyh = MgData->message->payloadlen;
HAL_UART_Transmit(&huart1,pPayload,Payload_Lenyh,1000);
printf("\n");
}

到此,移植过程完成,但本平台编译的时候发生MQTT枚举SUCCESS与系统相冲突,对其进行了全部替换,如下图
在这里插入图片描述
三,测试
在这里插入图片描述
unsigned char sendbuf[1024] ={0};
//unsigned char readbuf[1024] ={0};
MQTTClient client_Test;
Network network;
network.mqttread =myMqttread;//指向网络接口函数读
network.mqttwrite = myMqttwrite;
network.my_socket = MqttNetwork_USART2;
MQTTClientInit(&client_Test,&network,5000,sendbuf, sizeof(sendbuf),ESP8266_uartRx, sizeof(ESP8266_uartRx));//创建一个设备并默认初始化

	MQTTSetMessageHandler(&client_Test,"/ota/device/upgrade/a19tZSI5p0d/STM32",Device_Upgrade);//绑定topic与其回调处理函数
	
	MQTTPacket_connectData options =MQTTPacket_connectData_initializer;
	options.cleansession = 1;	//清理会话
	options.clientID.cstring = "STM32|securemode=3,signmethod=hmacsha1|";//客户端标识符
	options.username.cstring = "STM32&a19tZSI5p0d";//用户名
	options.password.cstring = "C78834B21306AFE988A25B5163C15C328DE84F31";//用户密码
	options.MQTTVersion = 3; //MQTT版本
	options.willFlag = 0;
	options.keepAliveInterval = 60;

	if(MQTTConnect(&client_Test, &options) ==MQTT_SUCCESS)//登陆阿里云平台
		printf("Device-Connect!\n");
	else
		printf("Device-DisConnect!\n");
	Clear8266_array(ESP8266_uartRx,sizeof(ESP8266_uartRx));//接收清零
	MQTTYield(&client_Test,10000);//定时一段时间 用于接收服务器发来的数据 在此等待10秒用于接收数据
if(pPayload != NULL)//接收到Json数据
	{

测试结果:成功登陆阿里云平台,并接收到返回数据
在这里插入图片描述
附,MQTT移植包,包含了移植的所有文件:https://download.csdn.net/download/mymycsdn321/20664289

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-01 14:40:08  更:2021-08-01 14:41:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 10:21:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计