设为首页收藏本站

arduino 单片机机器人爱好者之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 10127|回复: 28

光立方原理图 制作过程V1.4,arduino驱动光立方,灯塔搭建,驱动函数,动画演示

[复制链接]

签到天数: 63 天

[LV.6]常住居民II

发表于 2014-1-14 08:16:17 | 显示全部楼层 |阅读模式

      因版本不同,驱动板外观有所区别,但灯塔的搭建方式是相同的。

亲自动手制作一个光立方,将能够给你带来无穷乐趣,做好后,还可以把他放在房间里,当作一盏小灯,每到夜晚,光彩夺目。

T2PN5WXw8XXXXXXXXX_!!230039547.jpg
光立方
1  光立方V1.3介绍

目前市面上大部分的光立方产品都是基于STC的51单片机来控制的,如果你擅长51单片机,这将都不会是问题,但如果你是Arduino用户,或者你精通STM32、MSP430或者其他控制器,那么无形中就会有很多的局限性。我们的推出的光立方,只需要3个IO引脚就能实现对512个LED的控制,也就是说不管你用什么控制器(当然像初级的51是不可以的,内存还是速度都跟不上),你都可以使用。即使你更换新的控制器,你同样可以使用它。光立方的控制非常的简单,对于很多朋友来说,困难之处在于焊接,因为想要512个LED整齐排列,并焊接牢靠,对于一般的人来说并非易事,但事实上是,焊接远没有你想象中的困难。甚至我们不需要借助外部工具,你只需要准备常规的器件即可动手了。

        驱动板从左往右,依次是电源开关、音频座、电源座、红外接收头、两个轻触按键、排针,排针引出的端口分别是VCC、GND(可以给外部提供5V电源);SER、RCK、SCK(驱动板驱动信号);L、R(左右声道模拟信号输出);IR(遥控信号输出);K1、K2(按键输出信号)。排针焊接时需要注意方向,尤其您使用光立方罩时。
排针方向.jpg

图1 排针焊接方式
        插件焊接时,根据下图所示焊接:
插件焊接.jpg


图2  插件焊接示意图
        还需要一些其他的必备工具:
        1:电烙铁1把,建议40元左右的,价格太便宜的烙铁不仅使用寿命短,温度也不能够保持恒定,最好带有静电保护的,降低灯珠被静电击穿的概率;
        2:焊锡丝4米,经过我们实际操作,一个光立方焊好后差不多使用了0.8mm直径的锡丝3.5米;
        3:斜口钳1把,主要用来剪引脚;4:口罩1只,为了自身的健康,这是比不可少的保护,因为这个工程也不是一两分钟的事儿。
2  光立方灯塔焊接
2.1  “点”
    灯塔的焊接是从“点”开始,我们先把灯的引脚折弯,如下图所示。左边为Ⅰ型灯,只需要弯折一次,一共需要弯折448个灯珠;右侧为Ⅱ型灯,需要弯折两次,共需要64个灯珠。长脚为阳极,短脚为阴极。
3.jpg
图3  灯引脚折弯(左为Ⅰ型,右为Ⅱ型)
2.2  “线”
        512个灯珠安装上节要求弯折好后,我们将进行“线”的焊接,线的焊接非常的简单,不需借用额外的模具,我们的控制板就是很好的模具。如图4所示,先将30MM的铜柱安装在驱动板上。
4.jpg
图4  30MM铜柱安装示意图
        铜柱安装到位后,我们将7个Ⅰ型灯、1个Ⅱ型灯的阳极插入驱动板PIN孔中,插件顺序,如图5所示。
5.jpg
图5  两种型号灯排列方式
        之后,我们用列子将灯的阴极引脚排列整齐,用烙铁焊接,使引脚相连,如图6所示。焊接时间不可太久,防止灯珠损坏,焊接的烙铁我们建议使用带有静电保护的。
6.jpg
图6  线的焊接
        焊接好后,将灯从驱动板上取出,并整理灯的引脚,使引脚之间相互垂直或平行,如图7所示。就以这种方法,完成剩下的63条“线”。
7.jpg
图7  焊接好的“线”
2.3  “面”
        64条线焊接完成后,我们的工程已经完成一半了,先偷着乐乐吧。
        在面焊接前,我们需要焊接一下驱动板上的芯片与圆孔PIN,焊接时,注意图8中的注意事项。4个5MM白发白氛围灯可以先不焊,等到面都焊接完成后在焊接,引脚暂时不剪。
8.jpg
图8  驱动板焊接
        圆孔PIN焊接需垂直于驱动板,这样可以保证灯塔搭建的美观。面的焊接我们就是利用焊好的圆孔PIN作为模板,就可以焊出完美的方格了,以这种方法依次焊好8个面。
9.jpg
图9  面的焊接
        8个面全部焊接好后,我们将对灯进行测试,找出坏“点”,及时更换,不然等体焊接好后将会带来更大的麻烦。测试很简单只需要一个3V左右的电源就可以了,当然,电压不能大于3.3V。神马!没有3V电源,嘿嘿。那我们氛围灯的引脚的用处就大大体现了。按照图10连接就可以进行测试了。经过我们的实际操作,没有灯不亮,当然,这不能保证所有。
10.jpg
图10  测试
2.3  “体”  
        面都测试完成后,我们将进行体的拼装与焊接焊接。如果您觉得阳极的引脚有些长,或者您想给他建个“阳光房”,按照图11所示的方法,将灯的引脚剪齐。
11.jpg
图11  修剪引脚
        先将面的阳极引脚插入圆孔PIN中,插入时需稍微用力,并调整灯高度,使灯的高度保持一致。如图12所示:
12.jpg
图12  插入引脚
        将面与面之间连接的引脚焊好,焊接时保证面与面之间等距、平行,且垂直于驱动板,将多余的引脚剪去。如图13:
13.jpg
图13  “体”完成
      就差层控制线的焊接了,如图14所示:
14.jpg
图14  层控制线焊接
        将灰色细线线头剥皮,从H1圆孔的下方穿到上方,将露出的铜丝弯成钩形,焊接在第一层阴极引脚上,将光立方底向上,亲亲拉着细线,用烙铁直接去靠近焊盘与细线,将线的绝缘皮融化、上锡,将细线从根部剪断,这样一根层控制线就焊接完成,这样可以保证层控制线是笔直的,且非常美观。
3  光立方驱动板
         光立方驱动板请移步下方下载,74hc595具体的使用方法请移步[url=读芯片手册及595串行实例全解 http://www.yfrobot.com/forum.php?mod=viewthread&tid=2389]读芯片手册及595串行实例全解[/url]。
         建立“体”的空间坐标系,如图15:
光立方坐标系.jpg
图15  坐标系
        Z=0为第1层、Z=1为第2层、···Z=7为第8层,在每一层中有8束光(就是我们前面焊接的“线”),一个立方共有64束,我们将他们分别编号为012···63(图3.1.2),每束光由8个灯组成。例如,第一层,我们分别编号012、···7。在X=0这个面,有08、···568束光
        我们数组的编号方式正好对应着数组中数,one[0]控制这光束0上面的8个灯,a[0]=0x01,用二进制表示就是00000001,控制(0,0,0)这个灯被点亮。如果a[1]=0x88,用二进制表示就是10001000,控制灯(1,3,0)和(1,7,0)两个灯亮,这样编号的优点,您会在今后的编程过程中慢慢体会到。        
        例如一个数组
        u8 one[]=
        {               
                ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
                ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
                ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
                ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
                ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
                ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
                ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
                ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
        }
        这个数组选择的是Y=0这个面的灯“同时”亮。“同时”我们加双引号,实际上在某一时刻只有一层灯是被点亮,对8层灯进行扫描,利用人眼的视觉停留效果,给人一种同时亮的错觉。
4  程序例解
        我们的程序是建立在控制器为“YFstm32核心控制板V1.0”的基础上编写的,程序为C语言编程,有较强的移植性,只需部分修改,就可以在其他控制器中运行。完整程序请到此贴结尾处下载。端口定义函数:
        #define SER PBout(8)  //串行数据输入
        #define RCK PBout(9)  //上升沿,串行输出,并行输出并锁存
        #define SCK PBout(10)  //上升沿,输入到移位寄存器
         根据端口设置,将控制器输出端口对应接到驱动板的SER、SCK、RCK上,控制板不驱动板用不同电源时,控制板上GND与驱动板上GND相连。
4.1  驱动函数
        数据最先被写入U8,然后通过移位,将数据从U8移到U7···U1,最后被移入U9 ,U9中的数据为层选择信号。
       下方贴出的程序为驱动函数:
  1. //595串行接法驱动程序
  2. //层填充函数,控制某层灯点亮方式
  3. //Called By:void Frame(u8 *a,u8 speed)
  4. //Input:*a
  5. //Output:SER、SCK
  6. void Storey(u8 *a)               
  7. {
  8.         u8 i , j , num ;
  9.         for(i = 0;i < 8;i++)
  10.         {
  11.                 num = a[i];                 //将数组中数输入寄存器
  12.                 for(j = 0;j < 8;j++) //串行数据输入
  13.                 {
  14.                         if(num&0x80)
  15.                                 SER = 1;          // SER串行输入端口
  16.                         else
  17.                                 SER = 0;
  18.                         SCK = 0;                  //上升沿,输入到移位寄存器
  19.                         delay_us(1);               
  20.                         SCK = 1;               
  21.                         num <<= 1;
  22.                 }
  23.         }
  24. }

  25. //帧控制函数
  26. //帧,就是影像动画中最小单位的单幅影像画面,相当于电影胶片上的每一
  27. //格镜头。一帧就是一副静止的画面,连续的帧就形成动画。
  28. //a是一帧编码起始地址
  29. //speed表示一帧画面扫描的次数,可以看作这帧显示的时间,这里我们理解为动画速度
  30. //Calls(被本函数调用的函数):void Storey(u8 *a)
  31. //Input:*a
  32. //Output:SER、SCK、RCK
  33. void Frame(u8 *a,u8 speed)
  34. {
  35.         u8 i,j,num;  
  36.         while(speed--)
  37.         {        
  38.                 num = 0x01;
  39.                 for(i = 0;i < 8;i++) //层数层控制,选通某一层,
  40.                              //使得第1层到第8层,依次点亮
  41.                 {        
  42.                         num <<= i;
  43.                         RCK = 0;
  44.                         for(j = 0;j < 8;j++) //串行数据输入,先写0
  45.                         {
  46.                                 SER = 0;
  47.                                 delay_us(1);
  48.                                 SCK= 0;                  //上升沿,输入到移位寄存器
  49.                                 delay_us(1);               
  50.                                 SCK = 1;               
  51.                         }

  52.                         for(j  =0;j < 8;j++) //串行数据输入,写入层控制数
  53.                         {
  54.                                 if(num & 0x80)
  55.                                         SER = 1;          // SER串行输入端口
  56.                                 else
  57.                                         SER = 0;
  58.                                 
  59.                                 SCK = 0;                  //上升沿,输入到移位寄存器
  60.                                 delay_us(1);               
  61.                                 SCK = 1;               
  62.                                 num <<= 1;
  63.                         }
  64.                         Storey(a+i*8);//层填充函数,控制某层灯点亮方式
  65.                         RCK= 1;
  66.                         num=0x01;                        
  67.                         delay_ms(2);   // 层显示时间
  68.                 }
  69.         }        
  70. }
复制代码
帧——就是影像动画中最小单位的单幅影像画面,相当于电影胶片上的每一格镜头。一帧就是一副静止的画面,连续的帧就形成动画。
4.2  动画一
  1. //动画内容是:侧面从左向右依次点亮
  2. void Face_LtoR(u8 speed)
  3. {
  4.         u8 b[64]={0};
  5.         u8 x,z;
  6.         for(z=0;z<8;z++)
  7.         {
  8.                 b[z*8]=0xff;
  9.         }
  10.         Frame(b,speed);//帧函数
  11.         for(x=1;x<8;x++)
  12.         {
  13.                 for(z=0;z<8;z++)
  14.                 {
  15.                         b[z*8+x]=0xff;
  16.                         b[z*8+(x-1)]=0;
  17.                 }
  18.                 Frame(b,speed);
  19.         }
  20.         All_Light_Off();
  21. }
复制代码
这里,先使编号为(z*8)+0的灯束全亮(0=<z<8),再使(z*8)+1的灯束都亮,这样就可以从从左往右依次点亮8个面的灯了。
4.3  动画二
  1. const u8 dot_tab[64]=
  2. {
  3.     0x01,0x01,0x00,0x00,0x00,0x00,0x01,0x01,
  4.         0x01,0x01,0x00,0x00,0x00,0x00,0x01,0x01,
  5.         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  6.     0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,
  7.     0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,
  8.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  9.     0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,
  10.     0x00,0x00,0x01,0x01,0x01,0x01,0x00,0x00,
  11. };

  12. //依次点亮00-1,01-1,02-1,03-1....63-1,笑脸
  13. void Dot(s8 time, u8 speed)        
  14. {
  15.         u8 b[64] = {0};
  16.         u8 x, z;
  17.         s8 t;
  18.         Frame(b, speed);
  19.         for(z = 0; z<8; z++)
  20.         {
  21.                 for(x = 0; x<8; x++)
  22.                 {
  23.                     b[z * 8 + x] = 0x01;
  24.                     Frame(b, speed);        
  25.                 }
  26.         }
  27.         for(z = 0; z<8; z++)
  28.         {
  29.             for(x = 0; x<8; x++)
  30.                     b[z * 8 + x] =  dot_tab[z * 8 + x];
  31.                 Frame(b, 20);
  32.         }
  33.         t=time;
  34.         while(t--)
  35.         {        
  36.             Frame(b, 200);
  37.         }
  38. }
复制代码
这里可以通过time的大小来设置笑脸显示时间长短。笑脸就是一个数组,通过不断的显示数组dot_tab[64]的内容,使光立方点亮“笑脸”。
经过我们的测试,灯全点亮2天两夜,共计48小时,光立方未出现异常。
光立方V1.4资料此文件主要包含:
1:驱动板原理图
2:芯片介绍
3:图片
4:光立方驱动程序V1.2--STM32控制
5:光立方--Arduino控制
6:新手理解FFT.pdf
7:基于单片机的音频频谱显示研究_FFT算法原理分析.pdf
8:光立方制作手册V1.3.pdf
9:FFT结果的物理意义.pdf
10:C语言实现FFT(快速傅里叶变换).pdf
Cube8SchV1.2.pdf (696.31 KB, 下载次数: 208)

签到天数: 63 天

[LV.6]常住居民II

 楼主| 发表于 2016-1-15 08:13:09 | 显示全部楼层
Sawada 发表于 2016-1-14 18:15
可是裡面的程序的副檔名都是.c例如LED.C要怎麼用Arduino燒錄
不好意思,搞错了,现在更新为1.4了。4楼的回复中也有相关连接。
回复 支持 1 反对 0

使用道具 举报

签到天数: 63 天

[LV.6]常住居民II

 楼主| 发表于 2014-2-14 09:55:09 | 显示全部楼层

光立方按键中断调速

光立方按键中断调速。
                                                                 
         这层楼,将介绍按键中断调速。调速!首先我们需要知道调哪个参数,可以改变动画速度,当然,第一个想到的就是变量speed,在很多的动画中我们都使用了这个变量,但是我们在显示每个动画的时候是不是都要检测speed的值?这样保证调速的实时性?主函数中,我们动画显示部分会不会很乱?好了,写了改变这个变量。我们就会对主函数动画部分进行大的改动。pass这个想法。
    再看void Frame(u8 *a,u8 speed),因为我们知道,每个动画显示时都会调用此函数。

  1. void Frame(u8 *a,u8 speed)
  2. {
  3.         u8 i,j,num;
  4.         while(speed--)
  5.         {        
  6.                 num = 0x01;
  7.                 for(i = 0;i < 8;i++) //层数层控制,选通某一层,
  8.                              //使得第1层到第8层,依次点亮
  9.                 {        
  10.                         num <<= i;
  11.                         RCK = 0;
  12.                         for(j = 0;j < 8;j++) //串行数据输入
  13.                         {
  14.                                 SER = 0;
  15.                                 delay_us(1);
  16.                                 SCK= 0;                  //上升沿,输入到移位寄存器
  17.                                 delay_us(1);               
  18.                                 SCK = 1;               
  19.                         }

  20.                         for(j  =0;j < 8;j++) //串行数据输入
  21.                         {
  22.                                 if(num & 0x80)
  23.                                         SER = 1;          // SER串行输入端口
  24.                                 else
  25.                                         SER = 0;
  26.                                 SCK = 0;                  //上升沿,输入到移位寄存器
  27.                                 delay_us(1);               
  28.                                 SCK = 1;               
  29.                                 num <<= 1;
  30.                         }
  31.                         Storey(a+i*8);//层填充函数,控制某层灯点亮方式
  32.                         RCK = 1;
  33.                         num=0x01;                        
  34. <font color="#ff0000">                        delay_ms(2);   // 层显示时间</font>
  35.                 }
  36.         }        
  37. }
复制代码
    是不是我们可以改变其它参数,间接的来改变动画速度,有的,请看红色字体那,层显示时间,我们改变它,也就间接的改变了每帧显示的时间,这样就达到了改变速度的目的。
   在led.c函数中我们声明一个全局变量:u8 GEAR = 4。 将delay_ms(2)改为delay_us(500 + (8-GEAR) * 250)。
   下面开始编写外部中断函数。
  1. #define KEY_DOWN PAin(6)  //PA6 速度减
  2. #define KEY_UP PAin(7)           //PA7 速度加
  3. void EXTIX_Init(void);//外部中断IO初始化
  4. //按键调速,共7个档位,调整光立方的运行数度
  5. //PA6,PA7外部中断输入端口,分别接驱动板的KEY1、KEY2
  6. //按下KEY1速度变慢,按下KEY2速度变快
  7. //外部中断服务函数
  8. void EXTI9_5_IRQHandler(void)
  9. {                        
  10. <font color="#ff0000">        delay_ms(1);    //消抖</font>                        
  11.         if(KEY_DOWN == 0)      //按键1
  12.         {
  13.             if(GEAR > 1 && GEAR < 8)
  14.                 {   
  15.                     -- GEAR;
  16.                         printf("%d\n",GEAR);
  17.                 }        
  18.         }
  19.         else if(KEY_UP == 0)//按键2
  20.         {
  21.                 if(GEAR > 0 && GEAR < 7)
  22.                 {
  23.                     ++ GEAR;
  24.                         printf("%d\n",GEAR);
  25.                 }
  26.         }
  27.         EXTI->PR = 1<<6;     //清除LINE6上的中断标志位  
  28.         EXTI->PR = 1<<7;     //清除LINE7上的中断标志位  
  29. }
  30. //外部中断初始化程序
  31. //初始化PA6,PA7为中断输入.
  32. void EXTIX_Init(void)
  33. {
  34.         RCC->APB2ENR |= 1<<2;     //使能PORTA时钟
  35.         JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG和SWD
  36.         GPIOA->CRL &= 0X00FFFFFF;//PA6,PA7设置成输入         
  37.         GPIOA->CRL |= 0X88000000;                                    
  38.         GPIOA->ODR |= 1<<6;           //PA6上拉
  39.         GPIOA->ODR |= 1<<7;           //PA7上拉
  40.         Ex_NVIC_Config( GPIO_A, 6, FTIR);//下降沿触发
  41.         Ex_NVIC_Config( GPIO_A, 7, FTIR);//下降沿触发
  42.         MY_NVIC_Init( 2, 1, EXTI9_5_IRQChannel, 2);//抢占2,子优先级1,组2           
  43. }
复制代码
通过上面的中断服务函数就可以实时改变GEAR的值了,需要注意的是消抖时间,这个时间不可很大,时间过长,按键中断时光立方就会出现“一闪”的现象。
回复 支持 反对

使用道具 举报

签到天数: 5 天

[LV.2]偶尔看看I

发表于 2015-5-13 09:49:50 | 显示全部楼层
请问有没有用arduino微控制器 控制8*8*8光立方的程序与接线图?
回复 支持 反对

使用道具 举报

签到天数: 63 天

[LV.6]常住居民II

 楼主| 发表于 2015-5-13 13:41:28 | 显示全部楼层
xiaochen 发表于 2015-5-13 09:49
请问有没有用arduino微控制器 控制8*8*8光立方的程序与接线图?

请您浏览:http://www.yfrobot.com/forum.php ... =%B9%E2%C1%A2%B7%BD
回复 支持 反对

使用道具 举报

签到天数: 5 天

[LV.2]偶尔看看I

发表于 2015-5-14 09:54:23 | 显示全部楼层
aosini 发表于 2015-5-13 13:41
请您浏览:http://www.yfrobot.com/forum.php?mod=viewthread&tid=11526&highlight=%B9%E2%C1%A2%B7%BD

非常感谢您,实在太棒了
回复 支持 反对

使用道具 举报

签到天数: 5 天

[LV.2]偶尔看看I

发表于 2015-5-14 11:37:14 | 显示全部楼层
本帖最后由 xiaochen 于 2015-5-14 12:35 编辑

请问电路板上 L、R(左右声道模拟信号输出),K1、K2(按键输出信号)4个端口分别要接在arduino板上的哪里,也是自定义的吗?我的电路板和你是完全相同的,如何才能输入音乐,要加驱动小卡才能用吗?现在就差音乐这部分不太懂了,知道回复一下哦,感谢了
回复 支持 反对

使用道具 举报

签到天数: 63 天

[LV.6]常住居民II

 楼主| 发表于 2015-5-14 14:18:34 | 显示全部楼层
xiaochen 发表于 2015-5-14 11:37
请问电路板上 L、R(左右声道模拟信号输出),K1、K2(按键输出信号)4个端口分别要接在arduino板上的哪里,也 ...

都需要自定义的,需要用到模拟量采集端口,将采集的数据进行傅立叶变换,得到不同频率所对应的幅值,这样就可以做成频谱了,具体请看光立方V1.3资料中《FFT结果的意义》,及fft.c。
  1. for(i=0;i<65;i++)
  2. {
  3.         dd[i].real=Get_Adc(ADC_CH0);          //读取ad结果;        
  4.         dd[i].imag=0;                //清零虚部
  5. }
复制代码
采集65个模拟值。


回复 支持 反对

使用道具 举报

签到天数: 5 天

[LV.2]偶尔看看I

发表于 2015-5-14 15:57:07 | 显示全部楼层
我浏览了你给我发的那网站里面的资料,可是为什么我用资料里面的arduino光立方程序执行起来看不出所写的效果,完全没有动态的感觉,求解,请问有没有以上3分钟视频的程序呢?可否提供,我再自己进行修改,谢谢
回复 支持 反对

使用道具 举报

签到天数: 63 天

[LV.6]常住居民II

 楼主| 发表于 2015-5-14 17:28:51 | 显示全部楼层
xiaochen 发表于 2015-5-14 15:57
我浏览了你给我发的那网站里面的资料,可是为什么我用资料里面的arduino光立方程序执行起来看不出所写的效 ...

1楼底层 “光立方V1.3资料”,里面包含了程序,但是stm32的,需要修改。
给您介绍的帖子中有使用说明的,你可以先检查一下接线,然后尝试运行一个简单的动画,像全亮。
回复 支持 反对

使用道具 举报

签到天数: 5 天

[LV.2]偶尔看看I

发表于 2015-5-15 14:26:34 | 显示全部楼层
请问面与面我放在驱动板上的位置方向和你的不一样,这会影响到程序所写的效果吗?还是没有差别?麻烦你了,谢谢
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|Archiver|手机版|小黑屋|联系我们|YFRobot ( 苏ICP备13017135  

GMT+8, 2017-4-27 07:32 , Processed in 0.441655 second(s), 33 queries .

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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