极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 33550|回复: 26

思考了一晚上不知道为什么,求助论坛大神,关于Arduino中的wire

[复制链接]
发表于 2015-4-29 21:42:40 | 显示全部楼层 |阅读模式
首先我写了五个文件放在同一目录下:MPU6050.h 、MPU6050.CPP 、PASSOMETER.INO、DATABUFFER.H、DATABUFFER.H
功能实现放在passometer.ino里面,其他的 当类库使用,编译通过,可以运行。
在MPU6050.CPP中有这样两个函数:MPU6050_read和readFromsensor,前一个函数在第二中得到调用。
int MPU6050::MPU6050_read(int start, uint8_t *buffer, int size)
{
        int i, n;
        Wire.begin();
        Wire.beginTransmission(MPU6050_I2C_ADDRESS);
        n = Wire.write(start);
        if (n != 1)
                return (-10);
        n = Wire.endTransmission(false);
        if (n != 0)
                return (n);
        Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true);
        i = 0;
        while(Wire.available() && i<size)
        {
          buffer[i++]=Wire.read();
        }               
        if ( i != size)
                return (-11);
        return (0); // return : no error
}

void MPU6050::readFromSensor(DataBuffer * db) {
       
        int error;
        error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
     ........
}

然后loop中申明了一个mpu6050的对象,循环调用了readFromsensor,是这样调用的:
mpu6050.readFromSensor(&databuffer);
按照预期,,Wire.read应该返回动态的一组数据,,可实际上wire.read每次读取到的都是同样的。

为了找到错误,我做了这样的尝试:
1、以为是buffer中存储时出错,,所以有直接让wire.read的内容输出的串口,,发现结果仍然是每次返回同样的数据。
2、用while(wire.available())wire.read();
      来清空缓存,,结果失败。

新手遇到这样的问题好心塞,百度都百度不到,求好心人指点。
回复

使用道具 举报

发表于 2015-4-29 22:09:12 | 显示全部楼层

可能是你程序自己写错了
把以下这完整贴上来:
void MPU6050::readFromSensor(DataBuffer * db) {
        
        int error;
        error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
     ........
}
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-29 22:19:32 | 显示全部楼层
感觉没有必要贴,,因为在readFromsensor一开始就调用了,MPU6050_read函数,,没有贴的部分都是读取后做的一些处理。现在的问题是在MPU6050里读到的数据就是不对的。我又尝试了将MPU6050_read直接合并到readFromSensor里面,失败了。。等下只能试试将函数弄到loop里面去会不会成功了。因为我是初学者,整个代码我只是把一个单文件改成了多文件的形式,,原来能运行的文件应该是对的,,所以一步步减小多文件与单文件的差异希望能找到错误。

void MPU6050::readFromSensor(DataBuffer * db) {
       
        int error;
        error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
        if(error != 0) {
                Serial.print(F("Read accel, temp and gyro, error = "));
                Serial.println(error,DEC);
        }
        uint8_t swap;
        #define SWAP(x,y) swap = x; x = y; y = swap
        SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
        SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
        SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
        SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
        SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
        SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
        SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);
  
        Serial.print(F("accel x,y,z: "));
        Serial.print(accel_t_gyro.value.x_accel, DEC);
        Serial.print(F(", "));
        Serial.print(accel_t_gyro.value.y_accel, DEC);
        Serial.print(F(", "));
        Serial.print(accel_t_gyro.value.z_accel, DEC);
        Serial.print(F(", at "));
        Serial.print(db->Index);
        Serial.println(F(""));
  
    if((db->Index) < (db->BUFFER_SIZE) && (db->Index) > 1) {
                int tempX = accel_t_gyro.value.x_accel;
                int tempY = accel_t_gyro.value.y_accel;
                int tempZ = accel_t_gyro.value.z_accel;

                char temp = (char)(tempX >> 8);
                if(temp == 0x00)
                        temp = 0x7f;
                db->aAccelBuffer[db->Index] = temp;
                db->Index++;
                temp = (char)(tempX);
                if(temp == 0x00)
                        temp = 0x01;
                db->aAccelBuffer[db->Index] = temp;
                db->Index++;
   
                temp = (char)(tempY >> 8);
                if(temp == 0x00)
                        temp = 0x7f;
                db->aAccelBuffer[db->Index] = temp;
                db->Index++;
                temp = (char)(tempY);
                if(temp == 0x00)
                temp = 0x01;
                db->aAccelBuffer[db->Index] = temp;
                db->Index++;
   
                temp = (char)(tempZ >> 8);
                if(temp == 0x00)
                        temp = 0x7f;
                db->aAccelBuffer[db->Index] = temp;
                db->Index++;
                temp = (char)(tempZ);
                if(temp == 0x00)
                        temp = 0x01;
                db->aAccelBuffer[db->Index] = temp;
                db->Index++;
    }
}
回复 支持 反对

使用道具 举报

发表于 2015-4-29 22:53:54 | 显示全部楼层
armray 发表于 2015-4-29 22:19
感觉没有必要贴,,因为在readFromsensor一开始就调用了,MPU6050_read函数,,没有贴的部分都是读取后做的 ...

(1)你的以下这句写在何处 ?
   accel_t_gyro_union accel_t_gyro;

(2)你的这句写在何处?
   MPU6050  mpu6050;

(3)麻烦把 MPU6050.h  也贴上来
回复 支持 反对

使用道具 举报

发表于 2015-4-29 23:00:06 | 显示全部楼层
armray 发表于 2015-4-29 22:19
感觉没有必要贴,,因为在readFromsensor一开始就调用了,MPU6050_read函数,,没有贴的部分都是读取后做的 ...

还有还有

你说在 loop ( ) 内用:
   mpu6050.readFromSensor(&databuffer);
那请问这里的 databuffer 是写在何处, 以及如何写?
回复 支持 反对

使用道具 举报

发表于 2015-4-29 23:35:07 | 显示全部楼层
armray 发表于 2015-4-29 22:19
感觉没有必要贴,,因为在readFromsensor一开始就调用了,MPU6050_read函数,,没有贴的部分都是读取后做的 ...

你的问题应该跟 Wire 没关系
应该是使用类库创建 "对象" 使用上的问题
例如 DataBuffer databuffer; 使用错误或写在错误的地方
还有
你说 "然后loop中申明了一个mpu6050的对象"
其实这也不应该,
如果你真的是 "在loop中申明一个mpu6050的对象"
则等于每次进入 loop 都重新创建新的 mpu6050的对象
因为, 每次离开 loop( ) { } 时在 loop( ) 中所有的变量与对象都会不见
意思是该些在 loop( ) 申明的变量与对象所占用内存都会被移除 !
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-30 10:35:34 | 显示全部楼层
tsaiwn 发表于 2015-4-29 23:35
你的问题应该跟 Wire 没关系
应该是使用类库创建 "对象" 使用上的问题
例如 DataBuffer databuffer; 使 ...

哦哦,终于从wire的话题上打住了,看了下逻辑,也用你说的方法清理了缓存,应该不是wire的问题。问题应该还是在单文件到多文件的转换,就是引用对象时产生了差异,,整体的代码也不长,300行吧,我整理一下贴出来吧。
昨晚回去就睡了,才看到,既然大神都已经入局了,就麻烦再多看一下,帮我解决了问题吧,小弟不胜感激
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-30 10:54:21 | 显示全部楼层
  1. //DataBuffer.h
  2. #ifndef DataBuffer_H
  3. #define DataBuffer_H

  4. #if defined(ARDUINO) && ARDUINO >= 100
  5.         #include "Arduino.h"
  6. #else
  7.         #include "WProgram.h"
  8. #endif

  9. class DataBuffer{
  10.         public:
  11.                 int BUFFER_SIZE;//buffer大小
  12.                 int Index;//buffer已存数据位
  13.                 byte aAccelBuffer[125];//存储单元
  14.                 DataBuffer();//构造函数
  15.                 void InitBuffer();//清空buffer
  16. };
  17. #endif
  18. //DataBuffer.cpp
  19. #include"DataBuffer.h"
  20. DataBuffer::DataBuffer(){
  21.     BUFFER_SIZE=125;
  22.     Index=2;       
  23. }
  24. void DataBuffer::InitBuffer(){
  25.             Index = 2;
  26.         for(int i=Index; i<BUFFER_SIZE; i++) {
  27.                 aAccelBuffer[i] = 0x00;
  28.         }
  29.        aAccelBuffer[0] = 0xfe;
  30.        aAccelBuffer[1] = 0xfd;
  31.        aAccelBuffer[122] = 0xfd;
  32.        aAccelBuffer[123] = 0xfe;
  33.        aAccelBuffer[124] = 0x00;
  34. }
  35. //MPU6050.h
  36. #ifndef MPU6050_H
  37. #define MPU6050_H

  38. #if defined(ARDUINO) && ARDUINO >= 100
  39.         #include "Arduino.h"
  40. #else
  41.         #include "WProgram.h"
  42. #endif
  43. #include"DataBuffer.h"

  44. #define MPU6050_ACCEL_XOUT_H 0x3B
  45. #define MPU6050_PWR_MGMT_1 0x6B
  46. #define MPU6050_PWR_MGMT_2 0x6C
  47. #define MPU6050_WHO_AM_I 0x75
  48. #define MPU6050_I2C_ADDRESS 0x68

  49. class MPU6050{
  50.         public:
  51.                 MPU6050();
  52.                 void readFromSensor(DataBuffer * db);
  53.                 int MPU6050_read(int start, uint8_t *buffer, int size);
  54.                 int MPU6050_write_reg(int reg, uint8_t *data);
  55.                 typedef union accel_t_gyro_union {
  56.                         struct {
  57.                         uint8_t x_accel_h;
  58.                         uint8_t x_accel_l;
  59.                         uint8_t y_accel_h;
  60.                         uint8_t y_accel_l;
  61.                         uint8_t z_accel_h;
  62.                         uint8_t z_accel_l;
  63.                         uint8_t t_h;
  64.                         uint8_t t_l;
  65.                         uint8_t x_gyro_h;
  66.                         uint8_t x_gyro_l;
  67.                         uint8_t y_gyro_h;
  68.                         uint8_t y_gyro_l;
  69.                         uint8_t z_gyro_h;
  70.                         uint8_t z_gyro_l;
  71.                         } reg;

  72.                         struct {
  73.                         int x_accel;
  74.                         int y_accel;
  75.                         int z_accel;
  76.                         int temperature;
  77.                         int x_gyro;
  78.                         int y_gyro;
  79.                         int z_gyro;
  80.                         } value;
  81.                 };
  82.         accel_t_gyro_union accel_t_gyro;

  83. };
  84. #endif
  85. //MPU6050.cpp
  86. #include"MPU6050.h"
  87. #include"DataBuffer.h"
  88. #include <math.h>
  89. #include <Wire.h>
  90. #include <SoftwareSerial.h>
  91. MPU6050::MPU6050(){
  92.        
  93. };
  94. int MPU6050::MPU6050_read(int start, uint8_t *buffer, int size)
  95. {
  96.         int i, n;
  97.         Wire.begin();
  98.         Wire.beginTransmission(MPU6050_I2C_ADDRESS);

  99.         n = Wire.write(start);
  100.         if (n != 1)
  101.                 return (-10);
  102.        
  103.         n = Wire.endTransmission(false);
  104.         if (n != 0)
  105.                 return (n);
  106.        
  107.         // Third parameter is true: relase I2C-bus after data is read.
  108.         Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true);
  109.         i = 0;
  110.         while(Wire.available() && i<size)
  111.         {
  112.           buffer[i++]=Wire.read();
  113.         }               
  114.         if ( i != size)
  115.                 return (-11);
  116.         return (0);
  117. }
  118. void MPU6050::readFromSensor(DataBuffer * db) {
  119.        
  120.         int error;
  121.         error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
  122.         if(error != 0) {
  123.                 Serial.print(F("Read accel, temp and gyro, error = "));
  124.                 Serial.println(error,DEC);
  125.         }
  126.         uint8_t swap;
  127.         #define SWAP(x,y) swap = x; x = y; y = swap//这一大段其实并没有用到,,也没有传给蓝牙
  128.         SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
  129.         SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
  130.         SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
  131.         SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
  132.         SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
  133.         SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
  134.         SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);
  135.   
  136.         Serial.print(F("accel x,y,z: "));
  137.         Serial.print(accel_t_gyro.value.x_accel, DEC);
  138.         Serial.print(F(", "));
  139.         Serial.print(accel_t_gyro.value.y_accel, DEC);
  140.         Serial.print(F(", "));
  141.         Serial.print(accel_t_gyro.value.z_accel, DEC);
  142.         Serial.print(F(", at "));
  143.         Serial.print(db->Index);
  144.         Serial.println(F(""));
  145.   
  146.     if((db->Index) < (db->BUFFER_SIZE) && (db->Index) > 1) {
  147.                 int tempX = accel_t_gyro.value.x_accel;
  148.                 int tempY = accel_t_gyro.value.y_accel;
  149.                 int tempZ = accel_t_gyro.value.z_accel;

  150.                 char temp = (char)(tempX >> 8);
  151.                 if(temp == 0x00)
  152.                         temp = 0x7f;
  153.                 db->aAccelBuffer[db->Index] = temp;
  154.                 db->Index++;
  155.                 temp = (char)(tempX);
  156.                 if(temp == 0x00)
  157.                         temp = 0x01;
  158.                 db->aAccelBuffer[db->Index] = temp;
  159.                 db->Index++;
  160.    
  161.                 temp = (char)(tempY >> 8);
  162.                 if(temp == 0x00)
  163.                         temp = 0x7f;
  164.                 db->aAccelBuffer[db->Index] = temp;
  165.                 db->Index++;
  166.                 temp = (char)(tempY);
  167.                 if(temp == 0x00)
  168.                 temp = 0x01;
  169.                 db->aAccelBuffer[db->Index] = temp;
  170.                 db->Index++;
  171.    
  172.                 temp = (char)(tempZ >> 8);
  173.                 if(temp == 0x00)
  174.                         temp = 0x7f;
  175.                 db->aAccelBuffer[db->Index] = temp;
  176.                 db->Index++;
  177.                 temp = (char)(tempZ);
  178.                 if(temp == 0x00)
  179.                         temp = 0x01;
  180.                 db->aAccelBuffer[db->Index] = temp;
  181.                 db->Index++;
  182.     }
  183. }
  184. int MPU6050::MPU6050_write_reg(int reg, uint8_t *data)
  185. {
  186.         int error,n;
  187.         Wire.beginTransmission(MPU6050_I2C_ADDRESS);
  188.        
  189.         n = Wire.write(reg);
  190.         if (n != 1)
  191.                 {error=-20;return (error);}
  192.        
  193.         n = Wire.write(data, 1);
  194.         if (n != 1)
  195.                 {error=-21;return (error);}
  196.        
  197.         error = Wire.endTransmission(true);
  198.         if (error != 0)
  199.                 return (error);
  200.         return (error);
  201. }

  202. //main file
  203. #include <math.h>
  204. #include <Wire.h>
  205. #include <SoftwareSerial.h>
  206. #include"DataBuffer.h"
  207. #include"MPU6050.h"

  208. #define SENSOR_READ_INTERVAL 50 //&#65533;&#65533;&#545;MPU&#65533;&#316;&#65533;&#65533;&#689;&#65533;&#65533;
  209. unsigned long prevSensoredTime = 0;//&#65533;&#1012;ζ&#65533;&#545;&#689;&#65533;&#65533;
  210. unsigned long curSensoredTime = 0;//&#65533;&#65533;&#496;&#689;&#65533;&#65533;

  211. SoftwareSerial BTSerial(2, 3);
  212. MPU6050  mpu6050=MPU6050();
  213. DataBuffer databuffer=DataBuffer();

  214. void setup() {
  215.         Serial.begin(9600);
  216.         BTSerial.begin(9600);  
  217.         Wire.begin();
  218.         int error;
  219.         uint8_t c;
  220.         error = mpu6050.MPU6050_read (MPU6050_WHO_AM_I, &c, 1);
  221.         Serial.print(F("WHO_AM_I : "));
  222.         Serial.print(c,HEX);
  223.         Serial.print(F(", error = "));
  224.         Serial.println(error,DEC);

  225.         error = mpu6050.MPU6050_read (MPU6050_PWR_MGMT_2, &c, 1);
  226.         Serial.print(F("PWR_MGMT_2 : "));
  227.         Serial.print(c,HEX);
  228.         Serial.print(F(", error = "));
  229.         Serial.println(error,DEC);
  230.         mpu6050.MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0);
  231.         databuffer.InitBuffer();
  232. }
  233. void loop() {
  234.   curSensoredTime = millis();
  235.   while(Wire.available())
  236.         {Wire.read( );}
  237.   if(curSensoredTime - prevSensoredTime > SENSOR_READ_INTERVAL) {
  238.     mpu6050.readFromSensor(&databuffer);
  239.     prevSensoredTime = curSensoredTime;

  240.     if(databuffer.Index >= databuffer.BUFFER_SIZE - 3) {
  241.       sendToRemote(&databuffer);
  242.       databuffer.InitBuffer();
  243.       Serial.println("------------- Send 20 accel data to remote");
  244.     }
  245.   }
  246. }
  247. void sendToRemote(DataBuffer * db) {
  248.   BTSerial.write( "accel" );
  249.   BTSerial.write( (char*)(db->aAccelBuffer) );
  250. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-30 10:57:06 | 显示全部楼层
tsaiwn 发表于 2015-4-29 22:53
(1)你的以下这句写在何处 ?
   accel_t_gyro_union accel_t_gyro;

1、  accel_t_gyro_union accel_t_gyro;写在头文件里面了
2、MPU6050 mpu6050写在主文件中,但不是loop和setup中
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-30 11:00:20 | 显示全部楼层
tsaiwn 发表于 2015-4-29 23:35
你的问题应该跟 Wire 没关系
应该是使用类库创建 "对象" 使用上的问题
例如 DataBuffer databuffer; 使 ...

因为在loop中要用到,对象在setup中申明的话会报“未定义对象”的错误,所以我在函数外申明了
回复 支持 反对

使用道具 举报

发表于 2015-4-30 11:35:28 | 显示全部楼层
armray 发表于 2015-4-30 10:54
//DataBuffer.h
#ifndef DataBuffer_H
#define DataBuffer_H


Line 224 那句不对
    MPU6050  mpu6050=MPU6050();

请注意 C++ 不是 Java, 对于 class/Object 的概念与用法略有不同.
该句必须改为:
    MPU6050  mpu6050;   // 如果是 Java 则必须写 MPU6050  mpu6050 = new MPU6050( );
  /// 在 C++, 这样 mpu6050 就是个可以用的 Object (对象) 了 !

另外, 以下Line 225 也不对

   DataBuffer databuffer=DataBuffer();

虽然编译会过, 但是意义不同 !
必须改为

   DataBuffer databuffer;

或这样也可以:

   DataBuffer databuffer( );

你先改这两个看看是否问题就解决了 !?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-30 12:16:38 | 显示全部楼层
tsaiwn 发表于 2015-4-30 11:35
Line 224 那句不对
    MPU6050  mpu6050=MPU6050();

按照你刚才说的改了,可以运行,但输出还是一直是这样

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-30 12:29:56 | 显示全部楼层
tsaiwn 发表于 2015-4-30 11:35
Line 224 那句不对
    MPU6050  mpu6050=MPU6050();

还有DataBuffer databuffer();这样的表达编译时通不过的哈

passometer.ino: In function 'void setup()':
passometer.ino:34:13: error: request for member 'InitBuffer' in 'databuffer', which is of non-class type 'DataBuffer()'
passometer.ino: In function 'void loop()':
passometer.ino:42:39: error: no matching function for call to 'MPU6050::readFromSensor(DataBuffer (*)())'
passometer.ino:42:39: note: candidate is:
In file included from passometer.ino:6:0:
C:\Users\rayray\AppData\Local\Temp\build1820798255905393185.tmp\MPU6050.h:21:8: note: void MPU6050::readFromSensor(DataBuffer*)
   void readFromSensor(DataBuffer * db);
        ^
C:\Users\rayray\AppData\Local\Temp\build1820798255905393185.tmp\MPU6050.h:21:8: note:   no known conversion for argument 1 from 'DataBuffer (*)()' to 'DataBuffer*'
passometer.ino:45:19: error: request for member 'Index' in 'databuffer', which is of non-class type 'DataBuffer()'
passometer.ino:45:39: error: request for member 'BUFFER_SIZE' in 'databuffer', which is of non-class type 'DataBuffer()'
passometer.ino:46:31: error: cannot convert 'DataBuffer (*)()' to 'DataBuffer*' for argument '1' to 'void sendToRemote(DataBuffer*)'
passometer.ino:47:18: error: request for member 'InitBuffer' in 'databuffer', which is of non-class type 'DataBuffer()'
编译有误。
回复 支持 反对

使用道具 举报

发表于 2015-4-30 13:01:33 | 显示全部楼层
armray 发表于 2015-4-30 12:16
按照你刚才说的改了,可以运行,但输出还是一直是这样

(1) Classname objname( );  这样会有问题喔  ?
   奇怪, 难道 Arduino 的 C++ 解读 class / object 不同
(2)还是 0 ? 那我晚上再看看
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-30 13:02:55 | 显示全部楼层
tsaiwn 发表于 2015-4-30 11:35
Line 224 那句不对
    MPU6050  mpu6050=MPU6050();

从com口传回的结果来看,用MPU6050_read在setup中执行这样的操作是正确的:
error = mpu6050.MPU6050_read (MPU6050_WHO_AM_I, &c, 1);
也就是说MPU605_read 函数本身是没有错误的;

但在readFromsensor中调用,在loop中执行就是错误的;为了消除差异,

我有试过将readFromsensor放到setup中执行,,失败;
试过将readFromsensor中的MPU6050read的调用注释掉,直接填入相关代码,,失败。

感觉最后问题的解决不是及其简单就是及其高深
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-17 10:52 , Processed in 0.048651 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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