完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
基于STC89C51单片机的双通道DHT11实时温湿度显示系统(LCD1602)
这是单片机系统的课程大作业,做的有点仓促,代码其实也可以再优化一下,在这里抛砖引玉,希望能给大家带来一些思路。这也是第一次使用 Markdown编辑器 ,顺便学一下写作,淦,不说那么多废话了。 题目要求 本题目要求学生利用数字式温度和湿度采集环境信息采用I2C串口通讯威廉希尔官方网站 返回单片机,并在LCD显示器实时显示,要求湿度误差不大于5%,温度误差不大于2摄氏度;要求能够显示二路的温度和湿度参数,在LCD屏幕上进行显示且刷新评率不低于0.5 Hz。系统组成包含有STC-89C52开发板,LCD1602显示屏,数字传感器DHT11。LCD显示要求可以同时显示两只传感器的任温度和湿度。 实现的功能 前三个问题已经解决。按键切换不同状态时,后台仍在持续读取数据,最大值为开机以来的最大值,平均值为检测到近10次数据的平均值(51性能有限,其实是答主能力有限),次数过多单片机将无法显示正确数据。题目中提到使用IIC,但是答主咩用到,DHT11通过单总线通信,之后简单复制便实现了两路操作。 至于第四问,答主还没肝出来,如果在课程时间内能做出来就更新,不行的话就随缘啦~提供一个思路:LCD1602作为一个字符型LCD,没有画点函数,但内置8个自定义字符,是否可以通过自定义字符来显示曲线呢,大家有兴趣可以试一下。 思路介绍 本次实验中,首先是两路DHT11温湿度传感器,管脚分别接P2.0,P2.1。剩余两个管脚分别板子自带接VCC和GND。将外部中断P3.3与一个独立按键相连接。按要求插好LCD1602.工作时DHT11测量外界温度。将温度信息发送到STC-C52,STC-C52实时检测DHT11的在线状态,并使LCD1602实时显示。通过按键切换,显示两路DHT11温湿度传感器的离在线状态、实时温湿度、平均温湿度与最大温湿度。 开发板是在一块芯片中集成了CPU( 中央处理器)、RAM( 数据存储器)、ROM( 程序存储器)、定时器/ 计数器和多种功能的I/O( 输入/ 输出) 接口等一台计算机所需要的基本功能部件,从而可以完成复杂的运算、逻辑控制、通信等功能。 软件设计思路:软件程序的设计包括多个模块,包括LCD1602显示驱动模块、延时函数模块、温度模式切换显示模块、中断服务函数模块、两路DHT11温度检测模块、按键检测模块等。 代码部分 下面是大家喜闻乐见的代码部分 注意事项 在keil的codesize和memory model注意选择最大,否则程序可能烧不进去。 驱动部分 为了方便管理,我把按键和LCD驱动写了两个库文件,在实际使用中,按键扫描并没有用到,因为避免程序运行过慢,检测不到,选择使用外部中断来实现按键。 LCD1602驱动 先来个头文件:注意PIN口的定义,这里只是简单的驱动函数,大家在网上随便都能找到相似的。 #ifndef __LCD_H_ #define __LCD_H_ /********************************** 包含头文件 **********************************/ #include《reg52.h》 /********************************** PIN口定义 **********************************/ #define LCD1602_DB P0 ***it LCD1602_RS = P3^5; ***it LCD1602_RW = P3^6; ***it LCD1602_EN = P3^4; //void Lcd1602_Delay1ms(uint c); //误差 0usvo void LCD_Delay10ms(unsigned int c); //void Read_Busy(); //忙检测函数,判断bit7是0,允许执行;1禁止 void Lcd1602_Write_Cmd(unsigned char cmd); //写命令 void Lcd1602_Write_Data(unsigned char dat); //写数据 void LcdSetCursor(unsigned char x,unsigned char y); //坐标显示 void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str); //显示字符串 void InitLcd1602(); //1602初始化 #endif 再来个C文件:只是简单的驱动函数,大家在网上随便都能找到相似的,也可以通过数据手册自己写。 这里有一个点,就是很多驱动都略写了LCD1602的读BUSY函数,具体原因求大佬告知。在这里为简化代码,我也忽略了。 #include 《reg52.h》 #include “LCD.h” void Lcd1602_Write_Cmd(unsigned char cmd) //写命令 { //Read_Busy(); LCD1602_RS = 0; LCD1602_RW = 0; LCD1602_DB = cmd; LCD_Delay10ms(1); LCD1602_EN = 1; LCD_Delay10ms(1); LCD1602_EN = 0; } void Lcd1602_Write_Data(unsigned char dat) //写数据 { //Read_Busy(); LCD1602_RS = 1; LCD1602_RW = 0; LCD1602_DB = dat; LCD_Delay10ms(1); LCD1602_EN = 1; LCD_Delay10ms(1); LCD1602_EN = 0; } //指定位置开始显示数据! void LcdSetCursor(unsigned char x,unsigned char y) //坐标显示 { unsigned char addr; if(y == 0) addr = 0x00 + x;//第一行开始,x表示一行的第x个 else addr = 0x40 + x;//第二行开始,x表示一行的第x个 Lcd1602_Write_Cmd(addr|0x80); } void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str) //显示字符串 { LcdSetCursor(x,y); //当前字符的坐标 while(*str != ‘ ’) { Lcd1602_Write_Data(*str++); } } void InitLcd1602() //1602初始化 { Lcd1602_Write_Cmd(0x38); //打开,5*8,8位数据 Lcd1602_Write_Cmd(0x0c); //开显示,未添加光标闪烁 Lcd1602_Write_Cmd(0x01); //清屏 Lcd1602_Write_Cmd(0x06); // Lcd1602_Write_Cmd(0x07); //地址指针加一,右移 } void LCD_Delay10ms(unsigned int c) //误差 0us { unsigned char a,b; for(;c》0;c--) for(b=38;b》0;b--) for(a=130;a》0;a--); } 按键驱动 没啥好说的,虽然写了,但其实我就没咋用到。。。。。。 头文件 #ifndef __KEY_H_ #define __KEY_H_ #include《reg52.h》 #define FOSC 11059200L #define uint unsigned int /********************************** PIN口定义 **********************************/ ***it KEY = P3^0;//独立按键S2 ***it KEY0 = P3^1;//独立按键S3 //***it KEY = P3^6;//上课用单片机 //***it KEY0 = P3^5; void KeyScanInd();//独立按键检测 void Keymode(); //模式切换 #endif C文件:没用到就注释了哈 #include 《reg52.h》 #include “key.h” #include “LCD.h” //uint KeyValue=0; //void KeyScanInd() //{ // KEY = 1; //判断独立按键 // KEY0 = 1; //判断独立按键 // // if(KEY != 1) // { // Delayms(5);//软件消抖 // if( KEY!= 1) // { // KeyValue++; // if(KeyValue==4) KeyValue=1; // while(KEY != 1);//松手检测 // } // } // // if(KEY0 != 1) // { // Delayms(5);//软件消抖 // if( KEY0!= 1) // { // KeyValue--; // if(KeyValue==0) KeyValue=3; // while(KEY0 != 1);//松手检测 // } // } // //} //void Keymode() //{ // if(KeyValue==1)//当前值 // { // LcdShowStr(0,0,“Present value!”); // P1 = ~P1; // } // if(KeyValue==2)//平均值 // { // LcdShowStr(0,0,“Average value!”); // P1 = ~P1; // } // if(KeyValue==3)//最大值 // { // LcdShowStr(0,0,“Maximum value!”); // P1 = ~P1; // // } //} 我使用到的按键是P3^3,通过外部中断1触发(不好意思忘更新了),这部分直接写到主要模块了。 //键盘函数中断版 void KeymodeINTER() { switch(modeflag) { case 0: displaySTATUS(); Lcd1602_Write_Cmd(0x01); //清屏 break; //当前值 case 1: displayNOW(); Lcd1602_Write_Cmd(0x01); //清屏 break; //平均值 case 2: displayAVE(); Lcd1602_Write_Cmd(0x01); //清屏 break; //最大值 case 3: displayMAX(); Lcd1602_Write_Cmd(0x01); //清屏 break; case 4: displayBight(); Lcd1602_Write_Cmd(0x01); //清屏 break; case 5: displayBight1(); modeflag = 0; Lcd1602_Write_Cmd(0x01); //清屏 break; } } 主要模块 初始化 淦定义了好多变量,大家可以看一下代码的注释 这里有一点,在编写到最后,因为多定义两个数组,结果烧录进去程序就崩了,最后只好把一个二维数组改成一维的,放弃储存一些数据。 /********************************************************************************* * 【编写时间】: 2021年3月22日 * 【作 者】: 手动打码,滑稽 * 【版 本】: 1.7 * 【编译环境】: Keil μVisio5 * 【程序功能】: * 【版本更新】: 21.10:00 添加外部中断按键消抖,优化部分代码,略微提高速度,可实现功能1.1要求 解决了切屏后温度不实时更新的问题 21.18:07 完成任务1.3 21.22:00 1.2最大值部分调试成功 22.9:26 1.2最大值可实现无缝记录,开机到显示的最大值一直有效。 22.10:28 1.2单平均值串口测量成功 22.11:16 1.2多平均值实时lcd、串口测量成功 22.15:30 1.1显示实时值刷新率提高 * 【预期改动】:1.使用定时器0按键消抖,使用定时器1定时发送串口数据(可拓展为1.2平均值问题)--------失败 2.不用数组储存数据,直接累加!!!解决问题1.2----------成功 **********************************************************************************/ #include 《reg52.h》 #include 《intrins.h》 #include 《math.h》 #include 《stdio.h》 #include “LCD.h” #include “key.h” #include 《string.h》 #define uchar unsigned char #define uint unsigned int #define N 5 //平均值计算的组数 /******************************************************************************* * 实验名 :温度显示程序 * 使用的IO : P2^0;P2^1; : *******************************************************************************/ ***it Temp_data =P2^0; // ***it Temp_data1=P2^1; ***it flag = P3^3;//中断启动位 uchar modeflag = 0;//键盘模式切换 uchar status1 = 0;//DHT11状态 uchar status = 0;//DHT11状态 //函数定义 void Delayms(unsigned int ms); void DHT11_delay_us(unsigned char n); void DHT11_delay_ms(unsigned int z); void DHT11_start(); uchar DHT11_rec_byte(); uchar DHT11_rec_byte1(); void DHT11_receive(); void DHT11_receive1(); void InitUART(void); void displaySTATUS(); void displayNOW(); void displayAVE(); void displayMAX(); void manage_math(); void max_math(); void avr_math(); unsigned int rec_dat[8]={0,0,0,0,0,0,0,0};//温度初始数组 double dat_manage[4]={ 0, 0, 0, 0};//实时数据储存数组 double dat_max[4]={0,0,0,0};//最大值储存数组 double dat_avr[4]={0,0,0,0};//平均值储存数组 double S[4] = {0,0,0,0}; //累加和 double C[4] = {0,0,0,0}; //本次采样值 double A[4] = {0,0,0,0}; //平均值 //第一路传感器 unsigned char rec_dat_lcd0[6]; unsigned char rec_dat_lcd1[6]; unsigned char rec_dat_lcd2[6]; unsigned char rec_dat_lcd3[6]; //第二路传感器 unsigned char rec_dat_lcd4[6]; unsigned char rec_dat_lcd5[6]; unsigned char rec_dat_lcd6[6]; unsigned char rec_dat_lcd7[6]; //最大值平均值字符串中转函数 unsigned char dat_max_lcd0[6]; unsigned char dat_max_lcd1[6]; unsigned char dat_max_lcd2[6]; unsigned char dat_max_lcd3[6]; DHT11驱动 我们将DHT11接受到的数据储存在rec_dat[ ]数组中,并记录判断位,为第三问求在线掉线错误做准备。 我将错误设置成校验位与传输数据不符,当然DHT11没毛病这种错误一定不会出现。。。 //DHT11起始信号1 void DHT11_start() { Temp_data=1; DHT11_delay_us(2); Temp_data=0; DHT11_delay_ms(20); Temp_data=1; DHT11_delay_us(13); } //DHT11起始信号2 void DHT11_start1() { Temp_data1=1;// DHT11_delay_us(2); Temp_data1=0;// DHT11_delay_ms(20); Temp_data1=1;// DHT11_delay_us(13); } //接收一个字节通道1 unsigned char DHT11_rec_byte() { unsigned char i,dat; for(i=0;i《8;i++) { while(!Temp_data); DHT11_delay_us(8); dat《《=1; if(Temp_data==1) { dat+=1; } while(Temp_data); } return dat; } //接收一个字节通道2 unsigned char DHT11_rec_byte1() { unsigned char i,dat1; for(i=0;i《8;i++) { while(!Temp_data1); DHT11_delay_us(8); dat1《《=1; if(Temp_data1==1) { dat1+=1; } while(Temp_data1); } return dat1; } //接收温湿度数据通道1 void DHT11_receive() { unsigned int R_H,R_L,T_H,T_L; unsigned char RH,RL,TH,TL,revise; DHT11_start(); Temp_data=1; if(Temp_data==0) { status=Temp_data;//此时为0,准备好嘞 while(Temp_data==0); //等待拉高 DHT11_delay_us(40); //拉高后延时80us R_H=DHT11_rec_byte(); //接收湿度高八位 R_L=DHT11_rec_byte(); //接收湿度低八位 T_H=DHT11_rec_byte(); //接收温度高八位 T_L=DHT11_rec_byte(); //接收温度低八位 revise=DHT11_rec_byte(); //接收校正位 DHT11_delay_us(25); //结束 if((R_H+R_L+T_H+T_L)==revise) //校正 { RH=R_H; RL=R_L; TH=T_H; TL=T_L; } else { status = 2;//此时为2,数据有误 } /*数据处理,方便显示*/ rec_dat[0]=RH; rec_dat[1]=RL; rec_dat[2]=TH; rec_dat[3]=TL; } else { status = 1;//此时为1,DHT11断线 } } //接收温湿度数据通道2 void DHT11_receive1() { uint R_H1,R_L1,T_H1,T_L1; uchar RH1,RL1,TH1,TL1,revise1; DHT11_start1(); Temp_data1=1; if(Temp_data1==0) { status1=Temp_data1;//此时为0,准备好嘞 while(Temp_data1==0); //等待拉高 DHT11_delay_us(40); //拉高后延时80us R_H1=DHT11_rec_byte1(); //接收湿度高八位 R_L1=DHT11_rec_byte1(); //接收湿度低八位 T_H1=DHT11_rec_byte1(); //接收温度高八位 T_L1=DHT11_rec_byte1(); //接收温度低八位 revise1=DHT11_rec_byte1(); //接收校正位 DHT11_delay_us(25); //结束 if((R_H1+R_L1+T_H1+T_L1)==revise1) //校正 { RH1=R_H1; RL1=R_L1; TH1=T_H1; TL1=T_L1; } else { status1 = 2;//此时为2,数据有误 } /*数据处理*/ rec_dat[4]=RH1; rec_dat[5]=RL1; rec_dat[6]=TH1; rec_dat[7]=TL1; } else { status1 = 1;//此时为1,DHT11断线 } } //延时us --2*n+5us void DHT11_delay_us(unsigned char n) { while(--n); } //延时ms void DHT11_delay_ms(unsigned int z) { unsigned int i,j; for(i=z;i》0;i--) for(j=110;j》0;j--); } 中断服务程序 这里启用了串口通信来实时打印温度值,在程序中可能有的注释了,大家如果想用取消注释就可以,打开串口助手起飞~ 这里也定义了键盘中断函数,可怜我的key.c没用上呜呜呜(开个玩笑)。 void InitUART(void)//使用定时器1作为串口波特率发生器 { SCON=0x40; //串口通信工作方式1 REN=1; //允许接收 TMOD=0x20; //定时器1的工作方式2 TH1=0xFd,TL1=0xFd; TI=1; //这里一定要注意 TR1=1; } //外部中断1初始化--键盘使用p3.3qingxiang void int1Init() { EA = 1; //开总中断 EX1 = 1;//开外部中断1 IT1 = 1;//外部中断1下降沿触发 } //外部中断1中断服务程序 切换显示模式 void int1() interrupt 2 { if(flag != 1) { Delayms(5);//软件消抖 if( flag!= 1) { P1 = ~P1; modeflag++; while(flag != 1);//松手检测 } } // P1 = ~P1; // modeflag++; } 显示函数 最占地方的一部分了。。。。。这里把各种状态显示到lcd上。 sprintf函数是转字符串,毕竟lcd1602的字符库一个一个敲地址也有点费事鸭。 /***********************************显示函数********************/ void displaySTATUS() { LcdShowStr(0,0,“1-DHT:”); LcdShowStr(0,1,“2-DHT:”); while(1) { //解决切屏后温度不实时更新的问题 DHT11_delay_ms(150); DHT11_receive(); DHT11_delay_ms(150); DHT11_receive1(); switch(status1) { case 0: LcdShowStr(7,1,“ALREADY”); break; case 1: LcdShowStr(7,1,“WAITING”); break; case 2: LcdShowStr(7,1,“ERROR!”); break; } switch(status) { case 0: LcdShowStr(7,0,“ALREADY”); break; case 1: LcdShowStr(7,0,“WAITING”); break; case 2: LcdShowStr(7,0,“ERROR!!!”); break; } if(modeflag != 0) break; } } void displayNOW() { InitLcd1602(); LcdShowStr(0,0,“Present value!”); DHT11_delay_ms(500);//只是为了好看 Lcd1602_Write_Cmd(0x01); //清屏 // //LED显示静态变量 LcdShowStr(0,0,“H:”); LcdShowStr(0,1,“T:”); LcdShowStr(8,0,“H‘:”); LcdShowStr(8,1,“T’:”); while(1) { //解决切屏后温度不实时更新的问题 DHT11_delay_ms(150); DHT11_receive(); DHT11_delay_ms(150); DHT11_receive1(); manage_math();// //通道1数据 sprintf(dat_max_lcd0,“%.1f”,dat_manage[0]); sprintf(dat_max_lcd1,“%.1f”,dat_manage[1]); //通道2数据 sprintf(dat_max_lcd2,“%.1f”,dat_manage[2]); sprintf(dat_max_lcd3,“%.1f”,dat_manage[3]); //*********通道1 //湿度 LcdShowStr(2,0,dat_max_lcd0); LcdShowStr(6,0,“%”); //温度 LcdShowStr(2,1,dat_max_lcd1); LcdShowStr(6,1,“C”); //*********通道2 //湿度 LcdShowStr(11,0,dat_max_lcd2); LcdShowStr(15,0,“%”); //温度 LcdShowStr(11,1,dat_max_lcd3); LcdShowStr(15,1,“C”); max_math();//保证之前的最大值被记录 avr_math();//保证之前的平均值被记录 //串口助手打印温度 printf(“Humi1:%d.%d ”, rec_dat[0],rec_dat[1]); //printf(“Temp1:%d.%d °Cn”,rec_dat[2],rec_dat[3]); printf(“Humi2:%d.%d ”, rec_dat[4],rec_dat[5]); //printf(“Temp2:%d.%d °Cn”,rec_dat[6],rec_dat[7]); printf(“avrHumi1:%.1f n”, dat_avr[0]); printf(“avrHumi2:%.1f n”, dat_avr[3]); printf(“A:%.1f n”, A[1]); printf(“C:%.1f n”, C[1]); printf(“S:%.1f n”, S[1]); printf(“/***********/n”); if(modeflag != 1) break; } } void displayAVE() { LcdShowStr(0,0,“Average value!”); DHT11_delay_ms(500); Lcd1602_Write_Cmd(0x01); //清屏 // //LED显示静态变量 LcdShowStr(0,0,“H:”); LcdShowStr(0,1,“T:”); LcdShowStr(8,0,“H‘:”); LcdShowStr(8,1,“T’:”); while(1) { //解决切屏后温度不实时更新的问题 DHT11_delay_ms(150); DHT11_receive(); DHT11_delay_ms(150); DHT11_receive1(); manage_math(); avr_math(); sprintf(dat_max_lcd0,“%.1f”,dat_avr[0]); sprintf(dat_max_lcd1,“%.1f”,dat_avr[1]); sprintf(dat_max_lcd2,“%.1f”,dat_avr[2]); sprintf(dat_max_lcd3,“%.1f”,dat_avr[3]); //*********通道1 //湿度 LcdShowStr(2,0,dat_max_lcd0); LcdShowStr(6,0,“%”); // //温度 LcdShowStr(2,1,dat_max_lcd1); LcdShowStr(6,1,“C”); //*********通道2 //湿度 LcdShowStr(11,0,dat_max_lcd2); LcdShowStr(15,0,“%”); //温度 LcdShowStr(11,1,dat_max_lcd3); LcdShowStr(15,1,“C”); printf(“avrHumi:%.1f ”, dat_avr[0]); printf(“avrTemp:%.1f °Cn”,dat_avr[1]); if(modeflag != 2) break; } } void displayMAX() { LcdShowStr(0,0,“Maximum value!”); DHT11_delay_ms(500); Lcd1602_Write_Cmd(0x01); //清屏 // //LED显示静态变量 LcdShowStr(0,0,“H:”); LcdShowStr(0,1,“T:”); LcdShowStr(8,0,“H‘:”); LcdShowStr(8,1,“T’:”); while(1) { //解决切屏后温度不实时更新的问题 DHT11_delay_ms(150); DHT11_receive(); DHT11_delay_ms(150); DHT11_receive1(); max_math(); sprintf(dat_max_lcd0,“%.1f”,dat_max[0]); sprintf(dat_max_lcd1,“%.1f”,dat_max[1]); sprintf(dat_max_lcd2,“%.1f”,dat_max[2]); sprintf(dat_max_lcd3,“%.1f”,dat_max[3]); //*********通道1 //湿度 LcdShowStr(2,0,dat_max_lcd0); LcdShowStr(6,0,“%”); // //温度 LcdShowStr(2,1,dat_max_lcd1); LcdShowStr(6,1,“C”); //*********通道2 //湿度 LcdShowStr(11,0,dat_max_lcd2); LcdShowStr(15,0,“%”); //温度 LcdShowStr(11,1,dat_max_lcd3); LcdShowStr(15,1,“C”); printf(“maxHumi:%.1f ”, dat_max[0]); printf(“maxTemp:%.1f °Cn”,dat_max[1]); if(modeflag != 3) break; } } 主函数 他来了他来了!主函数他来了! 哈哈哈哈哈其实主函数只是简单的初始化一下~ //主函数 void main() { InitUART(); InitLcd1602(); int1Init(); while(1) { //KeyScanInd(); KeymodeINTER();//进入该函数后会一直循环,下列函数功能失效 DHT11_delay_ms(100); DHT11_receive(); DHT11_delay_ms(100); DHT11_receive1(); // //串口助手打印温度 // printf(“Humi:%d.%d ”, rec_dat[0],rec_dat[1]); // printf(“Temp:%d.%d °Cn”,rec_dat[2],rec_dat[3]); // printf(“Humi:%d.%d ”, rec_dat[4],rec_dat[5]); // printf(“Temp:%d.%d °Cn”,rec_dat[6],rec_dat[7]); } } 数学处理函数 当时求平均值愁死我了,淦,捡起我大一零碎的C语言知识,在VSCODE跑了几遍求平均值才又移植到keil这儿。 求平均值借鉴了一个大佬的:ADC采样算法----递推平均值采样法 /*******************************数学处理部分**********************/ void manage_math() { // int i,j; //第一路温湿度 dat_manage[0]=rec_dat[0]+rec_dat[1]*0.1; dat_manage[1]=rec_dat[2]+rec_dat[3]*0.1; //第二路温湿度 dat_manage[2]=rec_dat[4]+rec_dat[5]*0.1; dat_manage[3]=rec_dat[6]+rec_dat[7]*0.1; } void max_math()//最大值处理函数 { uint n; manage_math(); for(n=0;n《4;n++) //取最大值 { if ( dat_manage[n] 》 dat_max[n] ) dat_max[n]=dat_manage[n] ; } } void avr_math() //平均值处理函数 { static uchar count = 0; uchar i; manage_math(); for(i=0;i《4;i++) { C[i] = dat_manage[i]; if( count == 0 ) { A[i] = C[i]; S[i] = A[i] * N; count = 1; } S[i] = S[i] - A[i] + C[i]; //加上本次采样值,减去上次平均值 A[i] = S[i] / N; //计算本次平均值 count = 0; dat_avr[i]=A[i]; } } |
|
|
|
只有小组成员才能发言,加入小组>>
2611 浏览 0 评论
808浏览 1评论
250浏览 1评论
578浏览 0评论
312浏览 0评论
528浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-2-3 11:33 , Processed in 1.276720 second(s), Total 77, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号