基于51单片机的通讯聊天系统

这篇具有很好参考价值的文章主要介绍了基于51单片机的通讯聊天系统。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、实践的目的

通过编写51单片机通讯聊天程序,掌握51单片机的各个模块的知识点和运用C语言编写51单片机的能力。

二、实践内容

用51单片机与口袋开发板设计实现一个单片机与电脑串口助手实现通讯功能的程序。程序的主要功能如下:
1 OLED初始化显示Welcome to Bluetooth communication! 字符串。
2 程序开始时处于接收信息模式, 电脑串口助手发送信息时,将从初始化字符第一个开始显示,电脑串口助手发送信息后,蜂鸣器响铃2秒左右。
3 每次同时按下左右键时,可以轮流切换接收/发送信息模式
4 在发送信息模式时,可以显示光标(第一次处于发送信息模式时光标显示在OLED的左上角),可以通过左右键、上下键控制光标移动
5 在发送信息模式下, 每次同时按下上下键, 可以将光标选中的字符发送到电脑串口助手,发送完字符后, led流水灯流动两次。

三、实践依托的实验设备与软件

  1. 口袋实验室
  2. Aultium Designer
  3. 使用的开发软件 : keil4、stc-isp-15xx-v6.28烧录软件
  4. PC电脑

四、硬件原理图

基于51单片机的通讯聊天系统基于51单片机的通讯聊天系统

二、相关元器件特性分析

原器件名称 元器件特性简介
单片机 Stc89c52 系统运行的的核心
手柄板 系统运行的基础
OLED 可以显示字符或字符串
蜂鸣器 接收信息时,可以响铃
LED灯 D1-D8 发送信息后,流水灯流动两次后熄灭
独立按键 切换接收/发送模式,发送信息时控制光标移动
蓝牙模块 与手机实现通讯,显示单片机发送的字符或字符串

五、主要算法流程图及描述

基于51单片机的通讯聊天系统

六、问题的分析与编写程序步骤与实现的过程

1、通过蓝牙模块与手机APP“SPP蓝牙串口”实现连接

将HC蓝牙模块通过杜邦线与开发板进行接线的连接。接线的方式是:将蓝牙模块RXD、TXD、GND、VCC分别与单片机的TX(单片机的串口发送脚)、RX(单片机串口接收脚)、GND、+5V相连接。接好线后如下图所示

基于51单片机的通讯聊天系统
打开手机蓝牙串口APP选择蓝牙HC-5,连接成功后如下图所示
基于51单片机的通讯聊天系统

蓝牙模块的指示灯没有快闪,说明连接成功了。

2、创建工程与编写OLED显示字符串的程序

通过软件Keil uVision4创建51单片机实现通讯工程后,新建两个文件,分别命名为Oled.h头文件与Oled.c源文件。
Oled.h头文件将变量的定义户函数的声明包含进来。因为OLED已经有示例程序提供给我们了,所以由我们系统要实现的功能,将相关的函数声明从示例程序赋值过来。如下图所示
基于51单片机的通讯聊天系统
OLED_Init()、OLED_Fill()、OLED_CLS()、OLED_WrCmd(byte)、OLED_WrDat(byte)是OLED工作的重要函数。这些函数是OLED液晶显示屏显示文字或图像等的基础。我们系统要显示的是文字,所以用void OLED_P8x16Str(byte, byte, byte[])函数将要显示的数据写入OLED中就可以显示我们想要显示的数据了。void OLED_Set_Pos(byte, byte )函数是用来设置数据显示在OLED屏幕的何处。它可以将我们要显示的数据放在指定的位置显示。
Oled.c源文件是将Oled.h头文件的声明的函数实现实现具体的功能。
现在新建两个文件保存为Main.c的源文件盒Main.h的头文件。在Main.h头文件中编写如下的代码

#ifndef _Main_H_
#define _Main_H_

#include <reg52.h> 

#define UINT unsigned int
#define UCHAR unsigned char

UINT i, index = 0;

UCHAR dataChar;		 		 
UCHAR dataString[64] = {"Welcome to Bluetooth communication!"}; 	// 单片机接收信息时, 用数组存放接收的信息

#endif

在Main.c源文件中编写如下代码

#include "Main.h"
#include "Oled.h"

void main()
{
	OLED_Init();  		  // OLED初始化

	OLED_Fill(0x00);	  // OLED全屏

	while(1)
	{
		OLED_P8x16Str(0, 0, dataString);   // 显示单片机接收的字符或字符串
}
}

编译程序,将生成的.hex文件用STC烧写软件-ISP-V6.82E软件将烧入到单片机中,单片机运行的效果如下图所示
基于51单片机的通讯聊天系统
现在已经成功实现OLED显示字符串了。

3、通过串口通断实现发送信息于OLED屏幕显示

上一步我们实现了OLED显示字符串的功能。现在我们将用串口中断实现电脑串口助手发送字符或字符串信息后,OLED屏幕显示发送的字符或字符串,同时蜂鸣器响铃1秒左右。
首先进行编写的是串口中断处理的初始化程序。在Main.h中声明void timer_portInit(); 函数。然后在Main.c中编写void timer_portInit()函数,如下所示

void timer_portInit()
{
	SM0 = 0;				//设置串口为工作方式1
	SM1 = 1;

	TMOD=0X20;			//设置计数器工作方式2
	PCON=0X80;			//波特率加倍

	TH1=0XFa;			//计数器初始值设置,注意波特率是9600的
	TL1=0XFa;

	EA=1;						// 打开总中断

	ES=1;						// 打开串口中断
	REN = 1;						// 允许串口接收数据

	TR1=1;						// 打开定时器T1	
}

串口中断初始化程序已经编写完成了,现在我们编写串口中断处理的函数

void serialPort() interrupt 4
{
	dataChar = SBUF;	  			// 读入串口接收到的数据
	RI = 0;		  				// 中断标志位置零
	
dataString[index] = dataChar;		// 单片机接收的数据存放与数组中
	index++;
	
	}
}

中断处理程序编写完成,现在我们进行蜂鸣器在单片机接收信息后响铃2秒左右。在Main.h中定义sbit beep = P1^5; // 蜂鸣器,定义UINT beepTime = 300; UINT flagReceive = 0; 两个变量,分别对蜂鸣器响铃的时间进行控制、串口中断接收信息的标志控制蜂鸣器响铃,当flagReceive为1时就让蜂鸣器响铃。现在要改变串口中断处理程序的代码,将
dataString[index] = dataChar; // 单片机接收的数据存放与数组中
index++;
改成如下代码

if(funcSelect == 0)			// 单片机接收的数据存放与数组中
{
	dataString[index] = dataChar;	
	index++;
	
	flagReceive = 1;  		
}

现在在main函数中编写如下代码:在OLED_Fill(0x00); 语句的后面加入timer_portInit();语句,完成定时串口中断初始化。然后在while(1)循环中加入如下的代码

while(flagReceive == 1 && beepTime > 0)		 // 单片机接收信息后, 蜂鸣器响铃
	{
		beep = ~beep;      //字符串接收完成,蜂鸣器响
		delay(1);			   

		beepTime--;
	}
	beepTime = 300; 
	flagReceive = 0;

现在编译程序,将生成的hex文件烧入单片机中,电脑串口助手发送信息后的效果如下图所示
基于51单片机的通讯聊天系统

现在已经实现了通过串口通断实现发送信息于OLED屏幕显示,并且蜂鸣器响铃的功能了。

4、 OLED显示光标与按键控制光标移动

上一步我们通过实现了串口通断发送信息于OLED屏幕显示的功能,现在我们要实现系统处于发送模式时:OLED 屏幕显示光标;用按键进行接收/发送模式的切换;用按键控制光标的移动来选择我们要发送给电脑串口助手的字符数据。
首先是要实现的是发送/接收信息模式的功能,这个功能的实现是要用按键来处理模式转换的功能。在Main.h中我们定义按键的处理变量如下

sbit left = P2^1;	//向左按键
sbit right = P2^2;	//向右按键
sbit up = P2^0;     //向上按键
sbit down = P3^3;   //向下按键

这里我们定义了开发板上的按键A4、A5、A6、A7分别是变量left、right、up、down,完成了左右、上下键的的定义。进行模式切换时,是每次通过同时按下左右键可以进行接收/发送模式的转换。
现在我们要实现的是OLED屏幕显示光标。显示光标的功能是通过调用Oled.c文件中的OLED_WrDat(0xFF)函数来实现的。0xFF表示写入OLED的数据是在OLED屏幕上显示的是白底。它与OLED_Fill(0xFF);写入OLED命令的功能是一样的,在OLED屏幕上全屏显示白底的功能。用这个OLED_WrDat来显示光标的功能,提前就要设置光标显示在OLED 屏幕的何处。比如通过调用Oled.c文件中的OLED_Set_Pos(0,0)函数就设置了OLED的坐标于屏幕的左上角的开始位置处。然后通过调用OLED_WrDat(0xFF)就可以在屏幕的左上角的位置处显示一条细细的竖直线。我们显示的字符的宽度是8*16的字体,所以我们通过for循环来调用OLED_WrDat()函数就可以在OLED屏幕的显示字符处显示与字符同样大小的光标了。现在我们在Main.h文件中定义如下的数组变量并初始化

UCHAR code closeCursor[8]=					// 清除光标
{
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

UCHAR code openCursor[8]=					// 显示光标
{
	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};

我们通过调用OLED_WrDat(openCursor[i])函数就可以将数组中的数据写入OLED中了。
现在要实现的是按键处理的功能,在Main.h中定义如下的变量和声明函数

char funcSelect = 0;   			// 非 0 时发送信息模式
  char flagSend = 0;				// 非 0 时单片机发送信息
char keyX = 0, keyY = 0;   			// 光标显示的坐标

void keyLeftRight();	 			// 按键处理
void keyUpDown();

void sendData();  				// 单片机发送数据
void sendMode();				// 发送信息模式

keyX与keyY变量都初始化为0 ,第一次模式切换到发送模式时,通过调用OLED_Set_Pos(keyX, keyY); 语句就可以在OLED 屏幕左上角的位置处显示光标了,keyX与keyY变量的值是在按键处理中,每次通过按键进行改变上下左右移动改变时改变的。
funcSelect变量初始化为0,当我们每次同时按下左右键时,通过执行funcSelect = ~funcSelect;语句后,可以在0与非0之间变换。

现在进行左右键功能的编写,在Main.c中实现keyLeftRight的功能,其代码如下所示

void keyLeftRight()
{
	if(left == 0)  //按往左键时
	{
		delay(10);
		if(left == 0 && right == 0)	 	//左右键同时按下时, 进行接收/发送模式切换
		{							 	// funcSelect: 为0 是接收信息模式, 非0是发送信息模式
			funcSelect = ~funcSelect;
			if(funcSelect == 0)
			{
				OLED_CLS();
			}
		}
		else if(left == 0 && right != 0 && funcSelect != 0)  
		{
			OLED_Set_Pos(keyX, keyY);	
			for(i = 0; i < 8; i++)
				OLED_WrDat(closeCursor[i]); 	// 关闭当前的光标
	
			OLED_Set_Pos(keyX, keyY + 1);	
			for(i = 0; i < 8; i++)
				OLED_WrDat(closeCursor[i]);
	
			keyX -= 8;							// 改变光标X轴的位置
	
			if(keyX < 0)						
			{
				keyX = 120;
			}
		}
		while(!left); //消抖 
	}
	
	if(right == 0)  //按往右键时
	{
		if(funcSelect != 0)
		{
			OLED_Set_Pos(keyX, keyY);	
			for(i = 0; i < 8; i++)
				OLED_WrDat(closeCursor[i]); 
	
			OLED_Set_Pos(keyX, keyY + 1);	
			for(i = 0; i < 8; i++)
				OLED_WrDat(closeCursor[i]);
	
			keyX += 8;
	
			if(keyX > 120)
			{
				keyX = 0;
			}
		}
		while(!right); //消抖
	}	
}

keyLeftRight()函数的功能就是:通过每次按下左右的时,可以通过改变funcSelect的值来控制sendMode()函数功能的实现;分别按下左右键的时候就可以实现光标的左右移动和关闭移动之前显示的光标位置处的光标;执行keyX += 8; 语句之后,就可以改变keyX的值了,在主函数里面通过死循环不断的调用sendMode()函数就可显示keyX改变之后的坐标处的光标了。

现在进行上下键功能的编写,在Main.c中实现keyUpDown的功能,其代码如下所示

void keyUpDown()
{
	if(up == 0)  //按往上键时
	{
		if(up == 0 && down == 0)	//上下键同时按下时控制单片机发送字符
		{
			flagSend = 1;
		}
		else if(up == 0 && down != 0 && funcSelect != 0) 
		{
			OLED_Set_Pos(keyX, keyY);	
			for(i = 0; i < 8; i++)
				OLED_WrDat(closeCursor[i]); 
	
			OLED_Set_Pos(keyX, keyY + 1);	
			for(i = 0; i < 8; i++)
				OLED_WrDat(closeCursor[i]);
	
			keyY -= 2;
	
			if(keyY < 0)
			{
				keyY = 6;
			} 
		}
	}
	while(!up); //消抖
	
	if(down == 0)  //按往下键时
	{
		if(funcSelect != 0)
		{
			OLED_Set_Pos(keyX, keyY);	
			for(i = 0; i < 8; i++)
				OLED_WrDat(closeCursor[i]); 
	
			OLED_Set_Pos(keyX, keyY + 1);	
			for(i = 0; i < 8; i++)
				OLED_WrDat(closeCursor[i]);
	
			keyY += 2;
	
			if(keyY > 6)
			{
				keyY = 0;
			}	
		}
	}
	while(!down); //消抖	
}

上下键改变光标的位置的原理和左右键改变光标的位置的原理是一样的。上下键还要实现的功能就是每次同时按下上下键时,可以将光标处的字符发送给电脑串口调式助手。发送字符是通过flagSend变量的值进行控制的。显示光标的功能是通过sendMode函数实现的,具体的代码与功能的实现是在下一步的讲解中。

主函数中,在OLED_P8x16Str(0, 0, dataString); 后面编写如下代码

keyLeftRight(); // 按键处理
keyUpDown();
sendMode(); // 模式转换检测

在主函数中通过函数调用实现按键处理的功能。
编译程序,将生成的hex文件烧入单片机中。OLED 屏幕屏幕显示光标如下图所示
基于51单片机的通讯聊天系统
现在我们已经实现了通过按键进行模式切换、OLED 屏幕显示光标、按键控制光标移动的功能了.

5、光标处的字符发送给电脑串口助手显示与流水灯

上一步我们实现了OLED显示光标与按键控制光标移动的功能,现在要实现的功能是通过同时按下上下键将光标处的字符发送给电脑串口调式助手于接收区内显示,在发送完字符后8个led灯实现流水灯流动两次的效果。
首先是实现发送光标处的字符功能。在上一步我们已经在Main.h中声明了sendData()与sendMode()函数。sendData()函数是实现单片机发送数据的功能,sendMode()函数是实现单片机处于发送模式与调用sendData()函数发送数据的功能。

现在实现sendMode函数的功能,在Main.c中编写代码如下

void sendMode()
{
	if(funcSelect)		//发送模式时
	{
		while(flagSend == 1) 		// 发送字符标志
		{
			sendData();				// 发送数据给电脑串口助手
			flagSend = 0;
		}

		OLED_Set_Pos(keyX, keyY);			// 打开光标
		for(i = 0; i < 8; i++)
			OLED_WrDat(openCursor[i]); 
	
		OLED_Set_Pos(keyX, keyY + 1);	
		for(i = 0; i < 8; i++)
			OLED_WrDat(openCursor[i]);
	}
	else
		flagSend = 0;
}

当处于发送模式时,funcSelect变量是非零执行if语句之后就可以显示光标了。每次按上下左右键之后,也是在主函数中通过死循环不断调用sendMode()函数实现的。当处于发送模式时,同时按下上下键时,flagSend变量的值就变为1了。执行if条件语句中的while语句,调用sendData()函数将光标处的字符发送给单片机。
现在实现sendData函数的功能,在Main.c中编写代码如下

void sendData()
{
	dataChar = keyX / 8 + keyY * 8;	   // 获取光标处的字符

	SBUF = dataString[dataChar];    //发送光标处的字符
	while(!TI);

	flagLed = 1;

	TI = 0;
}

dataChar = keyX / 8 + keyY * 8; 语句是用dataChar变量来存放光标处的字符在dataString数组中的下标位置,然后通过dataString[dataChar]就可以访问dataString数组中的字符数据了,也就是处于光标处的字符数据。
SBUF = dataString[dataChar]; //发送光标处的字符
while(!TI);
这两行代码的功能是将光标处的字符存放于寄存器SBUF中,然后发送给电脑串口调式助手与手机的SSP蓝牙串口APP上显示。每次发送完数据后,要将TI中断标志置零,为下一次的串口中断成功发送数据做好准备。光标处的字符发送给电脑串口调试助手与手机的SSP蓝牙串口APP上的效果如下图所示
基于51单片机的通讯聊天系统
基于51单片机的通讯聊天系统
现在要实现的功能是单片机发送完数据后,LED灯实现流水灯的功能。在sendData()函数中,当每次发送完数据之后,flagLed变量的值就为1。
现在在Main.h中定义流水灯初始化的数组和变量如下

UINT ledData[8] = 							// led流水灯初始化
{
	0xFE, 0XFD, 0XFB, 0XF7,
	0xEF, 0XDF, 0XBF, 0X7F
};

UINT ledTime = 2; // ledTime: 控制流水灯的次数
0xFE是表示8个LED灯中的D1灯为低电平,其他的七个LED灯处于高电平,所以访问ledData数组中的第一个数据时,只有第一个led灯点亮,其他的七个LED灯熄灭。

现在在主函数中的while(1)语句中编写如下代码实现流水灯的功能

if(flagLed == 1)						  // 单片机发送信息后, 流水灯流动两次
{
	while(ledTime > 0  )
	{
		for(i = 0; i < 8; i++)
		{
			P1 =ledData[i];
			delay(100);
		}
		ledTime--;	
	}

	flagLed = 0;
	ledTime = 2;
					// 流水灯时, led和OLED共用P1^2和P1^3引脚
	OLED_Init();		// 流水灯流动完后, 防止OLED出现乱码, 所以重新初始化OLED
	OLED_Fill(0x00);
}

在实现流水灯流动两次之后,将flagLed变量赋值0和ledTime变量赋值2,为下一次的发送数据后实现流水灯的效果做准备。因为流水灯时,led和OLED共用P12和P13引脚,所以流水灯流动完后, 防止OLED屏幕出现乱码, 要重新初始化OLED,OLED屏幕就可以正常显示字符数据了。
编译程序,将生成的hex文件烧入单片机中。运行单片机,发送数据后流水灯流动的效果录制了“发送数据后LED实现流水灯”的视频文件与程序文件夹中。
现在已经实现了发送光标处的数据、发送数据后流水灯流动的效果了。

到这一步,我们的通讯功能的系统已经全部完成了。

七、总结

学习51单片机提高了我们对于C语言的编程能力,从最简单的点亮LED灯开始,就用到了C语言的循环的知识点。在LED流水灯中,我们组运用了C语言的变量、数组存储我们的数据、用顺序结构与循环结构相结合进行了不同算法的编程实现同一种功能。在许多的简单的编程中我们运用了C语言函数进行模块化的编程,将实现一种功能分为几个小的功能进行模块化编程。在进行51单片机的过程中,让我们可以分析实际的问题,并运用C语言解决实际的问题。让我们对于C语言有了进一步的掌握与C语言编程的能力。
基于51单片机的通讯聊天系统文章来源地址https://www.toymoban.com/news/detail-404647.html

到了这里,关于基于51单片机的通讯聊天系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 基于51单片机的简易电梯系统的设计

      系统概述 设计要求 根据所学的知识以及技能,利用MCS-51系列单片机为中心设计一个简易电梯系统,实现四层电梯的无故障运行,并用数码管和指示灯显示对应楼层和运行方向等基本信息。设计所用的单片机为STC89C52为主要的控制器,自带AD转换,当一边有按键按下时,另一

    2024年02月09日
    浏览(51)
  • 基于51单片机的光照强度检测系统

    一.硬件方案         本设计采用单片机作为数据处理与控制单元,为了进行数据处理,通过光敏电阻来感应光强弱变化,经过ADC0804转换,直接将数字信号送入到单片机中进行数据处理。单片机数据处理之后,将光照强度发送到LED进行显示,并通过和LED进行声光。        

    2024年02月11日
    浏览(31)
  • 电脑通过串口助手和51单片机串口通讯

    今天有时间把电脑和51单片机之间的串口通讯搞定了,电脑发送的串口数据,单片机能够正常接收并显示到oled屏幕上,特此记录一下,防止后面自己忘记了怎么搞得了。 先来两个图片看看结果吧! 下面是串口3.c的文件全部内容: 下面是oled.h的全部内容: 下面是oled.c的全部内

    2024年02月07日
    浏览(53)
  • 基于51单片机和proteus的电流采集系统

    此系统是基于51单片机和proteus的仿真设计,功能如下: 1. LCD1602实时显示获取到电流值及设定值。 2. 按键可调整电流设定值。 3. 电流值过高则蜂鸣器报警。 4. 指示灯指示电流及系统状态。 5. 系统信息可通过串口实时更新。 功能框图如下: Proteus仿真界面如下: 下面就各个模

    2024年02月16日
    浏览(39)
  • 基于51单片机烟雾温度检测报警系统设计

    一、系统方案 本设计采用52单片机作为主控器,液晶1602显示,DS18B20采集温度,MQ2采集烟雾值,火焰传感器,按键设置报警,声光报警。 二、硬件设计 原理图如下: 三、单片机软件设计 1、首先是系统初始化 / / // 1602液晶初始化函数 / / void LcdInit() { LcdWriteCmd(0x38); // 16 2显示,

    2024年02月09日
    浏览(49)
  • 基于51单片机汽车智能灯光控制系统设计

    (protues仿真+程序+原理图+PCB+设计说明书) 仿真图proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:C0049 硬件构成: 51单片机 LCD1602液晶 光敏电阻 超声波 ADC0832 LED灯 1.按键说明:从左边第一个起,减键、加键、设置键。单独一个控制为复位按键。 2.LCD1602液晶第一行

    2024年02月08日
    浏览(52)
  • 基于51单片机和proteus的温室大棚系统

    此系统是基于51单片机和proteus的仿真设计,功能如下: 1. LCD1602实时显示光照/土壤湿度/温度值及设定值。 2. 按键可增减光照/土壤湿度/温度设定阈值。 3. 获取到的温度低于设定温度则打开加热设备。 4. 获取到的光照值低于设定光照值则打开补光灯。 5. 获取到的土壤湿度低于

    2024年02月16日
    浏览(48)
  • 基于51单片机的温度检测监测报警系统设计

    前些天发现了十分不错的人工智能学习网站,通俗易懂,风趣幽默,没有广告,分享给大家,大家可以自行看看。(点击跳转人工智能学习资料) 微信公众号:创享日记 发生:单片机温度检测 获取原理图源文件+程序源文件+仿真源文件+报告+相关资料 基于51单片机的温

    2024年02月13日
    浏览(52)
  • 48、基于51单片机红外遥控智能温控风扇系统设计

        本设计为一种温控风扇系统,具有灵敏的温度感测和显示功能,系统STC89C52单片机作为控制平台对风扇转速进行控制。可由用户设置高、低温度值,测得温度值在高低温度之间时打开风扇弱风档,当温度升高超过所设定的温度时自动切换到大风档,当温度小于所设定的温

    2024年02月04日
    浏览(47)
  • 32、基于51单片机红外智能垃圾桶系统设计

    随着现代化进程的日益推进,科技越来越发达,人们的生活水平也提高了,城市化程度越来越高,与此同时也带了许多问题,生活垃圾越来越多垃圾设施却不够完善。无论是在公共场合还是家庭厨房的垃圾大都是没有盖或者有盖但需要人用手打开的,比如夏天的家庭厨房没有

    2023年04月14日
    浏览(53)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包