找回密码
 立即注册
查看: 2526|回复: 10

打卡学习《STC32位8051单片机原理及C语言程序设计视频教程》

[复制链接]

1

主题

10

回帖

71

积分

注册会员

积分
71
发表于 2023-9-30 17:52:42 | 显示全部楼层 |阅读模式
截图202309301747031116.jpg

今天开始学习STC32G单片机,第一集通过冲哥的讲解了解到了单片机作为集成性芯片的概念。同时通过冲哥使用淘宝商品实物与应用功能的综合讲述,明白了单片机在医学、工业等方面的实际强大作用。
在问题讲解时,明白了51单片机的强大性,也感知到单片机的强应用性。
刚开始起步学习,第一集像绪论一样为自己对单片机的学习提供了明确的方向。加油!!

回复

使用道具 举报 送花

1

主题

10

回帖

71

积分

注册会员

积分
71
发表于 2023-9-30 18:46:09 | 显示全部楼层
第二集了解了9-4实验箱上各元器件的应用与原理。

实验箱截图-1

实验箱截图-1

(1)以红外遥控器做引导,了解其典型器件--红外发射与对应的红外接收
(2)电压比较的应用需要与其基准电压做比较,从而根据数据进行实时操作。这里和后面讲ADC采集的应用原理相似,即根据基准电压的对应数据,按照规则,反推出采集电压实际代表数据
(3)LED的应用最为广泛的就是流水灯
(4)数码管的原理:它的每一条灯线都可以根据信号独立点亮从而实现一组数据的显示;类似于电磁炉的显示和热水壶的数值显示

实验箱-NTC测温和万能板

实验箱-NTC测温和万能板

(5)万能板的存在更多是为了方便用户进行后期扩展,提供区域进行附加元器件的焊接
(6)NTC测温广泛应用于上方的电子体温计探头

实验箱-18B20和ADC

实验箱-18B20和ADC

(7)18B20作为温度传感,其精度高但间隔时间长,反馈数据不连续
(8)与之相比的ADC,作为模拟电压转数据的模块,它可实现连续实时测温,产生连续线性数据,同时通过基准电压得出温度数据
(9)DAC介绍不多,但可根据ADC反推,同时它可以产生波形图进而以此为基础进行功能调控
(10)数据存储方面
a.24C02作为外部存储芯片可以存储上次开机是使用数据,便于在单片机损坏时进行数据转移
b.FLASH扩展,存储空间大,可以存放图片与文字等大文件数据,实现实时存储
c.RAM可存储运行时产生的数据,但断电即丢失,需要存入上述的24C02或者FLASH内
(11)关于按键
a.独立按键,一个按键连接一个引脚,曾应用在影视剧内的典型炸弹与数码管配合使用
b.矩阵按键就是解决独立按键占用大量引脚问题,它也广泛应用于密码锁中
(12)232接口电路需要特定线进行连接,曾应用于打印机,也可进行代码烧录
截图202309301836066933.jpg
以上为第二集的知识梳理,在冲哥的讲解下对实验箱内各元器件得到了初步理解,对于冲哥留的思考作业,我可能会偏向于做一个红外装置配合的密码锁,嘿嘿
回复 支持 反对

使用道具 举报 送花

1

主题

10

回帖

71

积分

注册会员

积分
71
发表于 2023-10-1 17:40:20 | 显示全部楼层
第三集,学习开发环境的搭建和程序的下载
(1)下载STC-ISP,此软件负责STC系列单片机的程序下载烧录,是单片机开发中必不可少的配置软件

STC-ISP

STC-ISP

(2)STC32G单片机操作手册下载,可以从STC-ISP软件内下载也可以通过官网下载。

开发文档下载

开发文档下载

(3)根据开发手册可知,本课程所需keil版本为C251
截图202310011730303752.jpg
通过开发文档跳转到对应官网内
截图202310011731315835.jpg
根据开发文档内的步骤指导,完成编译环境的下载
截图202310011732317606.jpg
(4)通过软件STC-ISP下载STC32G的官方程序
截图202310011734264762.jpg
在keil仿真处配置STC MCU
截图202310011735272341.jpg
(5)安装配置USB驱动程序
截图202310011736594338.jpg
通过上述配置后,可通过打开对应文档的项目工程文件打开keil,编译无误后生成.hex文件。STC-ISP配置好芯片型号,再打开程序文件获取对应.hex文件,即可通过此软件将程序烧录到单片机内
截图202310011739323034.jpg
需要注意其他参数数据如运行频率,要与keil代码内配置一致。
回复 支持 反对

使用道具 举报 送花

1

主题

10

回帖

71

积分

注册会员

积分
71
发表于 2023-10-1 20:13:02 | 显示全部楼层
第四集的学习,开始建立第一个工程并在后期实现不断电下载
(1)首先,从原理来讲,LED点亮就是由元器件两端高低电平控制的。
过程中了解到GPIO的分组与输出电压的设置
(2)创建工程步骤
a.Project创建工程,并配置对应芯片

创建时配置STC MCU

创建时配置STC MCU

b.创建文本文件,并命名为.c文件。之后右键添加到工程中

添加文件

添加文件

c.编写程序,参照开发手册考虑控制LED灯点亮的引脚,可以使用sbit单独控制输出电平
d.进行编译,生成.hex(需要提前设置项目输出)

生成hex文件

生成hex文件

e.打开STC-ISP,配置对应参数,然后打开程序文件.hex,连接开发板进行下载

以上为创建工程的基础操作
同时,考虑到注册下载程序需要频繁断电。尝试使用USB_CDC不断电下载和USB_HID不断电下载,
截图202310012010317230.jpg
截图202310012010531547.jpg
工程开发没有问题,可实现全部点亮LED灯,但是在不断电下载处出现一定问题
截图202310012012074327.jpg
截图202310012012421057.jpg
想咨询一下是什么问题
回复 支持 反对

使用道具 举报 送花

1

主题

10

回帖

71

积分

注册会员

积分
71
发表于 2023-10-21 17:16:33 | 显示全部楼层
继续学习,打卡第五集
本节课的学习主要围绕C语言的数据表示与数据运算
1、首先学习了在keil上使用printf的方法
首先需要在主函数内加入
if(DeviceState!=DEVSTATE_CONFIGUSED)------>判断USB是否连接
continue;
if(bUsbOutReady){---------->判断是否接收到数据
usb_OUT_done();//接收应答
printf("");//接收数据后作出打印反映,打印双引号内字符串
}
做好基础配置后,可将编译生成的.hex文件放入STC-ISP内,运行后,模拟发送数据,系统将打印由十六进制码翻译出的字符串

2、printf内打印的知识点
(1)格式字符

格式字符

格式字符

补充

补充

在双引号内写入格式字符,打印时将识别双引号后跟随的数据根据格式进行打印
此时,%d十进制,%o八进制,%x十六进制以及%u十进制无符号是最经常使用的
%c与%s用于打印字符,根据ascii码进行数据翻译
(关于二进制有符号,二进制首位为0则为正数,正常运算;首位为1,为负数,运算时转十进制时,需求其补码,除符号位外按位取反,末位加1)
(2)转义字符

转义字符

转义字符

转义字符在打印时也经常使用,其中\n与\r常搭配使用用于换行
(3)ASCII码
生成的.hex为十六进制文件,打印输出时是以两位为一个字符,将十六进制根据ASCII码进行翻译得出的
3、数据运算
(1)进制转换
二进制(b),八进制(0),十进制,十六进制(0x)
二进制,仅由01,满二进一
八进制,以0开头,0,1,2,3,4,5,6,7为表示数,与二进制转换可以三位二进制转一位八进制
十六进制,以0x开头,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F为表示数,与二进制转换可以四位二进制转一位十六进制
(2)运算
按补码运算,数据的加减乘除,取余都正常
&为与运算,二进制补码11为1,10为0,01为0,00为0
|为或运算,二进制补码00为0,10为1,01为1,11为1
^为异或运算,相同为0,不同为1
~为取反运算,各位01互换取反
(3)基本类型

数据的基本类型

数据的基本类型

根据表中可得知,各数据的表示域根据其有无符号和位数bit决定

本节课为基础的理论知识,为进一步学习奠基基础,期待接下来的学习

回复 支持 反对

使用道具 举报 送花

1

主题

10

回帖

71

积分

注册会员

积分
71
发表于 2023-10-21 18:42:00 | 显示全部楼层
第六集学习打卡
1、本节课首先学习了使用Delay实现LED闪烁
功能实现核心代码
(1)基础配置
#define MAIN_Fosc        24000000UL------>此处设置TRC系统时钟频率
void  delay_ms(u16 ms)------->ms代表毫秒数,1s=1000ms;
{
     u16 i;--------->u16      typedef unsigned int u16;即代表无符号整型
     do{
          i = MAIN_Fosc / 6000;
          while(--i);
     }while(--ms);
}
(2)功能实现
p40=0;------>三极管引脚输出低电平
while(1){
p60=0;------>引脚输出低电平,LED灯点亮
delay_ms(500);---->延时0.5s
p60=1;------>输出高电平,LED熄灭}
实现LED等每0.5秒点亮,0.5秒熄灭的功能
2、代码语法分析
(1)while与dowhile
截图202310211828017153.jpg
二者区别在于while需要先判断再执行,do...while,是先执行一次再判断
(2)a--与--a自增自减
a--相当于a=a-1
符号在前先执行增减再运算
符号在后先执行运算再增减
(3)#define与typedef
二者都是用于简化符号,define新名称在前,typedef新名称在后
2、使用#define也可完成模块化编程
新建xxx.c和xxx.h文件,代表一个功能块。

xxx.h格式:
#ifndef __XXX_H
#define __XXX_H
调用头文件
函数声明...
#endif

xxx.c格式
#include “xxx.h”
函数定义
(这可避免出现头文件被重复声明,若存在该头文件将不再声明;同时,如果头文件与执行代码不处于同一文件夹,需要在keil内引用路径)
截图202310211836182748.jpg
在include path处添加头文件路径
3、函数声明
函数的使用在整个功能实现上起到模块封装的作用
在模块化编程里,函数使用分为如下三步:
1.函数定义
返回值 函数名称( 入口参数 )
{
函数要执行的功能
}
@返回值:没有返回值就是void
@函数名称:避开关键词,不重复,非特殊字符随便取
@入口参数:类型+名称,多个参数“,”分开,空就写void
2.函数声明
返回值 函数名称( 入口参数 );
3.函数调用
函数名称( 入口参数 );
4、作业SOS灯光编写
(2)功能实现
p40=0;------>三极管引脚输出低电平
void short(){
p60=0;------>引脚输出低电平,LED灯点亮
delay_ms(100);---->延时0.5s
p60=1;------>输出高电平,LED熄灭
delay_ms(100);---->延时0.5s
}
void long(){
p60=0;------>引脚输出低电平,LED灯点亮
delay_ms(500);---->延时0.5s
p60=1;------>输出高电平,LED熄灭
delay_ms(500);---->延时0.5s
}
while(1){
short();
short();
short();
long();
long();
long();
short();
short();
short();
delay_ms(200);
}
回复 支持 反对

使用道具 举报 送花

1

主题

10

回帖

71

积分

注册会员

积分
71
发表于 2023-10-25 21:13:38 | 显示全部楼层
第七集学习打卡
本次学习的中心围绕按键
1、按键的原理
(1)按键通常为两个引脚
截图202310252043177559.jpg
按照如图按键结构,通过检测p3.2的电平来判断按键状态。
按键SW17松开,电路处于断开,VCC电压全部分到P3.2,检测高电平,断开
按键SW17按下,电路连通,VCC电压分流,检测低电平,导通
所以,获取按键状态,只需要获得对应引脚的电平,如P32为引脚p3.2对应的按键,0为低电平表示按下,1为高电平表示松开
#define KEY P32
(2)机械开关
截图202310252053201443.jpg
根据机械开关抖动的特性,获取机械开关状态时,需要进行消抖
if (KEY==0){
Delay_ms(10);---->消抖核心,观察10ms后是否仍是按下状态
if(KEY==0){
执行功能
}
}
2、按键功能应用
(1)按键按下LED点亮,松开熄灭
if(KEY==0){
Delay_ms(10);
if(KEY==0){
P67=0;//灯组第七个点亮
}else{
P67=1;//灯组第七个熄灭
}
}
(2)按键按下LED熄灭,松开点亮
if(KEY==0){
Delay_ms(10);
if(KEY==0){
P67=1;//灯组第七个熄灭
}else{
P67=0;//灯组第七个点亮
}
}
(3)按下按键一次,LED状态改变一次
if(KEY==0){
Delay_ms(10);
if(KEY==0){
while(KEY==0);//防止状态频繁切换,按下一次只做一次操作
p67=!p67;//电平翻转,状态也翻转
}
(4)按键按下一次,LED向左走一次
int LED_Data=0xFE;//1111 1110
if(KEY==0){
delay_ms(10);
if(KEY==0){
LED_Data=((LED_Data<<1)+1);//使置零位向左移一位,并用1补位
if(LED_Data==0xFF)//1111 1111代表灯光已经移到最左,需要移到最右
LED_Data=0xFE;
P6=LED_Data//P6代表整个灯组的信号状态,0位点亮,1位熄灭
while(KEY==0);
}
3、针对上面的向左移动灯光的情况,也可以使用数组,将灯光的可能状态对应二进制按顺序存入数组,使用时根据下标调用
即int *LED[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
。。。
num=0;
f(KEY==0){
delay_ms(10);
if(KEY==0){
num++;
if(num==7)//1111 1111代表灯光已经移到最左,需要移到最右
num=0;
P6=LED[num]//P6代表整个灯组的信号状态,0位点亮,1位熄灭
while(KEY==0);
}
}
以上为本次学习的知识梳理
回复 支持 反对

使用道具 举报 送花

1

主题

10

回帖

71

积分

注册会员

积分
71
发表于 2023-10-26 21:27:48 | 显示全部楼层
第八集蜂鸣器学习打卡
1、本次课程了解到蜂鸣器本质分为两类
(1)有源蜂鸣器:由于内置震荡源,给点后即可发声,同样造价也相对贵一些
(2)无源蜂鸣器:直流电无法发声,需要交流电(频繁切换高低电平)才能发声,但同时也可以发出多种频率的声音
从外观观察,无源蜂鸣器的背面引脚处为裸露的电路板
2、控制原理
截图202310262102285705.jpg
蜂鸣器起到控制作用的依然是具有单向导通的二极管。
SYS-VCC处提供电压,若为高电平,二极管处无法导通,蜂鸣器关闭,同样P5.4处也出现高电平
若为低电平,二极管处可导通,蜂鸣器可运行,同样P5.4处为低电平
通过检测P5.4的电平可得出蜂鸣器状态
3、应用
仿造电磁炉进行操作
截图202310262106495375.jpg
为简化主函数代码,模块化实现函数
定义头文件test.h,将功能函数进行声明,定义各引脚
截图202310262108248542.jpg
创建test.c进行功能实现
(1)KEY控制开关机,如果没有开机其他按键功能无法实现,按键同时伴有蜂鸣器提示音
截图202310262110153154.jpg
设置标识位Run_Flag为0表示未开机,为1表示开机
同时,将while(KEY1==0)判定放置功能执行后面,实现按键后实现功能且一次按键只执行一次功能
(2)KEY2按下后进行功能切换,即LED灯每按一次向左移一位,同时伴有切换提示音
截图202310262116513188.jpg
本模块功能和上一节切换本质需求相同,但使用了一种新的解决办法
与每次功能切换对应的Run_Mode值相对应,每按一次便向左移动一位,
考虑到LED与位的联系将默认值次数-1,初始值为0000 0001,LED点亮要求0位点亮,所以取反得到所求
(3)注意,由于test.h文件为后添加的头文件,需要进行配置,将其所在文件夹作为头文件存储位置

头文件配置

头文件配置

4、作业
增加按键3,使选中功能运行时指示灯闪烁,不运行时常亮
截图202310262124337983.jpg
考虑其中逻辑关系,必须按键2选择了功能,即Run_Mode值不为0才能执行功能;同样按键3执行时按键2也不能再切换功能;使用标志位进行实现
同时,关机时,要把各状态位清零复位
基于原蜂鸣器应用代码,按键3的执行必须是在按键2执行完后,所以要在按键2功能代码外。

以上为本次蜂鸣器学习的知识梳理,期待继续收获新知识
回复 支持 反对

使用道具 举报 送花

1

主题

10

回帖

71

积分

注册会员

积分
71
发表于 2023-10-30 21:15:54 | 显示全部楼层
第九集数码管学习打卡
1、数码管的设备原理
数码管本质就是由多个LED二极管按不同位置摆放封装组成的
截图202310302101161185.jpg
如右侧示意图,代表数码管内二极管的摆放,共阴极和共阳极会影响指令信号的设置
截图202310302102562136.jpg
根据内部连线图可知,本设备为共阴极,通过数码管的二极管封装位置与共阴极性质可得出码表,推算出各数字显示所需信号量
截图202310302105066838.jpg
2、显示控制
截图202310302105585762.jpg
若仅点亮末尾的8,只需要P6和COM0(P7.0)进行配置
(1)用数组表示1-9的内码
根据码表可得,
u8 SEG_Tab[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}
(2)尝试使用延时实现0-9的循环显示
num=0;
while(1){
P70=0//开启COM0
P6=SEG_Tab[num];
num++;
if(num>9)
num=0;
delay_ms(1000)
}
(3)用按键控制数字的加或减
截图202310302111491433.jpg
3、拓展
通过一个按键设置数码管显示数字0-9循环,在按一下另一个按键的时候,数码管上显示的数字几,蜂鸣器就响几声。
首先设置蜂鸣器引脚
#define BEEP p54
...
int i;
while(){
....
for(i=0;i<num;i++){
BEEP=0;
delay_ms(10);
BEEP=1;
}}
回复 支持 反对

使用道具 举报 送花

1

主题

10

回帖

71

积分

注册会员

积分
71
发表于 2023-10-31 23:38:40 | 显示全部楼层
第十集数码管的动态显示知识梳理
本集的知识是基于前一集的静态显示实现的。
静态显示以末尾的单个数码管为例,展示了如何利用数组点亮LED二极管,来顺次显示0-9数字。此处的数组表示的是显示0-90数字的段码
1、动态显示的原理
截图202310312242086710.jpg
本开发板共八个数码管,每个结构都如上所示,此结构为共阳极,需要先为公共端设置低电平表示输出,再为需要点亮的LED二极管对应线路设置低电平进行点亮
截图202310312248384763.jpg
数码管每次点亮需要设置端口,即控制哪个数码管的公共端设为低电平,一次只能设置一个。
同时,控制数码管内LED的引脚为P6,控制各数码管电平的引脚为P7
(1)所以,设置一个数码管点亮需要先设置P7对应端口信号确认使用的数码管,再设置P6端口信号确认显示的图像
P7=0xfe;P6=0xc0;则末尾数码管显示0
(2)动态显示,则是切换P7对应端口位置信号,切换P6显示信号电平
截图202310312257238484.jpg
整理出各端口位置信号,即位码的具体数据,也可存入数组中使用
为避免系统出错,在切换过程中加入延时操作,依次为P7和P6配置不同位码与段码,并进行延时切换,便可实现动态显示
(3)延时操作
由于人眼视觉很难识别50hz以上的动态显示,只要我们将延时设置为每个切换1ms,一次总循环不超过20ms,人眼就会将顺次动态显示的数码管识别为同时显示的数据
2、练习:制作简易10s免单计数器(含两位小数显示)
截图202310312323551788.jpg
(1)分析
本项目本质为秒表,默认设置每次显示切换为1ms,则每10ms数据+1
截图202310312307417665.jpg
秒表需要小数点,由于各数码管小数点对应位置dp,位于二进制进制的第八位,则每个数字-0x80便得到对应数字带小数点的显示信号,将数据顺次存入数组。纯数字检索对应下标恰好+10即可得到带小数点数字
为方便显示,设置数组将每位数码管需要显示的信号对应下标存入,两位小数对应小数点属于第六个数码管即显示数组下标【5】,将其存入的数据+10得到带小数点形式
设置按键控制计数器的启动与暂停,对按键进行消抖与单次按键识别,设置状态量用于记录设备的启动与停止,每按下一次状态改变一次。同时,避免数据紊乱,按下停止后再启动,原始数据会直接清空,故初始化显示数组此时应该均为0
(2)实现(核心代码)
#define KEY1 P32                //定义一个按键 引脚选择P32
#define KEY2 P33                //定义一个按键 引脚选择P33

#define BEEP P54                //定义一个按键 引脚选择P54

#define SEG_Delay  1        //延时多少ms

#define MAIN_Fosc 24000000UL        //定义主时钟

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
       
u8 SEG_Tab[20] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};        //0-9段码,0-9带小数点
u8 COM_Tab[8] = { 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe };        //0-7的位码数组
u8 Show_Tab[8] = {3,0,0,0,0,10,0,0};

u32 TimCount = 0;                //计数单位1ms
bit RUN_State = 0;                //开始运行/结束运行
u8 num = 0;

void sys_init();        //函数声明
void delay_ms(u16 ms);        //unsigned int

void SEG_Fre( void ) -----》定义函数,用于刷新显示,在人眼无法识别的时间内,将变化的数据显示到数码管
{
        //位码选择第一位,段码选择0  
        P7 = COM_Tab[num];                        //位码的选择
        P6 = SEG_Tab[Show_Tab[num]];//需要显示的数字的内码 赋给 P6   NUM =0 -> Show_Tab[num]] = 1 -> p6 = oxF9
        delay_ms(SEG_Delay);

        num++;
        if( num >7 )----》数码管只有8个
                num = 0;       
}

void main()                                        //程序开始运行的入口
{
       
        sys_init();                                //USB功能+IO口初始化
        usb_init();                                //usb库初始化
        EA = 1;                                        //CPU开放中断,打开总中断。
       
        while(1)                //死循环
        {
                if( DeviceState != DEVSTATE_CONFIGURED )         //
                        continue;
                if( bUsbOutReady )                                                               
                {
                        usb_OUT_done();

                }


                Show_Tab[0]  = 1;                //末尾初始显示 1
                Show_Tab[1]  = 10;                //倒数第二位显示 0.(带小数点)
                Show_Tab[2]  = 0;                //选择 0
                Show_Tab[3]  = 0;                //选择 0        ------》用于显示10.00定时数据

               
               

                if( RUN_State==1 )----》状态为运行时数据才能累加
                {
                        TimCount++;
                        Show_Tab[4] = TimCount/10000%10;     -------》显示十位
                        Show_Tab[5] = TimCount/1000%10+10;        -----》显示数据,同时显示小数点
                        Show_Tab[6] = TimCount/100%10;                //显示秒表小数点后一位
                    Show_Tab[7] = TimCount/10%10;                //取10位 ,timecount每+1位1ms,10次为10ms,显示秒表最低位
                }
               
                SEG_Fre();---》将计算结果显示

                if( KEY1 ==0 )
                {
                        delay_ms(10);
                        if( KEY1 ==0 )---》按键消抖
                        {
                                BEEP = 0;---》蜂鸣器提示
                                delay_ms(10);
                                BEEP = 1;
                                while( KEY1 ==0 )
                                {
                                        SEG_Fre();
                                }
                                if( RUN_State==0 )
                                        TimCount = 0;----》清零
                               
                                RUN_State = !RUN_State;
                        }
                }               
               
3、拓展
截图202310312329451717.jpg
(1)-的显示,其实就是只点亮g,即1011 1111=0xbf,在段码数组内再填入此数据,并初始化第三个和第六个数码管为此段码一直显示如此
(2)计算数据时,num运行1000次秒区域+1,num/1000%60;num运行60000次分区域+1,num/60000%60;num运行3600000次,时区域数据+1,num/3600000%24
(3)进行if判断,当s=30,m=0,h=0时,蜂鸣器P54端口低电平启动,延时3s再设为高电平关闭
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-7 14:35 , Processed in 0.131252 second(s), 102 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表