开板:野火 stm32f103 指南者
wifi芯片 :ESP8266 板载的模块 出厂自带固件
C_SDK :阿里云官网 c_sdk_3.0.1版本
IDE:keil 5
首先学习、简单了解MQTT协议:
1.简介
Message Queuing Telemetry Transport 消息队列遥测传输协议,物联网的应用层协议,运行在TCP/IP,依赖TCP协议。
基于TCP协议的 CS模型,发布/订阅主题消息的轻量级协议。
2.通信模型
mqtt提供一对多的消息发布,协议中三种身份:发布者publisher、服务器broker、订阅者Subscriber
publisher和Subscriber都是客户端,服务器起到的是中转作用
MQTT 客户端的功能:
\1. 发布消息给其它相关的客户端。
\2. 订阅主题请求接收相关的应用消息。
\3. 取消订阅主题请求移除接收应用消息。
\4. 从服务端终止连接
mqtt服务器 :一般是云服务器,BAT三家中的物联网平台常使用mqtt协议。
\1. 接受来自客户端的网络连接请求。
\2. 接受客户端发布的应用消息
\3. 处理客户端的订阅和取消订阅请求。
\4. 转发应用消息给符合条件的已订阅客户端(包括发布者自身)。
3.消息主题 服务质量
主题 (Topic ):
客户端知道服务上有很多个主题。就好比如说有很多消息的分类一样子。有社会新闻、体育讲坛等。那么客户端只要找到自己感兴趣的进行订阅就可以了。一个客户端可以向服务器订阅多个主题。而所谓的发布就是客户端对不同的主题进行发布信息。
如果主题只是一个字符串值的话,那么显然会比较单调。这样子功能也显得比较无力。所以在主题上面就了所谓的分隔符和通配符的说法(个人想法)。分隔符的意思就是让主题可以分层次。就好如说主题“体育讲坛/篮球/NBA”。看到这样子的主题,请问一下你还有什么不明白的话。是不是感觉很有层次感。
如果我们订阅了主题“体育讲坛/篮球/NBA”,并向主题“体育讲坛/篮球”发布一个信息。那么已经订阅主题“体育讲坛/篮球/NBA”的客户端们是不是可以接受到信息呢?反过来讲如果我们订阅了主题“体育讲坛/篮球”,向主题“体育讲坛/篮球/NBA”发信息,客户端们是否又能接受信息呢?? (答案:不行!)
如果想要收到NBA就是必须订阅主题“体育讲坛/篮球/NBA”。
通配符:
可是总是有一些人只要是篮球的新闻有喜欢。怎么办。通配符的功能就出来了。通配符有俩种——"+"和“#”。
+为单层的通配符。表示当前这一层的全都合法。
订阅一个主题为“体育讲坛/篮球/+”,那么“体育讲坛/篮球/NBA”和“体育讲坛/篮球/ABC”各发布的信息订阅者都可以收到。
“#“通配符就是表示当前本身和下面子层所有。
服务质量:
服务质量分3等级:
QoS0:最多发送一次消息,在消息发送出去后,接收者不会发送回应,发送者也
不会重发消息,消息可能送达一次也可能根本没送达,这个服务质量常用在不重
要的消息传递中,因为即使消息丢了也没有太大关系。
QoS1:最少发送一次消息(消息最少需要送达一次,也有可送达多次),QoS 1
的 PUBLISH 报文的可变报头中包含一个报文标识符,需要 PUBACK 报文确认。
即需要接收者返回 PUBACK 应答报文。
QoS2:这是最高等级的服务质量,消息丢失和重复都是不可接受的,只不过使用
这个服务质量等级会有额外的开销,这个等级常用于支付中,因为支付是必须有
且仅有一次成功,总不能没给钱或者给了多次钱吧。
-------------------------------------------------------------------------
学习完总结:
要让开发板连接到阿里云,要使用mqtt协议,移植mqtt(因为阿里云物联网的平台就是基于mqtt的应用层)
移植MQTT有两种方式:一、移植MQTT的AT指令固件到esp8266中,MCU使用MQTT的AT指令连接阿里云、订阅、发布
二、MQTT移植到MUC的代码中,应用层代码
这里选择第二种:MQTT移植到MUC的代码中,移植方法有以下几种:
1.写好ESP8266的代码后,根据MQTT协议,自己写mqtt_connect mqtt_publish mqtt_subcribe
2.写好ESP8266的AT指令封装函数 ,移植SDK ,改写SDK层中的几个接口....
3.将mqtt源码编译到项目,修改transport.c文件
这里选择方法2:移植SDK到MCU
0.阿里云文档:SDK获取 https://help.aliyun.com/document_detail/164249.html?spm=a2c4g.11186623.2.15.6110fd92j5qQJW#concept-2050379
1.基于KEIL、IAR等开发工具进行开发,需要了解如何裁剪:https://help.aliyun.com/document_detail/111026.html?spm=a2c4g.11186623.2.29.34544e1eQnfBnc
2.MCU+TCP模组 https://help.aliyun.com/document_detail/97921.html?spm=a2c4g.11186623.2.31.34544e1e2xUS61
抽取mqtt功能的移植SDK说明https://help.aliyun.com/document_detail/111026.html?spm=a2c4g.11186623.6.599.2cb965b2dvPiuc
SDK官方文档:HAL库接口说明https://help.aliyun.com/document_detail/100111.html?spm=a2c4g.11186623.2.54.10045f4f29qKrw
3.看懂文档,按照文档去配置SDK功能(运行config.bat) 生成代码后,实现HAL库对接
太艰难了.....走了能走的所有弯路!
这里我选择的是:将协议移植到MCU上,就是MCU运行程序,wifi芯片esp8266只调用AT指令去完成网络功能:接入手机热点、TCP连接connect服务器等等...
下面是走的弯路心路历程:
有时候想想,并不是不会做,而是不知道从哪里入手,从哪里开始,各种方法哪一种最简单高效...
最开始,准备找支持mqtt协议的esp8266固件,将固件烧写后直接调用AT指令
然后确定没有这样开源的固件,就算有这种方法不太好...
后开始看官方文档,准备在MCU层写MQTT协议,应用层嘛就写好协议报文就行,底层的esp8266等等都写好了
怎么写?移植MQTT的源码,修改源码? CSDN上查了下发现大都做出来的是:自己根据协议写好mqtt_connect 等函数 ,我觉得这样速度快 高效 简单点
写到最后连不上去,后来问人
然后说 这样写不行,自己写mqtt_connect publish不太现实,协议是开源的库,不要重复造轮子
移植阿里云官方的SDK....选择C SDK 下载下来
移植官方的SDK,有3.x版本、4.x版本,好像4.x的更适用于通信模组的SDK
于是选择3.x版本
准备移植,发现3.0.1版本 和 3.1.0版本 坑死我,3.1.0的不管怎么配置功能,最后生成的代码就是不对,我明明没配置SSL功能,但是程序就是需要我去实现SSL的4个函数
于是再配置3.0.1版本,配置的时候要选择功能:选ATM 还是不选 ,选择使用阿里云提供的层层接口?
配置不同的功能,出来的代码量不一样,需要自己实现的函数也不一样
使能ATM :FEATURE_ATM_ENABLED :系统是使用MCU+外接模组的架构, 并且SDK运行在MCU上, 必须打开该选项, 然后进行配置
但是:文档里开始说://FEATURE_MQTT_ATM_ENABLED 是否使能SDK中的ATM模块 可选
这个可选 让我觉得不重要... 等等 这两个东西 不一样....
我草!!看混了....
文档中又看到://FEATURE_ATM_ENABLED 如果希望使用阿里提供的AT TCP或者AT Parser,请使能本选项。当本模块使能之后, 还会出现是否使能AT TCP的配置选项
使能TCP :不需要
使能AT parase :AT指令数据收发解析模块 (SDK提供的AT收发/解析的框架)
终于 成功配置出代码,将代码放到keil工程中 编译还算顺利(之前的3.1.0版本的 编译出几百个错误 根本就解决不了 解决)
补全wappers.c中的接口:补全后测试
改3-4个bug
终于 终于.....
我的STM32F103开发板连接到了阿里云!
好吐槽完,下面开始正式移植:按照步骤即可
这部分内容网上非常多的例子,随便搜一篇博客都有操作方法,并且官网文档资料也很详细...
建议仔细研究阿里云官网文档!
仔细研究阿里云官网文档!
仔细研究阿里云官网文档!
参考链接:
https://www.mscto.com/iot/382885.html
https://help.aliyun.com/document_detail/73705.html?spm=a2c4g.11186623.6.566.4f965a10nivV49
下面是我创建好产品的实例:
这一步骤很重要!做完之后我才意识到:为什么我走了那么多弯路,就是因为没好好看文档,文档中有介绍很全面很细节的地方,我忽略了,每次都是看两眼文档觉得差不多了就闷头去干!
第一部分:了解创建产品、设备,如何上云,使用技术等
了解MQTT的过程,方法,具体操作
https://help.aliyun.com/document_detail/96623.html?spm=a2c4g.11186623.2.16.11a22cf0nbQPag
参考博客:https://blog.csdn.net/spiremoon/article/details/104754432
这位博主的做法和我的做法是一模一样的。
这里我下载了c_sdk3.0.1 ,因为在配置功能的时候走了坑啊!坑死我了!3.1.0的不管怎么配置功能,最后生成的代码就是不对,我明明没配置SSL功能,但是程序就是需要我去实现SSL的4个函数。实在找不到原因,最后无奈试了试c_sdk3.0.1,没想到配置出后,生成的接口是我需要的。
下载链接官网都有:
下面是我下载下的c_sdk,解压后:(同样 官网有文档介绍每个文件夹的内容)
其中:config.bat是windows脚本,点击改文件在Windows下配置(其他文件makefile等就是在linux下使用的),
extract.bat是配置好功能后,使用该脚本抽取代码,抽取代码后会生成一个output文件夹,我们配置的功能代码就在这个文件夹。(其他的文件夹的代码就不需要了,只需要这个output)
点击config.bat,出现如下界面:
这里我配置的功能不多,只配置了必须的,如下:
一共就这6个 :
PLATFORM_HAS_STDINT (告诉SDK当前要移植的嵌入式平台是否有自带标准头文件
PLATFORM_HAS_DYNMEM(可以使用动态内存分配 我直接使用了malloc 和 free)
FEATURE_MQTT_COMM_ENABLED(长连接功能, 打开后将使SDK提供MQTT网络收发的能力和接口)
FEATURE_MQTT_DEFAULT_IMPL(SDK内包含的MQTT Client实现, 打开则表示使用SDK内置的MQTT客户端实现)
FEATURE_MQTT_DIRECT(mqtt直连)
FEATURE_ATM_ENABLED(系统是使用MCU+外接模组的架构, 并且SDK运行在MCU上, 必须打开该选项, 然后进行配置)
有两个功能当时很纠结,看阿里云文档也不知道配置不配置差距多大,所以这里我没有配置:
FEATURE_AT_TCP_ENABLED (一个模组TCP连接和数据缓存的模块)
FEATURE_AT_PARSER_ENABLED (AT指令数据收发解析模块 (SDK提供的AT收发/解析的框架))
这两个功能阿里云文档有介绍,我一开始配置了但是出来的代码功能多,编译各种报错,后来就放弃,准备自己写接口...去实现
将output文件夹下的几乎所有.c文件移植到keil工程中,个别文件除外
移植后修改mqtt_example.c中的main函数名,因为此时程序中有两个main,编译报错!
这里我修改成mqtt_main:并在主函数中调用这个mqtt_main。
编译!解决语法问题:这里应该会出现很多头文件找不到,需要在项目中把头文件路径加上。
我一个日志不打印的问题,修改了项目中的代码:很奇怪我明明配置正确功能,但是日志功能....出错
移植后 日志不打印 后修改mqtt_internal.h 把之前的屏蔽掉 使用HAL_Printf
#ifdef INFRA_LOG
#include "infra_log.h"
/* #define mqtt_emerg(...) log_emerg("MQTT", __VA_ARGS__)
#define mqtt_crit(...) log_crit("MQTT", __VA_ARGS__)
#define mqtt_err(...) log_err("MQTT", __VA_ARGS__)
#define mqtt_warning(...) log_warning("MQTT", __VA_ARGS__)
#define mqtt_info(...) log_info("MQTT", __VA_ARGS__)
#define mqtt_debug(...) log_debug("MQTT", __VA_ARGS__)*/
#define mqtt_emerg(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define mqtt_crit(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define mqtt_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define mqtt_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define mqtt_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define mqtt_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
到了最难的一步了!
第一部分的函数:相对简单,网上有例子,c_sdk中有参考实例:因为我项目中没有使用操作系统
第二部分:
最难最难的地方,我没有配置TCP的两个中间层的功能,所以就要自己写好这几个函数。其中最难写的是HAL_TCP_Read,这个函数我还有bug,所以我的项目还是没调通,只是能够连接上阿里云,阿里云显示我的设备在线.....
以下是我的wapper.c
#include
#include
#include
#include
#include "infra_types.h"
#include "infra_defs.h"
#include "wrappers_defs.h"
#include "mqtt.h"
#include
#include "esp8266.h"
#include "bsp_usart.h"
/**
* @brief Deallocate memory block
*
* @param[in] ptr @n Pointer to a memory block previously allocated with platform_malloc.
* @return None.
* @see None.
* @note None.
*/
void HAL_Free(void *ptr)
{
free(ptr);
}
/**
* @brief Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
*
* @param [in] size @n specify block size in bytes.
* @return A pointer to the beginning of the block.
* @see None.
* @note Block value is indeterminate.
*/
void *HAL_Malloc(uint32_t size)
{
printf("HAL_Malloc(uint32_t size :%d)",size);
return malloc(size);
}
/**
* @brief Create a mutex.
*
* @retval NULL : Initialize mutex failed.
* @retval NOT_NULL : The mutex handle.
* @see None.
* @note None.
*/
void *HAL_MutexCreate(void)
{
return (void *)1;
}
/**
* @brief Destroy the specified mutex object, it will release related resource.
*
* @param [in] mutex @n The specified mutex.
* @return None.
* @see None.
* @note None.
*/
void HAL_MutexDestroy(void *mutex)
{
return;
}
/**
* @brief Waits until the specified mutex is in the signaled state.
*
* @param [in] mutex @n the specified mutex.
* @return None.
* @see None.
* @note None.
*/
void HAL_MutexLock(void *mutex)
{
return;
}
/**
* @brief Releases ownership of the specified mutex object..
*
* @param [in] mutex @n the specified mutex.
* @return None.
* @see None.
* @note None.
*/
void HAL_MutexUnlock(void *mutex)
{
return;
}
/**
* @brief Writes formatted data to stream.
*
* @param [in] fmt: @n String that contains the text to be written, it can optionally contain embedded format specifiers
that specifies how subsequent arguments are converted for output.
* @param [in] ...: @n the variable argument list, for formatted and inserted in the resulting string replacing their respective specifiers.
* @return None.
* @see None.
* @note None.
*/
void HAL_Printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
}
int HAL_Snprintf(char *str, const int len, const char *fmt, ...)
{
va_list args;
int rc;
va_start(args, fmt);
rc = vsnprintf(str, len, fmt, args);
va_end(args);
return rc;
}
/**
* NOTE:
*
* HAL_TCP_xxx API reference implementation: wrappers/os/ubuntu/HAL_TCP_linux.c
*
*/
#include "infra_compat.h"
#include "stdarg.h"
/**
* 函数 HAL_GetDeviceName() 需要SDK的使用者针对SDK将运行的硬件平台填充实现, 供SDK调用
* 如果需要参考如何实现函数 HAL_GetDeviceName(), 可以查阅SDK移植到 Ubuntu Linux 上时的示例代码
* https://code.aliyun.com/linkkit/c-sdk/blob/v3.0.1/wrappers/os/ubuntu/HAL_OS_linux.
*/
/**
* @brief Get device name from user's system persistent storage
*
* @param [ou] device_name: array to store device name, max length is IOTX_DEVICE_NAME_LEN
* @return the actual length of device name
*/
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN])
{
int len = strlen(DEVICENAME);
memset(device_name,0,IOTX_DEVICE_NAME_LEN);
strncpy(device_name,DEVICENAME,len);
return len;
}
/**
* @brief Get device secret from user's system persistent storage
*
* @param [ou] device_secret: array to store device secret, max length is IOTX_DEVICE_SECRET_LEN
* @return the actual length of device secret
*/
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN])
{
int len = strlen(DEVICESECRET);
memset(device_secret,0,IOTX_DEVICE_SECRET_LEN);
strncpy(device_secret,DEVICESECRET,len);
return len;
}
/**
* @brief Get firmware version
*
* @param [ou] version: array to store firmware version, max length is IOTX_FIRMWARE_VER_LEN
* @return the actual length of firmware version
*/
int HAL_GetFirmwareVersion(char *version)
{
char *ver = "app-1.0.0-20200915.1000";
int len = strlen(ver);
memset(version, 0x0, IOTX_FIRMWARE_VER_LEN);
strncpy(version, ver, IOTX_FIRMWARE_VER_LEN);
version[len] = '\0';
return strlen(version);
}
/**
* @brief Get product key from user's system persistent storage
*
* @param [ou] product_key: array to store product key, max length is IOTX_PRODUCT_KEY_LEN
* @return the actual length of product key
*/
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN])
{
int len = strlen(PRODUCTKEY);
memset(product_key,0,IOTX_PRODUCT_KEY_LEN);
strncpy(product_key,PRODUCTKEY,len);
return len;
}
int HAL_GetProductSecret(char *product_secret)
{
int len = strlen(PRODUCYSECRET);
memset(product_secret,0,len);
strncpy(product_secret,PRODUCYSECRET,len);
return len;
}
uint32_t HAL_Random(uint32_t region)
{
return (uint32_t)1;
}
/* set不需要实现 */
int HAL_SetDeviceName(char *device_name)
{
return (int)1;
}
int HAL_SetDeviceSecret(char *device_secret)
{
return (int)1;
}
int HAL_SetProductKey(char *product_key)
{
return (int)1;
}
int HAL_SetProductSecret(char *product_secret)
{
return (int)1;
}
/**
* @brief Sleep thread itself.
*
* @param [in] ms @n the time interval for which execution is to be suspended, in milliseconds.
* @return None.
* @see None.
* @note None.
*/
void HAL_SleepMs(uint32_t ms)
{
HAL_Delay(ms);
}
void HAL_Srandom(uint32_t seed)
{
srand(seed);
}
/**
*
* 函数 HAL_TCP_Destroy() 需要SDK的使用者针对SDK将运行的硬件平台填充实现, 供SDK调用
* ---
* Interface of HAL_TCP_Destroy() requires to be implemented by user of SDK, according to target device platform
*
* 如果需要参考如何实现函数 HAL_TCP_Destroy(), 可以查阅SDK移植到 Ubuntu Linux 上时的示例代码
* ---
* If you need guidance about how to implement HAL_TCP_Destroy, you can check its reference implementation for Ubuntu platform
*
* https://code.aliyun.com/linkkit/c-sdk/blob/v3.0.1/wrappers/os/ubuntu/HAL_TCP_linux.c
*
*
* 注意! HAL_XXX() 系列的函数虽然有阿里提供的对应参考实现, 但不建议您不做任何修改/检视的应用于您的商用设备!
*
* 注意! 参考示例实现仅用于解释各个 HAL_XXX() 系列函数的语义!
*
*/
/**
* @brief Destroy the specific TCP connection.
*
* @param [in] fd: @n Specify the TCP connection by handle.
*
* @return The result of destroy TCP connection.
* @retval < 0 : Fail.
* @retval 0 : Success.
*/
int HAL_TCP_Destroy(uintptr_t fd)
{
return (int)1;
}
/**
*
* 函数 HAL_TCP_Establish() 需要SDK的使用者针对SDK将运行的硬件平台填充实现, 供SDK调用
* ---
* Interface of HAL_TCP_Establish() requires to be implemented by user of SDK, according to target device platform
*
* 如果需要参考如何实现函数 HAL_TCP_Establish(), 可以查阅SDK移植到 Ubuntu Linux 上时的示例代码
* ---
* If you need guidance about how to implement HAL_TCP_Establish, you can check its reference implementation for Ubuntu platform
*
* https://code.aliyun.com/linkkit/c-sdk/blob/v3.0.1/wrappers/os/ubuntu/HAL_TCP_linux.c
*
*
* 注意! HAL_XXX() 系列的函数虽然有阿里提供的对应参考实现, 但不建议您不做任何修改/检视的应用于您的商用设备!
*
* 注意! 参考示例实现仅用于解释各个 HAL_XXX() 系列函数的语义!
*
*/
/**
* @brief Establish a TCP connection.
*
* @param [in] host: @n Specify the hostname(IP) of the TCP server
* @param [in] port: @n Specify the TCP port of TCP server
*
* @return The handle of TCP connection.
@retval (uintptr_t)(-1): Fail.
@retval All other values(0 included): Success, the value is handle of this TCP connection.
*/
uintptr_t HAL_TCP_Establish(const char *host, uint16_t port)
{
static uintptr_t fd = 1;
//连接服务器
Esp8266_Connect_Server_host_port(host,port);
return fd++;
}
/**
* @brief Read data from the specific TCP connection with timeout parameter.
* The API will return immediately if 'len' be received from the specific TCP connection.
*
* @param [in] fd @n A descriptor identifying a TCP connection.
* @param [out] buf @n A pointer to a buffer to receive incoming data.
* @param [out] len @n The length, in bytes, of the data pointed to by the 'buf' parameter.
* @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly.
*
* @retval -2 : TCP connection error occur.
* @retval -1 : TCP connection be closed by remote server.
* @retval 0 : No any data be received in 'timeout_ms' timeout period.
* @retval (0, len] : The total number of bytes be received in 'timeout_ms' timeout period.
超时期间接收的字节总数
* @see None.
*/
int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms)
{
printf("HAL_TCP_Read len=%d\n",len);
return TCP_Read_From_ALIYUN_Data(buf,len,timeout_ms);
}
/**
* @brief Write data into the specific TCP connection.
* The API will return immediately if 'len' be written into the specific TCP connection.
*
* @param [in] fd @n A descriptor identifying a connection.
* @param [in] buf @n A pointer to a buffer containing the data to be transmitted.
* @param [in] len @n The length, in bytes, of the data pointed to by the 'buf' parameter.
* @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly.
*
* @retval < 0 : TCP connection error occur..
* @retval 0 : No any data be write into the TCP connection in 'timeout_ms' timeout period.
* @retval (0, len] : The total number of bytes be written in 'timeout_ms' timeout period.
* @see None.
*/
int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms)
{
printf("HAL_TCP_Write\n");
Esp8266_SendData(buf,len,timeout_ms);
return len;
}
/**
* @brief Retrieves the number of milliseconds that have elapsed since the system was boot.
*
* @return the number of milliseconds.
* @see None.
* @note None.
*/
//返回一个uint64_t类型的数值, 表达设备启动后到当前时间点过去的毫秒数
uint64_t HAL_UptimeMs(void)
{
return (uint64_t)1;
}
int HAL_Vsnprintf(char *str, const int len, const char *format, va_list ap)
{
return vsnprintf(str, len, format, ap);
}
程序能打印出log,但运行总会出错,调试吧......我这边有4个bug要解决:
最后一个bug还没完全调好... 有点遗憾
bug1 : mallo申请空间时,heap堆太小,导致malloc返回0,mqtt内部的接口出错,程序直接return
解决方法:去start_up_stm32f103xe.s 中修改heap大小
bug2:发送数据从透传模式 改为 非透传。透传模式,非常不建议使用!因为wifi转到透传模式后,后面就非常难弄,设备升级、还需要退出...
AT+CIPSEND= 该指令说明要发送数据长度 后面紧接着给8266的串口发送数据
bug3:发送数据中有\0 ,导致我服务器一直接受不到数据。原因:我串口发送数据:遇到\0结尾 ,改写串口发送程序
bug4:HAL_TCP_Read 第一次connect后需要接受1字节?? 但我的buff中有241字节
数据需要解析:
发送AT指令的数据后,esp8266将发送结果返回 同时也将服务器的响应结果返回,二者混合在了一起
解决方法:1.再写一个缓存区buff 将服务器的结果单独存放
2.改成透传模式 这样esp8266就只会将服务器结果返回(不会对AT指令的结果返回)
总结的话:8266的驱动程序写的很完善的话,应该就不会有那么多bug...
这个移植做了好久好久... 做到后面放弃了都要... 还有点bug也不想调试了...
感觉没多难,原理什么的感觉都明白,mqtt就是上层应用层的代码,一个通讯协议而已,规定数据格式,发送、接收、解析数据就好了.....
但是整个下来后还是各种问题....
参考链接的博主说的对:
最后我的项目代码:
链接:https://pan.baidu.com/s/1XYuOobpp1bRxT5_j7sNArQ
提取码:es5j
复制这段内容后打开百度网盘手机App,操作更方便哦