cubemx stm32 陶晶驰 串口屏 基于YXY通信原理的串口屏驱动代码

cubemx stm32 陶晶驰 串口屏 基于YXY通信原理的串口屏驱动代码串口屏通信_陶晶驰x2

陶晶驰串口屏

资料

陶晶驰串口屏是本质是一个MCU,屏幕是MCU的模块,一般是一块TFT屏幕。在串口屏厂商提供的软件上面编写界面,然后通过串口直接烧到串口屏的MCU上,然后在屏幕上展示出来。

串口屏实物

串口屏资料中心传送门入口

串口屏资料中心

使用方法

串口屏资料中心传送门入口(详细使用方法请关注资料中心)

YXY通信

YXY通信是专门为串口屏开发的一种通信方法

YXY通信把数据分为了三个部分,分别是数据id、数据、数据尾,没错就这三个简单吧,甚至没有打包解包的过程,比市面上的一众通信原理都简单。

在这里插入图片描述

数据id是用来区分是哪个模块,发过来的数据,比如我要做一个智能家居,智能家居,要做空调,要做窗帘,要做扫地机器人,那我就分别给他定义数据id,比如空调是0x11,风扇是0x12,扫地机器人是0x13,当串口屏给外部MCU发送0x11时,我就知道,用户在串口屏上操作了空调部分,获取了操作后的数据,我再到对应的地方去编写对应的代码,就可以实现由串口屏到模块的直接控制。

在这里插入图片描述

串口屏软件上数据发送部分

直接上例子

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

就这几个例子吧,后面之恶极上工程

cubemx配置

1.开一个串口(开串口中断)
在这里插入图片描述
在这里插入图片描述

代码部分

我是直接把我之前做的工程的代码拿过来了,最后面附上整个工程的源码,这里仅供参考。

UART_Screen.c

#include "UART_Screen.h"
#include "O_redirect.h"
#include "yxy_delay.h"
#include "usart.h"
#include "string.h"
#include "stdbool.h"

#include "UserHand.h"
#include "esp8266.h"
#include "errorType.h"



HMI_Struct HMI_InitStr;
HMI_SetTime hmiSetTime;


/*发送数字或字符串给串口屏*/
// ConData是串口屏的控制命令格式
// Data是对该命令格式赋予的数据
// DataType是发送的是字符数字还是字符串 0是数字,1是字符串
void HMI_SendData(uint8_t *ConData, uint8_t DataType, void * Data)
{ 
   
	U_Printf(HMI_print, "%s", ConData);
// U_Printf(U_UART1, "%s\r\n", ConData);
	
	switch(DataType)
	{ 
   
		case HMI_NUM:
		{ 
   
			uint16_t Num = *((uint16_t *)Data);

			U_Printf(HMI_print, "%d", Num);
// U_Printf(U_UART1, "Num : %d\r\n", Num); 
		}break;
		
		case HMI_STRING:
		{ 
   
			uint8_t * text = (uint8_t *)Data;
			uint8_t sz = 0;
			
			while(*(text+sz) != 255)
			{ 
   
				sz++;
			}
			
			U_Printf(U_UART1, "sz : %d\r\n", sz);
			
			U_Printf(HMI_print, "\"");
			for(int i=0; i<sz; i++)
			{ 
   
				U_Printf(HMI_print, "%c", text[i]);
			}
			U_Printf(HMI_print, "\"");
		}break;
	}

	U_Printf(HMI_print, "\xff\xff\xff");
}

/* 串口屏跳转页面函数 */
// Data 是要跳转的页面名字
void HMI_SendData(uint8_t* Data)
{ 
   
	U_Printf(HMI_print, "page %s\xff\xff\xff", Data);
}


/* * 函数名:HMI_Init * 描述 :串口屏数据与串口初始化 * 输入 :无 * 返回 :无 * 调用 :无 */
void HMI_Init(void)
{ 
   
	HMI_InitStr.HMI_cnt = 0;
	HMI_InitStr.a_HMI_buf=0;
	HMI_InitStr.HMI_cntPre=0;
	memset(HMI_InitStr.HMI_buf, 0, sizeof(HMI_InitStr.HMI_buf));
	
	HAL_UART_Receive_IT(&HMI_huart, (uint8_t *)&(HMI_InitStr.a_HMI_buf), 1);//开启接收中断
}

/* * 函数名:HMI_Clear * 描述 :清空缓冲区,以及接收计数 * 输入 :无 * 返回 :无 * 调用 :无 */
void HMI_Clear(void)
{ 
   
	memset(HMI_InitStr.HMI_buf, 0, sizeof(HMI_InitStr.HMI_buf));//清空缓冲区,全部填0
	HMI_InitStr.a_HMI_buf = 0;
	HMI_InitStr.HMI_cnt = 0;//清空缓存区计数
	HMI_InitStr.HMI_cntPre = 0;//清空
}

/*内部函数声明*/
static void LoginDataProcess(void);
static void M_C_DataProcess(void);
static void DisinfectDataProcess(void);
static void CurtainDataProcess(void);
static void InternetDataProcess(void);


/*串口屏解包函数*/
void HMI_UnPack(void)
{ 
   
	switch(HMI_InitStr.HMI_buf[0])
	{ 
   
		case HMI_MAIN:
			U_Printf(U_UART1, "这里是main界面\r\n");
		break;
		case HMI_LOGIN:
			U_Printf(U_UART1, "这里是login界面\r\n");
			LoginDataProcess();
		break;
		case HMI_PASS_CHANGE:
			U_Printf(U_UART1, "这里是password change界面\r\n");
			LoginDataProcess();
		break;
		case HMI_LOGIN_SUCC:
			U_Printf(U_UART1, "这里是login succeed界面\r\n");
		break;
		case HMI_LOGIN_FAIL:
			U_Printf(U_UART1, "这里是login fail界面\r\n");
		break;
		case HMI_MEDICINE_CHEST:
			U_Printf(U_UART1, "这里是mediciness chest界面\r\n");
			M_C_DataProcess();
		break;
		case HMI_DISINFECT:
			U_Printf(U_UART1, "这里是disinfect界面\r\n");
			DisinfectDataProcess();
		break;
		case HMI_CURTAIN:
			U_Printf(U_UART1, "这里是curtain界面\r\n");
			CurtainDataProcess();
		break;
		case HMI_INTERNET:
			U_Printf(U_UART1, "这里是internet界面\r\n");
			InternetDataProcess();
		break;
		default:
			
		break;
	}

	HMI_Clear();	//清空缓存
}

/*密码数据处理函数*/
static void LoginDataProcess(void)
{ 
   
	uint8_t tx[] = "va0.txt=";
	uint8_t UserPass[PASS_LENG_MAX+1];
	uint8_t i = 2;
	
	memset(UserPass, 255, sizeof(UserPass));
	
	switch(HMI_InitStr.HMI_buf[1])
	{ 
   
		case Get_PASS:		//获取单片机上存储的密码
		{ 
   
			U_Printf(U_UART1, "login中 的 Get_PASS\r\n");
			
			UserGetPassword(UserPass);
			UserPass[PASS_LENG_MAX] = '\0';
			U_Printf(U_UART1, "UserPass:%s\r\n", UserPass);

			HMI_SendData(tx, HMI_STRING, (void *)(UserPass));
		}break;
		case CHANGE_PASS:	//修改单片机上存储的密码
		{ 
   
			U_Printf(U_UART1, "login中 的 CHANGE_PASS\r\n");
		
			curPassLen=0;
			while(*(HMI_InitStr.HMI_buf + i) != 0xff)
			{ 
   
				curPassLen++;
				i++;
			}
			Wrinte_EEPOM(PASS_LEN, curPassLen);	//密码长度存储
			
			U_Printf(U_UART1, "UserPass:%s, Cnt : %d \r\n", HMI_InitStr.HMI_buf+2, curPassLen);
			
			UserSetPassword(((uint8_t *)(HMI_InitStr.HMI_buf+2)), curPassLen);	//cnt减去一级id,二级id 和 包尾
		}break;
		case RESET_PASS:	//重置单片机上的密码为1111
		{ 
   
			U_Printf(U_UART1, "login中 的 RESET_PASS\r\n");
			uint8_t ResPass[] = "1111";
			UserSetPassword((uint8_t *)ResPass, 4);
			curPassLen = 4;
			Wrinte_EEPOM(PASS_LEN, curPassLen);	//密码长度存储
		}break;
		default:
			U_Printf(U_UART1, "0x%x\r\n", HMI_InitStr.HMI_buf[1]);
		break;
	}
}

/*药箱数据处理函数*/
static void M_C_DataProcess(void)
{ 
   
	switch(HMI_InitStr.HMI_buf[1])
	{ 
   
		case MC_SW_ON_OFF:
			U_Printf(U_UART1, "mediciness chest 的 MC_SW_ON_OFF\r\n");
			switch(HMI_InitStr.HMI_buf[2])
			{ 
   
				case 1:
					U_Printf(U_UART1, "va0 : %d\r\n", HMI_InitStr.HMI_buf[3]);
					if(HMI_InitStr.HMI_buf[3] == MC_Close)
					{ 
   
						SG90_Ch_Degrees(sg90_Ch1, Degrees135);
					}
					else if(HMI_InitStr.HMI_buf[3] == MC_Open)
					{ 
   
						SG90_Ch_Degrees(sg90_Ch1, Degrees0);
					}
				break;
				case 2:
					U_Printf(U_UART1, "va1 : %d\r\n", HMI_InitStr.HMI_buf[3]);
					if(HMI_InitStr.HMI_buf[3] == MC_Close)
					{ 
   
						SG90_Ch_Degrees(sg90_Ch2, Degrees135);
					}
					else if(HMI_InitStr.HMI_buf[3] == MC_Open)
					{ 
   
						SG90_Ch_Degrees(sg90_Ch2, Degrees0);
					}
				break;
				default:
				break;
			}
		break;
		case Get_MC_Val:
		{ 
   
			U_Printf(U_UART1, "mediciness chest 的 Get_MC_Val\r\n");
			uint8_t tx0[] = "va0.val=";
			
			uint16_t Num = MC_Close;
			if(Get_MC_flag(sg90_Ch1) == MC_Open)
			{ 
   
				Num = MC_Open;
			}
			HMI_SendData(tx0, HMI_NUM, &Num);	// 获取药箱数据
			
			// 获取吃药时间数据
			uint8_t tx2[] = "h0.val=";
			uint8_t tx3[] = "h1.val=";
			uint8_t tx4[] = "h2.val=";
			uint8_t tx5[] = "t5.txt=";
			uint8_t tx6[30];
			sprintf((char *)tx6, "定时时间:%2d:%2d:%2d", hmiSetTime.hmi_hour[HMI_MC_Num], 
				hmiSetTime.hmi_min[HMI_MC_Num], 
				hmiSetTime.hmi_sec[HMI_MC_Num]);
			
			HMI_SendData(tx2, HMI_NUM, &hmiSetTime.hmi_hour[HMI_MC_Num]);
			HMI_SendData(tx3, HMI_NUM, &hmiSetTime.hmi_min[HMI_MC_Num]);
			HMI_SendData(tx4, HMI_NUM, &hmiSetTime.hmi_sec[HMI_MC_Num]);
			HMI_SendData(tx5, HMI_STRING, (void *)tx6);
		}break;
		case Set_Med_Time:
		{ 
   
			U_Printf(U_UART1, "mediciness chest 的 Set_Med_Time\r\n");
			hmiSetTime.hmi_hour[HMI_MC_Num] = HMI_InitStr.HMI_buf[2];
			hmiSetTime.hmi_min[HMI_MC_Num]  = HMI_InitStr.HMI_buf[3];
			hmiSetTime.hmi_sec[HMI_MC_Num]  = HMI_InitStr.HMI_buf[4];
			
			hmiSetTime.hmi_flag &= ~(1<<(HMI_MC_Num));	// 清除标志位
			
			U_Printf(U_UART1, "Set_Med_Time: %d:%d:%d\r\n", hmiSetTime.hmi_hour[HMI_MC_Num], 
			hmiSetTime.hmi_min[HMI_MC_Num], hmiSetTime.hmi_sec[HMI_MC_Num]);
		
		}break;
		case In_Med_Interface:
		{ 
   
			U_Printf(U_UART1, "mediciness chest 的 In_Med_Interface\r\n");
// U_Printf(U_UART1, "HMI_InitStr.HMI_buf[2] : %d\r\n", HMI_InitStr.HMI_buf[2]);
			
			switch(HMI_InitStr.HMI_buf[2])
			{ 
   
				case 0x01:
					BeepRing(1);
					yxy_delay_ms(200);
					BeepRing(0);
				break;
				case 0x02:
					hmiSetTime.hmi_flag |= 1<<(HMI_MC_Num);	// 闹铃消除标志位
					hmiSetTime.hmi_lastTime = esp_time.esp_hour*60 + esp_time.esp_min; // 一定时间不响闹铃
				break;
			}
		}break;
		default:
		break;
	}
}

/*紫外线消毒数据处理函数*/
static void DisinfectDataProcess(void)
{ 
   
	switch(HMI_InitStr.HMI_buf[1])
	{ 
   
		case D_SW_ON_OFF:
			switch(HMI_InitStr.HMI_buf[2])
			{ 
   
				case 0x00:
					No_Disinfection;
					TIM5->CCR1 = 10000;
				break;
				case 0x01:
					LowDisinfection;
					TIM5->CCR1 = 6666;
				break;
				case 0x02:
					ModDisinfection;
					TIM5->CCR1 = 3333;
				break;
				case 0x03:
					HigDisinfection;
					TIM5->CCR1 = 0;
				break;
				default:
					No_Disinfection;
					TIM5->CCR1 = 0;
				break;
			}
		break;
		case Get_LED_Val:
		{ 
   
			uint8_t tx[] = "h0.val=";
			uint16_t Num;
			Num = UV2_State();
			HMI_SendData(tx, HMI_NUM, &Num);
		}break;
		default:
		break;
	}
}

/*窗帘数据处理函数*/
static void CurtainDataProcess(void)
{ 
   
	switch(HMI_InitStr.HMI_buf[1])
	{ 
   
		case C_SW_ON_OFF:
		{ 
   
			U_Printf(U_UART1, "curtain 的 C_SW_ON_OFF\r\n");
			switch(HMI_InitStr.HMI_buf[2])
			{ 
   
				case 0x01:
					uln2003_MotorRotation(FORWARD);
					uln_flag = 1;
				break;
				case 0x02:
					uln2003_MotorRotation(REVERSE);
					uln_flag = 2;
				break;
				default:
					uln2003_MotorRotation(STOP_IT);
					uln_flag = 0;
				break;
			}
		}break;
		case Get_Cur_Val:
		{ 
   
			U_Printf(U_UART1, "curtain 的 Get_Cur_Val\r\n");
			
			uint8_t tx2[] = "h0.val=";
			uint8_t tx3[] = "h1.val=";
			uint8_t tx4[] = "h2.val=";
			uint8_t tx5[] = "t5.txt=";
			uint8_t tx6[30];
			sprintf((char *)tx6, "定时时间:%2d:%2d:%2d", hmiSetTime.hmi_hour[HMI_Cur_Num], 
				hmiSetTime.hmi_min[HMI_Cur_Num], hmiSetTime.hmi_sec[HMI_Cur_Num]);
			
			HMI_SendData(tx2, HMI_NUM, &hmiSetTime.hmi_hour[HMI_Cur_Num]);
			HMI_SendData(tx3, HMI_NUM, &hmiSetTime.hmi_min[HMI_Cur_Num]);
			HMI_SendData(tx4, HMI_NUM, &hmiSetTime.hmi_sec[HMI_Cur_Num]);
			HMI_SendData(tx5, HMI_STRING, (void *)tx6);
		}break;
		case Set_Cur_Time:
		{ 
   
			U_Printf(U_UART1, "curtain 的 Set_Cur_Time\r\n");
			
			hmiSetTime.hmi_hour[HMI_Cur_Num] = HMI_InitStr.HMI_buf[2];
			hmiSetTime.hmi_min[HMI_Cur_Num]  = HMI_InitStr.HMI_buf[3];
			hmiSetTime.hmi_sec[HMI_Cur_Num]  = HMI_InitStr.HMI_buf[4];
			
// hmiSetTime.hmi_flag &= ~(1<<(HMI_Cur_Num)); // 清除标志位
			
			U_Printf(U_UART1, "Set_Cur_Time: %d:%d:%d\r\n", hmiSetTime.hmi_hour[HMI_Cur_Num], 
			hmiSetTime.hmi_min[HMI_Cur_Num], hmiSetTime.hmi_sec[HMI_Cur_Num]);
			
			U_Printf(HMI_print, "page Curtain\xff\xff\xff");
		}break;
		default:
			
		break;
	}
}

/*联网数据处理函数*/
static void InternetDataProcess(void)
{ 
   
	uint16_t Len = 0;
	uint8_t ssid[20];
	uint8_t wifiPassword[20];

	
	switch(HMI_InitStr.HMI_buf[1])
	{ 
   
		case NETWORKING:
		{ 
   
			uint8_t tx[] = "main.p0.pic=";
			uint16_t Num = 40;
			
			ESP_flag &= ~ESP_IN_NETWORK;	// 清空联网标志位
			HMI_SendData(tx, HMI_NUM, &Num);// 显示未联网
			
			while(Len < HMI_InitStr.HMI_buf[2])
			{ 
   
				ssid[Len] = HMI_InitStr.HMI_buf[3+Len];
				Len++;
			}
			ssid[Len] = '\0';	// 字符串结尾符号
			
			Len = 0;
			while(Len < HMI_InitStr.HMI_buf[3 + HMI_InitStr.HMI_buf[2]])
			{ 
   
				wifiPassword[Len] = HMI_InitStr.HMI_buf[4 + HMI_InitStr.HMI_buf[2] + Len];
				Len++;
			}
			wifiPassword[Len] = '\0';	// 字符串结尾符号
			
			U_Printf(U_UART1, "ssidLen : %d password : %d\r\n", HMI_InitStr.HMI_buf[2], HMI_InitStr.HMI_buf[3 + HMI_InitStr.HMI_buf[2]]);
			U_Printf(U_UART1, "ssid : %s\r\npassword : %s\r\n", ssid, wifiPassword);
			
			ssidPass_wifi(ssid, wifiPassword);	// 配置esp 并联网
			
			U_Printf(HMI_print, "page main\xff\xff\xff");	// 联网成功后跳转到main界面
			
			if((ESP_flag&ESP_IN_NETWORK) == ESP_IN_NETWORK)	// 判断是否联网成功
			{ 
   
				Num = 41;
			}
			else
			{ 
   
				Num = 40;
			}
			
			HMI_SendData(tx, HMI_NUM, &Num);
			
		}break;
		
		default:
			
		break;
	}
}


/*HMI、esp8266串口中断函数*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{ 
   
	if(huart->Instance == HMI_UART)
	{ 
   
		if(HMI_InitStr.HMI_cnt >= HMI_BUF_SIZE)//溢出判断
		{ 
   
			HMI_InitStr.HMI_cnt = 0;
			memset(HMI_InitStr.HMI_buf, 0, sizeof(HMI_InitStr.HMI_buf));	//清零字符串
			U_Printf(U_UART1, "HMI data overflow\r\n");
		}
		else
		{ 
   	//数据存入
			HMI_InitStr.HMI_buf[HMI_InitStr.HMI_cnt] = HMI_InitStr.a_HMI_buf;
			HMI_InitStr.HMI_cnt++;
			
			if(HMI_InitStr.a_HMI_buf == HMI_PackTail)	//检测到包尾
				HMI_flag = 1;	// 解包函数准备启动
		}
		HAL_UART_Receive_IT(&HMI_huart, (uint8_t *)&(HMI_InitStr.a_HMI_buf), 1);   //再开启接收中断
	}
}


UART_Screen.h

#ifndef __UART_SCREEN_H_
#define __UART_SCREEN_H_

#include "stdint.h"

/*宏定义区*/
#define HMI_BUF_SIZE 127 //缓冲区大小

#define HMI_huart huart2
#define HMI_UART USART2
#define HMI_print U_UART2

#define HMI_PackTail 0xff // 包尾

#define TimeNumber 16
#define TimeRInit 0x70

/*枚举区*/

//页面id合集
typedef enum
{ 
   
	HMI_MAIN			= 0x01,	//主页面id

	HMI_LOGIN			= 0x70,	//密码登入页面id
	HMI_PASS_CHANGE		= 0x71,	//密码修改页面id
	HMI_LOGIN_SUCC		= 0x72,	//登入后界面id
	HMI_LOGIN_FAIL		= 0x73,	//登入失败界面id
	HMI_MEDICINE_CHEST	= 0x74,	//药箱界面id
	HMI_DISINFECT		= 0x75,	//紫外线界面id
	HMI_CURTAIN			= 0x76,	//床帘界面id
	HMI_INTERNET		= 0x77,	//联网页面

	MAX_MODULE_ID		= 0x80
}EnumPackID;

#define HMI_MC_Num (HMI_MEDICINE_CHEST - TimeRInit)
#define HMI_Cur_Num (HMI_CURTAIN - TimeRInit)

/*主页面数据与命令*/
//typedef enum
//{ 
   
// 
//}MainID;

/*修改密码界面操作命令*/
typedef enum
{ 
   
	Get_PASS	= 0x11,	//获取密码值
	CHANGE_PASS	= 0x12,	//修改密码
	RESET_PASS 	= 0x13	//重置密码为1111
}PasswordChangeID;

/*药箱界面操作*/
typedef enum
{ 
   
	MC_SW_ON_OFF	= 0x11, //药箱开关信号
	Get_MC_Val		= 0x12,	//获取当前单片机上的药箱数值情况
	Set_Med_Time	= 0x13,	//设置用药时间
	In_Med_Interface= 0x14	//在吃药界面
}MedicineChestID;

/*紫外灯界面操作*/
typedef enum
{ 
   
	D_SW_ON_OFF = 0x11, //紫外灯开关信号
	Get_LED_Val = 0x12	//获取当前单片机上的紫外线数值情况
}DisinfectID;

/*窗帘界面操作*/
typedef enum
{ 
   
	C_SW_ON_OFF = 0x11, //床帘开关信号
	Get_Cur_Val	= 0x12,	//获取当前单片机上的上窗帘时间数值
	Set_Cur_Time= 0x13,	//设置晚上睡觉时间
}CurtainID;

/*联网界面操作*/
typedef enum
{ 
   
	NETWORKING = 0x11 //联网信号
}InternetID;

/*给串口屏数据类型*/
typedef enum
{ 
   
	HMI_NUM  = 0,	//数字类型
	HMI_STRING		//字符串类型
}HMI_Data_Type;

/*结构体部分*/
/*单片机接收串口屏数据类型*/
typedef struct HMI_struct
{ 
   
	uint8_t 	HMI_buf[HMI_BUF_SIZE];	//数据缓冲存取区
	uint8_t 	a_HMI_buf;				//缓冲区元素暂存位置
	uint16_t 	HMI_cnt;				//当前接收计数
	uint8_t		HMI_cntPre;				//上次计数
}HMI_Struct;

/* //包 typedef struct { uint8_t packPageId; //用户自定义页面Id uint8_t packDataId; //二级页面内数据Id uint8_t arrData[10]; //10个数据元素 uint8_t packtail; //数据尾 }StructPackType; */

typedef struct hmiSet_Time
{ 
   
	uint8_t hmi_hour[TimeNumber];
	uint8_t hmi_min[TimeNumber];
	uint8_t hmi_sec[TimeNumber];
	uint16_t hmi_flag;
	uint16_t hmi_lastTime;
}HMI_SetTime;

extern HMI_SetTime hmiSetTime;

/*函数区*/
/*串口屏初始化以及数据接收处理部分*/
void HMI_Init(void);	//串口屏初始化
void HMI_UnPack(void);	//串口屏数据解包,并执行相应解包函数

/*单片机发送数据到串口屏部分*/	/*发送数字或字符串给串口屏*/
void HMI_SendData(uint8_t *ConData, uint8_t DataType, void * Data);


/* //函数用法 1、单片机发送数据到串口屏函数使用方法 uint8_t tx[] = "123"; uint8_t str[] = "12345"; uint16_t Num = 0; HMI_SendData(tx, HMI_STRING, (void *)(str)); HMI_SendData(tx, HMI_STRING, (void *)(&Num)); */



/*全局变量*/



#endif /* __UART_SCREEN_H_ */

初始化

HMI_Init();

效果展示

串口屏的智能家居

源码

链接:https://pan.baidu.com/s/1FYY1S2K6p81wKKVA_KCcxg?pwd=nkxs
提取码:nkxs

今天的文章cubemx stm32 陶晶驰 串口屏 基于YXY通信原理的串口屏驱动代码分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/60025.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注