物联网小项目——墨水屏时钟(STM32+ESP8266实现)

这篇具有很好参考价值的文章主要介绍了物联网小项目——墨水屏时钟(STM32+ESP8266实现)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

无意间在网上看到开源的使用墨水屏打造的桌面时钟,当个桌面小摆件可谓是十分优雅,于是就萌生出了自己DIY一个的想法。这个墨水屏时钟具有以下特点

  • 时间日期的显示和自动校准
  • 自动获取实时天气
  • 半夜自动进入休眠
  • 支持微信智能配网

目前已经实现软件功能,但是硬件上没有画板做成一体化的,只是开发板和模块之间使用杜邦线连接的试验版本。
物联网小项目——墨水屏时钟(STM32+ESP8266实现)
物联网小项目——墨水屏时钟(STM32+ESP8266实现)
物联网小项目——墨水屏时钟(STM32+ESP8266实现)

硬件设计

硬件由STM32主控、ESP8266模块、墨水屏驱动电路和墨水屏主体组成。STM32通过串口给ESP8266发送AT指令控制其连接WIFI和获取信息等操作;通过SPI控制墨水屏。
为了节约成本墨水屏使用的是电子价签上拆下来的2.13寸汉朔墨水屏,驱动电路可以参照微雪电子官方的提供的驱动电路,单片机通过SPI与其通信即可。
物联网小项目——墨水屏时钟(STM32+ESP8266实现)

墨水屏驱动

驱动程序可以参考微雪电子官网的,只需把STM32版本的demo下载下来,找到RTS,CS,DC,BUSY,SCL,SDA,USART宏定义,并改成自己实际接的GPIO,最后将main函数里的EPD_2in13_test()注释打开,编译烧录就能看到墨水屏显示图片了。
能刷新墨水屏就说明硬件没有问题了,接下来就要精简出项目需要的墨水屏驱动代码即可。我用到了gpio,spi,DEV_Config,存储图片数据的imageData,存储字库数据的Font,负责控制的EPD_2in13,画图接口的GUI_Paint。

获取网络时间

墨水屏时钟的时钟来源是STM32内部的RTC时钟,因为晶振的差异,导致RTC时钟走时并不十分准确,所以使用网络校准每隔一个小时获取一次网络时间写入RTC寄存器中。如何配置RTC实时时钟和ESP8266连接WIFI可以参考我的另外两篇博客
STM32F1系列HAL库开发——RTC实时时钟
STM32使用ESP8266模块AT指令连接心知天气API获取天气信息
获取网络时间可以使用ESP8266的AT+CIPSNTPCFG设置时域和 SNTP 服务器AT+CIPSNTPTIME—查询 SNTP 时间

//设置SNTP服务器时域,参数1:使能,参数2:设置时域
AT+CIPSNTPCFG=1,8\r\n
//获取SNTP服务器时间
AT+CIPSNTPTIME?\r\n
//获取到的时间格式如下
+CIPSNTPTIME:Thu	Aug	04	14:48:05	2016
//解析获取到的数据
char result[16];
char *p = strstr((const char*)USART2_RX_BUF,"+CIPSNTPTIME:");
p += 17;		//跳到月份的字符串
		//设置月份
		for(i=0; (*p != ' ') && (*p != '\t'); i++)
		{
			result[i] = *p++;
		}
		if(strcmp(result,"Jan") == 0)
			RTC_DataStruct.Month = RTC_MONTH_JANUARY;
		else if(strcmp(result,"Feb") == 0)
			RTC_DataStruct.Month = RTC_MONTH_FEBRUARY;
		else if(strcmp(result,"Mar") == 0)
			RTC_DataStruct.Month = RTC_MONTH_MARCH;
		else if(strcmp(result,"Apr") == 0)
			RTC_DataStruct.Month = RTC_MONTH_APRIL;
		else if(strcmp(result,"May") == 0)
			RTC_DataStruct.Month = RTC_MONTH_MAY;
		else if(strcmp(result,"Jun") == 0)
			RTC_DataStruct.Month = RTC_MONTH_JUNE;
		else if(strcmp(result,"Jul") == 0)
			RTC_DataStruct.Month = RTC_MONTH_JULY;
		else if(strcmp(result,"Aug") == 0)
			RTC_DataStruct.Month = RTC_MONTH_AUGUST;
		else if(strcmp(result,"Sept") == 0)
			RTC_DataStruct.Month = RTC_MONTH_SEPTEMBER;
		else if(strcmp(result,"Oct") == 0)
			RTC_DataStruct.Month = RTC_MONTH_OCTOBER;
		else if(strcmp(result,"Nov") == 0)
			RTC_DataStruct.Month = RTC_MONTH_NOVEMBER;
		else if(strcmp(result,"Dec") == 0)
			RTC_DataStruct.Month = RTC_MONTH_DECEMBER;
		p++;	//跳过空格
		//设置日
		for(i=0; *p != ' ' && *p != '\t'; i++)
		{
			result[i] = *p++;
		}
		RTC_DataStruct.Date = (result[0]-'0')*16 + (result[1]-'0');
		p++;	//跳过空格
		//设置小时
		for(i=0; *p != ':'; i++)
		{
			result[i] = *p++;
		}
		RTC_TimeStruct.Hours = (result[0]-'0')*10 + (result[1]-'0');
		p++;	//跳过:
		//设置分钟
		for(i=0; *p != ':'; i++)
		{
			result[i] = *p++;
		}
		RTC_TimeStruct.Minutes = (result[0]-'0')*10 + (result[1]-'0');
		p++;	//跳过:
		//设置秒
		for(i=0; *p != ' ' && *p != '\t'; i++)
		{
			result[i] = *p++;
		}
		RTC_TimeStruct.Seconds = (result[0]-'0')*10 + (result[1]-'0'); 
		p++;	//跳过空格
		//设置年份
		for(i=0; i<4; i++)
		{
			result[i] = *p++;
		}
		RTC_DataStruct.Year = (result[2]-'0')*16 + (result[3]-'0');
		RTC_DataStruct.WeekDay = RTC_WEEKDAY_TUESDAY;
		HAL_RTC_SetTime(&hrtc,&RTC_TimeStruct,RTC_FORMAT_BIN);	//设置时间
		HAL_RTC_SetDate(&hrtc,&RTC_DataStruct,RTC_FORMAT_BCD);	//设置日期

上电后获取完了网络时间并设置到RTC时钟后就设置RTC的闹钟时间为当前时间+1分钟,让STM32进入停止模式来降低功耗,设置的RTC闹钟中断就会让STM32从低功耗中唤醒,在闹钟中断里我们可以执行墨水屏刷新时间的操作后再重新设置闹钟时间和进入低功耗。这样就可以实现每隔一分钟墨水屏刷新时间。当走过一个小时后就再获取一次网络时间和天气信息。

//设置下一次闹钟时间
	if(RTC_TimeStruct.Minutes == 59)
	{
		if(RTC_TimeStruct.Hours == 23)
			RTC_SetAlarm(0,0,0);
		else
			RTC_SetAlarm(RTC_TimeStruct.Hours+1,0,0);			
	}
	else
	{
		RTC_SetAlarm(RTC_TimeStruct.Hours,RTC_TimeStruct.Minutes+1,0);
	}
	
	while(1)
	{
		if(Alarm_Flag == 1)
		{
			Alarm_Flag = 0;	//清除闹钟标志位
			RTC_Alarm();	//闹钟事件处理
			if(Updata_Flag == EPD_PART)	//局部刷新
			{
				Updata_Flag = 0;	//清除刷新标志位
				GUI_Display_Part();
			}
			else if(Updata_Flag == EPD_FULL)	//全局刷新
			{
				Updata_Flag = 0;	//清除刷新标志位
				GUI_Display_All();
			}
			else if(Updata_Flag == EPD_SLEEP)	//休眠页面
			{
				Updata_Flag = 0;
				GUI_Display_Sleep();
			}
			printf("%d-%02d-%02d %d\r\n",RTC_DataStruct.Year+2000,RTC_DataStruct.Month,RTC_DataStruct.Date,RTC_DataStruct.WeekDay);
			printf("%02d:%02d:%02d\r\n",RTC_TimeStruct.Hours,RTC_TimeStruct.Minutes,RTC_TimeStruct.Seconds);
			//设置下一次闹钟时间
			if(RTC_TimeStruct.Hours>=1 && RTC_TimeStruct.Hours<=6)
				RTC_SetAlarm(6,59,55);
			else
				RTC_SetAlarm(RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds+55);
			Sys_Enter_Stop();	//系统进入停止模式
		}
	}

//RTC闹钟事件处理
void RTC_Alarm(void)
{
	printf("WK_UP\r\n");
	do
	{
		HAL_RTC_GetTime(&hrtc,&RTC_TimeStruct,RTC_FORMAT_BIN);	//获取RTC时间
		HAL_Delay(250);
	}while(Paint_time.Min == RTC_TimeStruct.Minutes);	//等待分钟更新
	
	if(Paint_time.Hour != RTC_TimeStruct.Hours)	//每小时全局刷新一次
	{
		//凌晨时间,墨水屏休眠
		if(RTC_TimeStruct.Hours>=1 && RTC_TimeStruct.Hours<=6)
		{
			Updata_Flag = EPD_SLEEP;
		}
		else
		{
			Updata_Flag = EPD_FULL;		//全局刷新标志位
			Get_Net_Time();				//每小时获取网络时间		
			Get_Weather();				//每小时更新天气信息
		}
	}
	else
	{
		Updata_Flag = EPD_PART;		//局部刷新标志位
	}
}

//系统进入停止模式
void Sys_Enter_Stop(void)
{
	printf("go to sleep\r\n");
	__HAL_RCC_PWR_CLK_ENABLE();			//使能PWR时钟
	__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);	//清除唤醒标志
	HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_STOPENTRY_WFI);		//进入待机模式
}

//RTC闹钟中断服务函数
void RTC_Alarm_IRQHandler(void)
{
	HAL_RTC_AlarmIRQHandler(&hrtc);
}

//RTC闹钟唤醒中断回调函数
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *RTC_Handle)
{
	SystemClock_Config();	//唤醒后要初始化时钟配置
	Alarm_Flag = 1;			//标志位置一
	__HAL_RTC_ALARM_EXTI_CLEAR_FLAG();
}

获取实时天气

利用ESP8266TCP连接来天气网站API获取天气信息,怎么连接天气API还是参考上面提到的另一篇博客。这里还是介绍怎么解析数据,并把解析到的天气代码,温度湿度放到一个结构体中管理,方便后续读出数据进行显示。

//存储天气信息的结构体
typedef struct{
	uint8_t icon;
	char Tempera[4];
	char Humidity[4];
} PAIN_WEATHER;

//建立TCP连接,并开启透传,进行HTTP请求
uint8_t TCP_Connect(char *IP,char *URL)
{	
	uint8_t res = 0;
	USART2_RX_STA = 0;
	u2_printf("AT+CIPSTART=\"TCP\",\"%s\",80\r\n",IP);
	HAL_Delay(500);
	if(Send_Command("AT+CIPSTATUS","TCP",20))	//检查TCP是否连接
	{
		res = 1;
		Send_Command("AT+CIPMODE=1","OK",20);	//开启透传模式
		Send_Command("AT+CIPSEND",">",20);		//开始传输
		HAL_Delay(200);
		USART2_RX_STA = 0;
		u2_printf("GET %s\r\n",URL);
		HAL_Delay(200);
		strcpy(Rcv_Str,(const char*)USART2_RX_BUF);
	}
	return res;
}

//关闭透传并断开TCP连接
void TCP_Disconnect(void)
{
	//退出发送模式
	while((USART2->SR&0X40)==0);	//等待发送空
	USART2->DR='+';      
	HAL_Delay(15);					//大于串口组帧时间(10ms)
	while((USART2->SR&0X40)==0);	//等待发送空
	USART2->DR='+';      
	HAL_Delay(15);					//大于串口组帧时间(10ms)
	while((USART2->SR&0X40)==0);	//等待发送空
	USART2->DR='+';      
	HAL_Delay(1000);					//等待1s
	//while(!Send_Command("AT","OK",20));//退出透传判断.
	//关闭透传模式
	Send_Command("AT+CIPMODE=0","OK",20);
	//断开TCP连接
	Send_Command("AT+CIPCLOSE","OK",20);
}

//解析GET请求返回的数据
void Weather_DataParsing(char *reqRes, char *keywords, char *keyval)
{
	char *p1 = NULL;
	char *p2 = NULL;
	if(strstr(reqRes,"Sucess") != NULL)
	{
		p1 = strstr(reqRes, keywords);  //查找关键词
        if(p1)
        {
            p1 += strlen(keywords) + 3;
            p2 = strstr(p1, "\"");      //查找末端的 " 
            strncpy(keyval, p1, p2 - p1); //拷贝数据
        }
	}
}

void Get_Weather(void)
{
	char result[16] = "NULL";
	//连接天气API获取天气信息
	if(!TCP_Connect("api.yytianqi.com",
	"http://api.yytianqi.com/observe?city=CH281101&key=72r8t4knnk32g8s9\r\n"))
	{
		Paint_weather.Tempera[0] = '?';
		Paint_weather.Tempera[1] = '?';
		Paint_weather.Tempera[2] = 'C';
		Paint_weather.Humidity[0] = '?';
		Paint_weather.Humidity[1] = '?';
		Paint_weather.Humidity[2] = '%';
	}
	
	//获取气温
	Weather_DataParsing(Rcv_Str,"qw",result);
	if(result[1] == 'U')	//气温低于10度处理
	{
		Paint_weather.Tempera[0] = result[0];
		Paint_weather.Tempera[1] = 'C';
		Paint_weather.Tempera[2] = '\0';
	}
	else
	{
		Paint_weather.Tempera[0] = result[0];
		Paint_weather.Tempera[1] = result[1];
		Paint_weather.Tempera[2] = 'C';
	}
	
	//获取湿度
	Weather_DataParsing(Rcv_Str,"sd",result);
	Paint_weather.Humidity[0] = result[0];
	Paint_weather.Humidity[1] = result[1];
	Paint_weather.Humidity[2] = '%';
	
	//获取天气代码
	Weather_DataParsing(Rcv_Str,"numtq",result);
	Paint_weather.icon = (result[0]-'0')*10 + (result[1]-'0');
	
	printf("Rcv:%s\r\n",Rcv_Str);
	printf("%sC\t%s\r\n",Paint_weather.Tempera,Paint_weather.Humidity);
	HAL_Delay(1000);
	TCP_Disconnect();	//断开TCP连接
}

智能配网

ESP8266的智能配网指由外部设备(如手机)向 外部广播含有 SSID 和密码(PSW)的WiFi信息的报文,ESP8266获取到该报文就可以连接到WiFi了。使用AT+CWSTARTSMART开启 SmartConfig,使用AT+CWSTOPSMART停止 SmartConfig 。需要注意的是,在开启智能配网时不要执行其他的AT指令,无论配置成功与否都要及时停止智能配网。而且在实际使用中发现,如果上一次未配置成功即使重新上电也会影响下一次智能配网的开启,所以每次使用完都要调用停止智能配网。
具体操作流程是,系统上电后检测是否连接WiFi,未连接则显示智能配网的二维码,同时开启智能配网,监听报文。当用户输入WiFi的信息后,并且接收到报文就会连接WiFi,连接成功就会返回smartconfig connected wifi等一系列数据,就是通过判断是否接收到smartconfig connected wifi的应答来判断是否成功连接。
物联网小项目——墨水屏时钟(STM32+ESP8266实现)

//检查WIFI是否连接
uint8_t Check_WIFI(void)
{
	if(Send_Command("AT+CWJAP_DEF?","No AP",20))
	{
		printf("WIFI未连接\r\n");
		return 0;
	}
	else
	{
		printf("WIFI已连接\r\n");
		return 1;
	}
}

uint8_t WIFI_SmartConfig(uint32_t waittime)
{
	uint8_t res = 0;
	
	//开启station模式
	if(!Send_Command("AT+CWMODE?","1",20))
	{
		Send_Command("AT+CWMODE=1","OK",20);
	}
	//退出smartconfig,防止上一次未退出
	Send_Command("AT+CWSTOPSMART", "OK", 50);
	//开启smartconfig
	if(Send_Command("AT+CWSTARTSMART", "OK", 50))
	{
		//printf("%s\r\n",USART2_RX_BUF);
		while(waittime--)
		{
			HAL_Delay(10);
			if(USART2_RX_STA & 0x8000)
			{
				printf("%s\r\n",USART2_RX_BUF);
				if(Check_Command("smartconfig connected wifi"))
				{
					res = 1;
					HAL_Delay(500);
					break;	
				}
				USART2_RX_STA=0;
			}
			if(waittime == 0)
				printf("Timeout\r\n");
		}
		if(Send_Command("AT+CWSTOPSMART", "OK", 50))
		{
			printf("Stop smartconfig\r\n");
		}
		else
		{
			printf("smartconfig stop error\r\n");
		}
	}
	else
	{
		printf("smartconfig open error\r\n");
	}
	return res;
}

墨水屏的显示

墨水屏的显示关键在于调用GUI_Paint里的各种画图接口来显示图片,数字,字母,中文等。这里用墨水屏的局部刷新为例子。
首先需要事先申请开辟一块空间用于存储画点的数据,调用Paint_NewImage函数创建一幅新的图像。

uint8_t	*BlackImage;
uint16_t Imagesize = ((EPD_WIDTH % 8 == 0)? (EPD_WIDTH / 8 ): (EPD_WIDTH / 8 + 1)) * EPD_HEIGHT;//申请空间
	if((BlackImage = (uint8_t *)malloc(Imagesize)) == NULL)
		return -1;
	Paint_NewImage(BlackImage, EPD_WIDTH, EPD_HEIGHT, 270, WHITE);	//创建新的图像

然后调用DEV_Module_Init初始化模块,EPD_Init确定刷新墨水屏的模式是局部刷新还是全局刷新,Paint_SelectImage选择刚刚申请的内存空间为刷新数据。然后就可以调用具体的画图函数去显示自己想要显示的内容即可,最后调用EPD_Display显示图片,调用EPD_SleepDEV_Module_Exit让墨水屏进入休眠即可。文章来源地址https://www.toymoban.com/news/detail-492013.html

//屏幕部分刷新
void GUI_Display_Part(void)
{
	DEV_Module_Init();
	EPD_Init(EPD_PART);
	Paint_SelectImage(BlackImage);
	
	RTC_GetTime();	//获取RTC时间
	//刷新时间
	Paint_ClearWindows(5, 50, 5 + FontNum.Width * 5-5, 50 + FontNum.Height, WHITE);
	Paint_DrawTime(5, 50, &Paint_time, &FontNum, WHITE, BLACK);
	
	//刷新WIFI连接状态
	Paint_ClearWindows(90,30,90 + 24,30 + 24,WHITE);
	if(Check_WIFI())
		Paint_DrawBitMap_Paste(gImage_WIFI_24,90,30,24,24,1);
	else
		Paint_DrawBitMap_Paste(gImage_NoWIFI_24,90,30,24,24,1);
	
	EPD_Display(BlackImage);
	EPD_Sleep();
	DEV_Module_Exit();
}

到了这里,关于物联网小项目——墨水屏时钟(STM32+ESP8266实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32+ESP8266水墨屏天气时钟:ESP8266连接心知天气获取数据

    利用STM32F103C8T6和ESP8266模块进行通信,获取心知天气的数据。 硬件设计为串口1(PA9和PA10)连接ESP8266. 串口2打印 ESP8266模块可以通过AT指令控制搭配使用源代码API函数开发,总体开发速度快,难度较低。 说明:下面仅列举一些最常用的AT指令及用法,指令的详细参数及使用说明请

    2024年04月12日
    浏览(37)
  • STM32+ESP8266水墨屏天气时钟:简易多级菜单(数组查表法)

    本次的水墨屏幕项目需要做一个多级菜单的显示,所以写出来一起学习,本篇文章不单单适合于水墨屏,像0.96OLED屏幕也适用,区别就是修改显示函数。 多级菜单的实现,一般有两种实现的方法 1.通过双向链表实现 2.通过数组查表实现 两种方法的思路都是把所有的界面连接在

    2024年04月10日
    浏览(45)
  • 从零开始制作一个基于STM32和ESP8266-01S的智能时钟(3)ESP8266-01S模块(上)

    提示:这里可以添加本文要记录的大概内容:之前在忙着,现在继续补充完整,然后这次的ESP-01S的典型应用图是没有连接RST引脚的,但是我的项目是用到了RST引脚的,所以需要使用跳线连接一下RST引脚。 本项目需要基础的stm32单片机知识,这里我推荐 链接:https://www.bilibil

    2024年02月03日
    浏览(51)
  • 使用micropython(ESP8266、ESP32)驱动SES 2.66寸墨水屏显示中文

    由于需要做一些低功耗的东西,所以最近在尝试玩墨水屏。出于成本考虑(没钱的另一种委婉说法)从咸鱼淘到2块便宜的二手SES 2.66寸三色墨水屏,并使用micropython将其驱动起来,并用字库的方法显示中文。 1.硬件连线 SES 2.66墨水屏 SES 2.66墨水屏带驱动小板 买到的屏幕是图上

    2024年01月22日
    浏览(35)
  • 【物联网】手把手完整实现STM32+ESP8266+MQTT+阿里云+APP应用——第3节-云产品流转配置

    本节目标: 本节目标是进行云产品流转配置为后面实际的手机APP的接入做铺垫。云产品流转配置的目的是为了后面能够让后面实际做出来的手机APP可以控制STM32/MCU,STM32/MCU可以将数据发给实际的手机APP。 配置步骤主要分为三步: 1.创建数据源;2.创建数据目的;3.创建解析器

    2024年02月03日
    浏览(57)
  • STM32 ESP8266 物联网智能温室大棚 (附源码 PCB 原理图 设计文档)_stm32 esp8266 onenet 温室

    系统启动后,单片机控制相关传感器进行环境参数的采集,将数据传回单片机处理后,通过OLED显示屏将相关环境指数实时显示。用户可以在手机端打开APP与本系统进行通信,更加便捷地查看监测数据。结构框图如下所示。 硬件部分包含主控芯片、传感器模块,OLED模块,WIF

    2024年04月23日
    浏览(49)
  • 第十章 STM32+ESP8266接入机智云 实现小型IOT智能家居项目

    前言 最近有不少小伙伴私信留言,想要我推出一章能够通过APP进行远程控制并获取传感器信息的实验教程。说实话在嵌入式毕设里边,这算是中等偏上水平的了。刚好我也有兴趣写写。全篇4700多字,我写的很详细,按着文章一步一步操作即可。(建议跟同学集资购买模块,

    2024年02月03日
    浏览(43)
  • STM32 标准库+ESP8266+华为云物联网平台

    文章内容:     STM32标准库通过串口发送AT指令完成与ESP8266的控制实现接入华为云物联网平台,并完成基本通信与控制,包括设备属性上报和命令下发解析与响应,并将相关代码打包成HuaweiIOT_at_esp8266.c和HuaweiIOT_at_esp8266.h驱动文件。 一、华为云物联网平台 创建 产品与设备

    2024年02月12日
    浏览(51)
  • STM32 HAL库+ESP8266+华为云物联网平台

    文章内容:     STM32 HAL库通过串口发送AT指令完成与ESP8266的控制实现接入华为云物联网平台,并完成基本通信与控制,包括设备属性上报和命令下发解析与响应。     文末获取 “STM32 HAL库+ESP8266+华为云物联网平台keil工程 ”下载的链接。 一、华为云物联网平台 创建 产品

    2024年02月14日
    浏览(54)
  • ESP8266 -- STM32与阿里云物联网平台建立通信(四)

    目录 链接快速定位 前沿 1 准备工作 2 硬件环境介绍 3 软件环境介绍 3.1 串口初始化及配置 3.2 编写AT MQTT指令代码 3.2.1 ESP8266_Cmd函数介绍 3.2.2 wifi连接函数介绍 3.2.3 云端连接语句介绍 3.2.4 环回消息测试语句介绍 3.2.5 属性上报语句介绍 3.2.6 设置属性语句介绍 4 实验现象 4.1 代码

    2024年02月04日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包