admin 管理员组文章数量: 887006
写在前面:
因为最近帮一个朋友完成他的项目,就有了这样一个支线项目,主线项目基于stm32的HAL库开发学习以后有时间一定会继续更新,考虑到广大大学牲完成这样一个新版本无完整开发过程,资料的情况下,我就给大家仔细介绍一下我的开发历程,希望对大家的学习生涯有所帮助,也欢迎各位大佬批评指正!!!文末贴上本次项目的完整例程。
UP几乎踩完了所有的坑,最后终于可以连上onenet,先贴上效果图
分别是连接上服务器,以及stm32采集的数据传到了onenet云平台上
一:硬件选择
本次使用单片机是stm32f103c8t6 选用是最小系统板,其中使用usart1与esp8266通信,而usart3将esp8266返回的数据打印出来,我们便可以通过pc的串口助手观潮我们发送的信息以及收到回复的信息是否正确。
而esp8266本次选择的是esp01-s,最好的优点就是便宜好用。
但是在使用前,需要注意的是,由于本次使用的mqtt协议连接上云,而esp01s刚出场时自带的固件是不支持mqtt协议,所以就需要重新烧录固件,这里根据这篇文章做就可以了。
这里的esp01s我选择的是某宝上的这一家的,这一家客服耐心回答问题售后良好,硬件质量优秀,完全不用担心被坑,闭眼入就完了!(关键是确实便宜啊)。
ESP8266-01 MQTT固件烧录并连接阿里云服务器_烧录mqtt固件接线-CSDN博客
这样硬件部分就准备好了,但我这里还是建议大家用串口助手先发送at指令和esp8266通信试试,为了避免时硬件本身的问题导致后面的过程都通过不了。
二:stm32与esp8266通信至连接wifi部分
如上文所说,我们使用串口1和esp8266进行通信,下面将展示cubemx的配置
首先时RCC和SYS这个自不必说,主要看usart1的配置,
同时,我也开了DMA,DMA这里就不具体展开了,后面有机会的话再来介绍。
波特率设置为115200,同时打开NVIC串口中断开关,以及添加DMA通道。
同理,usart3的配置也是如此,唯一的区别就是并未开启DMA通道,因为usart3的唯一作用就只是在串口DMA中断函数里将接收到的数据打印出来。
下面开始贴代码。
#include "UART_DMA.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "NumAndStr.h"
#include "stm32f1xx_hal.h"
#include "usart.h"
#include "oled.h"
uint8_t RxBuffer[UART_RX_BUF_SIZE] = {0};
uint8_t TxBuffer[UART_RX_BUF_SIZE] = {0};
uint8_t sendCompleteSign = 1;
uint8_t flag,flag_wifi,flag_mqtt,flag_reset;
uint8_t TxLen = 0;
int32_t a,b,c;
double d,e,f;
extern uint8_t uart3_RX_Buffer[r3_length];
extern uint8_t UART3_temp[REC_LENGTH];
extern unsigned int UART3_Rx_cnt ;
void DataProcess(void)
{
//在这里加入数据处理的函数
a = str2int(RxBuffer, ' ', 1);
b = str2int(RxBuffer, ' ', 2);
c = str2int(RxBuffer, ' ', 3);
str2double(RxBuffer, ' ', 4, &d);
str2double(RxBuffer, ' ', 5, &e);
str2double(RxBuffer, ' ', 6, &f);
}
//到USARTx_IRQHandler中添加,如:
//void USART1_IRQHandler(void)
//{
// /* USER CODE BEGIN USART1_IRQn 0 */
// if(__HAL_UART_GET_FLAG(&USB_Huart,UART_FLAG_IDLE))
// {
// HAL_UART_IdleCallback(&USB_Huart);
// }
//
// /* USER CODE END USART1_IRQn 0 */
// HAL_UART_IRQHandler(&huartx);
//}
void HAL_UART_IdleCallback(UART_HandleTypeDef *huart)
{
__HAL_UART_CLEAR_IDLEFLAG(huart);
{
HAL_UART_DMAStop(huart);
ProcessData();
StartUartRxDMA();
}
}
void ProcessData()
{
uint32_t len = 0;
//得到已经接收了多少个字节 = 总共要接收的字节数 - >NDTR F1为CNDTR F4为NDTR
#ifdef __STM32F1xx_HAL_H
len = UART_RX_BUF_SIZE - USB_Huart.hdmarx->Instance->CNDTR;
#define ProcessDataOK
#endif
#ifdef __STM32F4xx_HAL_H
len = UART_RX_BUF_SIZE - USB_Huart.hdmarx->Instance->NDTR;
#define ProcessDataOK
#endif
#ifndef ProcessDataOK
增加所用芯片的版本
#endif
if(len > 0)
{
if(sendCompleteSign == 1)
{
#if UART_RXTX_Switch
memset((void *)TxBuffer, 0, sizeof(TxBuffer));//将TxBuffer数组全部赋值为0
memcpy(TxBuffer, RxBuffer, len);//将RxBuffer的内容全部复制到TxBuffer
TxLen = len;
StartUartTxDMA(); //串口回显
#endif
{
//在这里面加入数据处理的函数
DataProcess();
}
}
}
}
void USB_DMA_printf(const char *format,...)
{
uint32_t length;
va_list args;
va_start(args, format);
length = vsnprintf((char*)TxBuffer, sizeof(TxBuffer)+1, (char*)format, args);
va_end(args);
HAL_UART_Transmit_DMA(&USB_Huart,TxBuffer,length);
}
void USB_printf(const char *format,...)
{
uint32_t length;
va_list args;
va_start(args, format);
length = vsnprintf((char*)TxBuffer, sizeof(TxBuffer)+1, (char*)format, args);
va_end(args);
HAL_UART_Transmit(&USB_Huart,TxBuffer,length,0xFFFF);
}
/**
* @brief Tx Transfer completed callbacks.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
// UNUSED(huart);
if(huart == &USB_Huart)
{
sendCompleteSign = 1;
}
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_UART_TxCpltCallback could be implemented in the user file
*/
}
/**
* @brief Rx Transfer completed callbacks.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
// UNUSED(huart;);
if(huart == &huart3)
{
uart3_RX_Buffer[UART3_Rx_cnt]=UART3_temp[0];
UART3_Rx_cnt++;
// USB_printf("%s",uart3_RX_Buffer);
HAL_UART_Receive_IT(&huart3,(uint8_t *)UART3_temp,REC_LENGTH);
}
if(huart == &USB_Huart)
{
ProcessData();
StartUartRxDMA();
}
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_UART_RxCpltCallback could be implemented in the user file
*/
}
uint8_t UartTxData(UART_HandleTypeDef *huart, uint8_t *buf, const uint32_t len)
{
HAL_StatusTypeDef status;
uint8_t ret = 1;
if(sendCompleteSign == 0 || len == 0)
{
return 0;
}
sendCompleteSign = 0;
status = HAL_UART_Transmit_DMA(huart, (uint8_t*)buf, len);
if(HAL_OK != status)
{
ret = 0;
}
return ret;
}
//启动DMA发送
uint8_t StartUartTxDMA()
{
return UartTxData(&USB_Huart, TxBuffer, TxLen);
}
uint8_t UartRxData(UART_HandleTypeDef *huart, uint8_t *buf, const uint32_t len)
{
HAL_StatusTypeDef status;
uint8_t ret = 1;
status = HAL_UART_Receive_DMA(huart, (uint8_t*)buf, len);
{
if(strstr(buf,"OK")!=NULL)
{
flag=1;
}
if(strstr(buf,"WIFI GOT IP")!=NULL)
flag_wifi=2;
if(strstr(buf,"MQTTCONNECTED")!=NULL)
flag_mqtt=1;
if(strstr(buf,"MQTTDISCONNECTED")!=NULL)
flag_reset=1;
// if(strstr(buf,"CLOUD CONNECTED")!=NULL)
// flag=3;
//if(strstr(buf,"led1off")!=NULL)
// LED1_OFF();
//if(strstr(buf,"led1on")!=NULL)
// LED1_ON();
// OLED_ShowStr(0+8,5,buf,1);
uart3_printf("%s",buf);
// LCD_ShowString(10,10,500,12,12,buf);
//
//
// if(buf[0]==0x31)
// {
// flag=1;
// }
//else if(buf[0]==0x32)
// {
// flag=2;
// }
//else if(buf[0]==0x33)
// {
// flag=3;
// }
//else if(buf[0]==0x34)
// {
// flag=4;
// }
// i++;
}
//pulseWide=buf[0]*10+buf[1];
if(HAL_OK != status)
{
ret = 0;
}
else
{
/* 开启空闲接收中断 */
__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
}
return ret;
}
//启动DMA接收
uint8_t StartUartRxDMA()
{
return UartRxData(&USB_Huart, RxBuffer, UART_RX_BUF_SIZE);
}
/*开始本次的代码解释 首先是USART1的全局中断进行改写,在ISR里添加了代码,对于串口中断的信号位进行判断
判断之后,就开始中断,,其实这个函数集其实也是层层利用的,在TX(由存储器到外设,发送)的中断回调函数里
设置串口中断标志位,然后是RX(外设到存储器,接收)函数的中断回调函数里接受DMA初始化
进而开启DMA接收,在DMA接收函数里返回接收到的数据,其中还有一个数据处理函数,里面将串口数据回显*/
如上代码是根据某一位佬的串口接收数据处理代码改了一下,使用的是DMA的空闲中断,所以需要在it.c里面将usart1_handler函数里面的内容改写一下。其中在UartRxdata里面出现的strtr函数就是比较esp8266返回的语句是否与我们预料的语句
例如
if(strstr(buf,"OK")!=NULL)
{
flag=1;
}
就是判断给esp8266发送AT的时候,是否能正确返回OK。
#include "esp8266.h"
extern uint8_t flag,flag_mqtt,flag_reset;
extern uint8_t flag_wifi;
uint8_t ssid[]={"xxx"};
uint8_t psd[]={"xxxx"};
uint8_t devicename[]={"test"};
uint8_t productid[]={"xxxxxxxx"};
uint8_t deviceid[]={"xxxx"};
uint8_t subscribe[]={"$sys/xxxx/test/thing/property/post/reply"};
uint8_t pubscribe[]={"$sys/xxxx/test/thing/property/post"};
uint8_t fuc[]={"temperature"};
//uint8_t data[]={"$sys/422b4zbv12/test/thing/property/post","{\"id\":\"123\"\,\"params\":{\"temperature\":{\"value\":30\}}}"};
int flag_temp;
extern int temp;
void esp_reset()
{
int i=0;
while(i<=6)
{
USB_printf("AT+RST\r\n");
HAL_Delay(500);
if(flag==1)
{
break;
flag=0;
}
}
}
uint16_t esp_init(void)
{
int i=0;
while(i<=6)
{ USB_printf("AT\r\n");
HAL_Delay(500);
i++;
}
if(flag==1)
{
//HAL_Delay(1000);
return ESP8266_Result_OK;
}
else
{
return ESP8266_Result_Err;
}
}
uint16_t esp_wifi_connect()
{
int i=0;
while(1)
{
USB_printf("AT\r\n");
HAL_Delay(500);
if(flag==1)
{
break;
flag=0;
}
}
HAL_Delay(500);
while(1)
{
USB_printf("AT+CWMODE=1\r\n");
HAL_Delay(200);
if(flag==1)
break;
else
return ESP8266_Result_Err;
}
HAL_Delay(500);
while(1)
{
USB_printf("AT+CWDHCP=1,1\r\n");
HAL_Delay(200);
if(flag==1)
break;
else
return ESP8266_Result_Err;
}
while(1)
{
flag=0;
USB_printf("AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,psd);
HAL_Delay(200);
if(flag_wifi==2)
break;
// else
// return ESP8266_Result_Err;
}
}
如上,不像一般esp8266通信代码一样,会等待多长时间然后返回通过或者没有通过,我的逻辑很简单,就是while循环里一直esp8266发送消息,直到esp返回OK或者是“WIFI GOT IP”才break掉while循环结束发送的流程,就是一直暴力发送(手动狗头),可能函数写的不像一般开源的代码优美,但本人试过确实好用。
其中ssid是wifi名称,psd是wifi密码,上述代码在main函数里的while循环之前被执行。后面会继续讲所有的程序逻辑。待上述程序跑完后,不出意外的话这边你的串口就会给你提示WIFI GOT IP以及WIFI CONNECTED。
tips:这里有坑!!!你的WIFI一定得是2.4G网络,5G网络无法使用,这是因为esp8266的芯片设定,而且如果的esp8266返回了AT+CWJAP=3,这就代表你的wifi是5G的,这是你就需要更换的wifi了。
三:onenet云平台如何创建一个可以连接mqtt的界面
第一步:首先是创建一个onenet平台的账号,然后登录,登录之后,如图
在产品开发这里创建一个产品,然后
创建产品之后产品品类这里选择其他行业
产品名称自填,节点类型选择直连设备,接入协议选择mqtt,数据协议选择onejeson
开发方案选择标准方案,其他的东西都无所谓了就。
紧接着创建设备,当你创建好产品之后,就可以添加设备了,如图
右上角有一个添加设备,添加完设备,设备名最好写test(因为和下文中的token生成有关),点进详情就有如下界面。
记住产品ID和设备密钥,这是我们与平台交互需要的钥匙,
根据平台提供的文档:OneNET - 中国移动物联网开放平台 (10086)
里面可以知道我们需要的指令形式
其中需要下一个token生成器
https://download5.mcloud.139/storageWeb/servlet/downloadServlet?code=TDAwMDExV2xBTXAxbTgyNzkxN3c4aTZTQXdJ&un=505808AAA2BC94B5F91FF8732C800E7A2EE72758AEF113513DCC9E0167B4B091&dom=D950&rate=0&txType=0
第一行最后一个/后是你的设备名,第一个/后是你的设备ID,ret是时间戳,key是设备密钥,点击generate,然后就会生成一串密钥。记住他,我们后面会用到
AT+MQTTUSERCFG=0,1,"test","422b4zbv12","version=2018-10-31&res=products%2F422b4zbv12%2Fdevices%2Ftest&et=2052911776&method=md5&sign=kSKpEHBa9KKDg%2FtfYQLKFQ%3D%3D",0,0,""
第二个引号里的内容是设备id,后面一长串则是刚刚生成的密钥。
AT+MQTTCONN=0,"mqtts.heclouds",1883,1
这一段代码直接无脑输入,是连接mqtt服务器的地址和端口。
AT+MQTTSUB=0,"$sys/422b4zbv12/test/thing/property/post/reply",1
这个是订阅mqtt服务器的消息,以上消息若成功发送,则会返回OK。这里建议大家用电脑串口助手测试一下。然后继续进行下一步的stm32代码编写。
四:通过串口给esp8266发送信息与onenet通信。
void esp_mqtt_connect()
{
int i=0;
flag=0;
// if(flag_wifi==2)
{
while(1)
{
USB_printf("AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n",devicename,productid,deviceid);
HAL_Delay(200);
if(flag==1)
break;
i++;
}
flag=0;
HAL_Delay(200);
while(1)
{
USB_printf("AT+MQTTCONN=0,\"mqtts.heclouds\",1883,1\r\n");
HAL_Delay(200);
if(flag==1)
break;
}
flag=0;
HAL_Delay(200);
while(1)
{
i++;
USB_printf("AT+MQTTSUB=0,\"%s\",1\r\n",subscribe);
HAL_Delay(200);
if(flag==1)
{
break;
}
}
flag_temp=1;
HAL_Delay(500);
// while(1)
// {
// i++;
// USB_printf("AT+MQTTPUB=0,\"%s\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"%s\\\":{\\\"value\\\":%d}}}\",0,0\r\n",pubscribe,fuc,i);
// HAL_Delay(1500);
// }
}
}
以上代码逻辑和连接wifi代码逻辑相同,暴力发送直到他返回ok,大家自己测试的时候最好先把延时的时间改稍微长一点看回复,当最后一条语句订阅了服务器消息的语句发送完毕,并且返回OK的时候,这里你会惊喜的发现,onenet平台你的设备就会显示在线了。
在这里解释一下前面productid是设备ID,deviceid是用token生成的密钥,subscribe是订阅消息的指令。
这里面又有坑!因为esp8266有记住wifi的功能,就是当你上电后,可能wifi随之就连上了,但是你后面又重新发送连接wifi指令的时候,可能这个时候wifi会掉,这也是我目前 代码一个 bug,此时你并没有连上wifi或者因为其他的原因导致wifi没连上,但是走到了连接mqtt服务器这一步的时候,mqtt就会返回mqttdisconnected :0 error,在你发送连接服务器请求后是有一段这个响应时间,
一般情况下,AT MQTT命令会在10秒内响应,但AT+MQTTCONN命令除外。例如,如果路由器无法访问internet,则AT+MQTTPUB命令会在10秒内响应。但是AT+MQTTCONN命令可能需要更多的时间,因为在不良的网络环境中需要重传数据包。.如果AT+MQTTCONN基于TLS连接,每个包的超时为10秒,则根据握手包计数,总超时将长得多。
后面有时间会修复这个bug,也希望各位读者可以帮我修一修哈哈。一般来说打断点,一步步debug可以避免这个问题,脱机后就可能会出现连不上的情况。
五:当你前面所有的操作都完成之后,将stm32外设采集的消息传到onenet云平台。
如果你千帆过尽,走到这最后一步的时候,恭喜你,快要成功了。
我拿温度举例,如下图,点进产品开发,右边点击设置物模型,自定义功能点
如下图设置,读写类型设置读写。
设置完毕后就是指令,
AT+MQTTPUB=0,"$sys/422b4zbv12/test/thing/property/post","{\"id\":\"123\"\,\"params\":{\"temperature\":{\"value\":20\}}}",0,0
第二个引号之后是你的产品ID,需要改的就是你的这个变量的标识符,与onenet云平台对应就好。
这里用电脑串口助手测试,回复ok,这个时候你就可以看到设备详情里的属性里的温度就会有你value后面的值了。
放在32里 是这样写的
void send_temp()
{
if(flag_temp==1)
{
// while(1)
{
USB_printf("AT+MQTTPUB=0,\"%s\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"%s\\\":{\\\"value\\\":%d}}}\",0,0\r\n",pubscribe,fuc,temp);
// HAL_Delay(1500);
}
}
}
如果代码跑下来一切顺利的话,电脑的串口助手应该会有如下图样
到这里就大功告成了!
最后:补充main.c以及串口3发送函数代码
main.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "i2c.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "UART_DMA.h"
#include "esp8266.h"
#include "bsp_ds18b20.h"
#include "oled.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
uint8_t uart3_RX_Buffer[r3_length]={0};
uint8_t UART3_temp[REC_LENGTH] = {0};
unsigned int UART3_Rx_cnt;
int temp,temp_set=15;
int flag_ds;
float m_water=0.15;
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_USART3_UART_Init();
MX_TIM1_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start(&htim2);
HAL_TIM_Base_Start(&htim3);
HAL_TIM_Base_Start(&htim1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
//__HAL_UART_ENABLE_IT(&huart3,UART_IT_RXNE);
//HAL_UART_Receive_IT(&huart3,(uint8_t *)UART3_temp,REC_LENGTH);
Ds18b20_Init();
StartUartRxDMA();
OLED_Init();
USB_DMA_printf("AT+RST\r\n");
HAL_Delay(100);
//uart3_printf("666");
//esp_init();
esp_wifi_connect();
HAL_Delay(100);
esp_mqtt_connect();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
如你所见,我的esp8266函数在main里的while循环前执行,在所有的模块初始化我完成之后,而且每一个与esp8266有关的函数都是一个while循环,这样写是因为之前frertos写多了,想每个功能都单独开一个任务完成,但f1的性能不足以支持这样玩,我这样的写法也是不合适的,像大多数开源等待响应返回函数值执行下一步,放在while循环里写才是正道,这时候你可能会问我的其他外设写在哪儿了,相信佬一定猜出来了,我开了四个定时器,其他的事件都放在定时器里刷新了。
串口3打印函数
void uart3_printf(char *fmt, ...)
{
uint32_t length;
va_list args;
va_start(args, fmt);
length = vsnprintf((char*)uart3_tx_buf,sizeof(uart3_tx_buf)+1, (char*)fmt, args);
va_end(args);
HAL_UART_Transmit(&huart3,uart3_tx_buf,length,0xFFFF);
}
到这里,全文就结束了,如果有什么问题,欢迎大家批评指正!
拜谢!
如果想要完整工程代码,请务必一键三连私信up,或者评论区,谢谢大家!!!最后祝大家都能成功实现,不踩坑!
链接:https://pan.baidu/s/12sCS9a8b8_6EFs6pVi8uPg?pwd=wifi
提取码:wifi
--来自百度网盘超级会员V2的分享
所有工程均在链接中~
版权声明:本文标题:最新!基于stm32+esp8266+mqtt连接最新版onenet云平台(非旧版本多协议接入)HAL库开发版本 文末附代码 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1729141266h1322962.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论