标题:
音乐频谱电路原理图与源程序分享
[打印本页]
作者:
boyfig
时间:
2016-5-1 16:04
标题:
音乐频谱电路原理图与源程序分享
一个学习单片机的程序及电路
原理图上画的是16 x 8的,实物是16 x 12的,另外加的4行LED分别由由P1.6、P1.7、P5.4和P5.5控制。
0.png
(63.93 KB, 下载次数: 174)
下载附件
2016-5-1 19:51 上传
完整的资料下载:
音乐频谱.zip
(476.95 KB, 下载次数: 282)
2016-5-1 16:04 上传
点击文件名下载附件
下载积分: 黑币 -5
音乐频谱电路图:
0.png
(133.99 KB, 下载次数: 143)
下载附件
2016-5-1 19:52 上传
音乐频谱源程序:
/*-----------------------------------------------------------------------*/
/* 单片机音乐频谱 */
/* 系统时钟33MHz */
/*-----------------------------------------------------------------------*/
/*-----------------------------宏定义-----------------------------------*/
#include<stc15f2k60s2.h> //stc15系列1T单片机
#define ADC_CHANNEL 0x01 //AD转换通道P1.0
#define ADC_POWER 0x80 //ADC电源控制位
#define ADC_SPEED 0x60 //90个时钟周期
#define ADC_START 0x08 //ADC启动控制位
#define ADC_FLAG 0x10 //ADC完成标志位
#define SAMPLE_NUM 64 //取64点FFT算法
#define NUM_2_LOG 6 //2的6次方
#define FFT_OUT_MIN 1 //FFT运算最小值
#define LED_C1_8 P2 //LED1~8列
#define LED_C9_16 P3 //LED9~16列
#define LED_R1_8 P0 //LED1~8行
/***************************引脚定义*****************************/
sbit LED_R1 = P0^0; //LED1~8行
sbit LED_R2 = P0^1;
sbit LED_R3 = P0^2;
sbit LED_R4 = P0^3;
sbit LED_R5 = P0^4;
sbit LED_R6 = P0^5;
sbit LED_R7 = P0^6;
sbit LED_R8 = P0^7;
sbit LED_R9 = P1^6; //LED第9行
sbit LED_R10 = P1^7; //LED第10行
sbit LED_R11 = P5^4; //LED第11行
sbit LED_R12 = P5^5; //LED第12行
sbit SWITCH = P4^5;
/*----------------------------变量表----------------------------*/
unsigned char code BIT_RESORT[SAMPLE_NUM] = { 0, 32, 16, 48, 8, 40, 24, 56,4, 36, 20, 52, 12, 44, 28, 60, //比特逆序重排
2, 34, 18, 50, 10, 42, 26, 58, 6, 38, 22, 54, 14, 46, 30, 62,
1, 33, 17, 49, 9, 41, 25, 57,5, 37, 21, 53, 13, 45, 29, 61,
3, 35, 19, 51, 11, 43, 27, 59,7, 39, 23, 55, 15, 47, 31, 63};
char code SIN_TAB[SAMPLE_NUM] = { 0 ,12 ,25 ,37 ,49 ,60 ,71 ,81 ,90 ,98 ,106 ,112 ,117 ,122 ,125 ,126 , //正弦表
127 ,126 ,125 ,122 ,117 ,112 ,106 ,98 ,90 ,81 ,71 ,60 ,49 ,37 ,25 ,12 ,
0 ,-12 ,-25 ,-37 ,-49 ,-60 ,-71 ,-81 ,-90 ,-98 ,-106 ,-112 ,-117 ,-122 ,-125 ,-126 ,
-127 ,-126 ,-125 ,-122 ,-117 ,-112 ,-106 ,-98 ,-90 ,-81 ,-71 ,-60 ,-49 ,-37 ,-25 ,-12 };
char code COS_TAB[SAMPLE_NUM] = {127 ,126 ,125 ,122 ,117 ,112 ,106 ,98 ,90 ,81 ,71 ,60 ,49 ,37 ,25 ,12 , //余弦表
0 ,-12 ,-25 ,-37 ,-49 ,-60 ,-71 ,-81 ,-90 ,-98 ,-106 ,-112 ,-117 ,-122 ,-125 ,-126 ,
-127 ,-126 ,-125 ,-122 ,-117 ,-112 ,-106 ,-98 ,-90 ,-81 ,-71 ,-60 ,-49 ,-37 ,-25 ,-12 ,
0 ,12 ,25 ,37 ,49 ,60 ,71 ,81 ,90 ,98 ,106 ,112 ,117 ,122 ,125 ,126 };
unsigned char LED_NUM[] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; //led显示数目
unsigned char AMP, AMP_TAB[16]; //频谱幅值,幅值表
unsigned char DISP_NUM; //显示次数
unsigned char KEEP, KEEP_NUM; //自动增益选择
int xdata FFT_REAL[SAMPLE_NUM]; //FFT运算结果实部
int xdata FFT_IMAGE[SAMPLE_NUM]; //FFT运算结果虚部
bit SWITCH_ON;
/**************************************************************
*名 称:delay
*功 能:微秒级延时
**************************************************************/
void Delay(unsigned int i)
{
while(i--);
}
/**************************************************************
*名 称:Delay_ms
*功 能:毫秒级延时
**************************************************************/
void Delay_ms(unsigned int x)
{
unsigned int i, j;
for(i = 0; i < x; i++)
for(j = 0; j < 500; j++);
}
/**************************************************************
*名 称:IOInit
*功 能:IO端口初始化
**************************************************************/
void IOInit(void)
{
P1M0 = 0x00; //高阻输入
P1M1 = 0x01;
P1ASF = 0x01; //设为AD转换
}
/**************************************************************
*名 称:Timer0Init
*功 能:定时器0初始化100us定时
**************************************************************/
void TimerInit(void) //100微秒@33.000MHz
{
AUXR = 0XC0; //定时器0-1T,定时器1-12T
TMOD = 0X00; //定时器0/1-方式0-16位自动重装
TL0 = 0X16; //定时器0-定时170us-显示幅值
TH0 = 0Xea;
TL1 = 0X1C; //定时器1-定时1ms-检测开关状态
TH1 = 0XF3;
TR0=1;
TR1 = 1;
}
/**********************************************************
*名 称:Display
*功 能:显示幅值
**********************************************************/
void Display(void)
{
DISP_NUM++;
if(DISP_NUM == 17)
DISP_NUM = 1;
LED_R1_8 = 0X00; LED_R9 = 0; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0; //显示前先关闭
switch(DISP_NUM) //逐列显示
{
case 1: AMP = AMP_TAB[0]; LED_C1_8 = 0X01; LED_C9_16 = 0x00; break;
case 2: AMP = AMP_TAB[1]; LED_C1_8 = 0X02; LED_C9_16 = 0x00; break;
case 3: AMP = AMP_TAB[2]; LED_C1_8 = 0X04; LED_C9_16 = 0x00; break;
case 4: AMP = AMP_TAB[3]; LED_C1_8 = 0X08; LED_C9_16 = 0x00; break;
case 5: AMP = AMP_TAB[4]; LED_C1_8 = 0X10; LED_C9_16 = 0x00; break;
case 6: AMP = AMP_TAB[5]; LED_C1_8 = 0X20; LED_C9_16 = 0x00; break;
case 7: AMP = AMP_TAB[6]; LED_C1_8 = 0X40; LED_C9_16 = 0x00; break;
case 8: AMP = AMP_TAB[7]; LED_C1_8 = 0X80; LED_C9_16 = 0x00; break;
case 9: AMP = AMP_TAB[8]; LED_C1_8 = 0X00; LED_C9_16 = 0x01; break;
case 10: AMP = AMP_TAB[9]; LED_C1_8 = 0X00; LED_C9_16 = 0x02; break;
case 11: AMP = AMP_TAB[10]; LED_C1_8 = 0X00; LED_C9_16 = 0x04; break;
case 12: AMP = AMP_TAB[11]; LED_C1_8 = 0X00; LED_C9_16 = 0x08; break;
case 13: AMP = AMP_TAB[12]; LED_C1_8 = 0X00; LED_C9_16 = 0x10; break;
case 14: AMP = AMP_TAB[13]; LED_C1_8 = 0X00; LED_C9_16 = 0x20; break;
case 15: AMP = AMP_TAB[14]; LED_C1_8 = 0X00; LED_C9_16 = 0x40; break;
case 16: AMP = AMP_TAB[15]; LED_C1_8 = 0X00; LED_C9_16 = 0x80; break;
}
if(AMP <= 8)
{
LED_R1_8 = LED_NUM[AMP];
LED_R9 = 0;
LED_R10 = 0;
LED_R11 = 0;
LED_R12 = 0;
}
if(AMP == 9)
{
LED_R1_8 = 0XFF;
LED_R9 = 1;
LED_R10 = 0;
LED_R11 = 0;
LED_R12 = 0;
}
if(AMP == 10)
{
LED_R1_8 = 0XFF;
LED_R9 = 1;
LED_R10 = 1;
LED_R11 = 0;
LED_R12 = 0;
}
if(AMP == 11)
{
LED_R1_8 = 0XFF;
LED_R9 = 1;
LED_R10 = 1;
LED_R11 = 1;
LED_R12 = 0;
}
if(AMP == 12)
{
LED_R1_8 = 0XFF;
LED_R9 = 1;
LED_R10 = 1;
LED_R11 = 1;
LED_R12 = 1;
}
// unsigned char i;
// LED_C1_8 = 0X01; LED_C9_16 = 0X00;
// for(i = 0; i < 8; i++)
// {
// if(LED_NUM[AMP_TAB[i]] <= 8)
// {
// LED_R1_8 = LED_NUM[AMP_TAB[i]];
// LED_R9 = 0; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0;
// }
// if(LED_NUM[AMP_TAB[i]] == 9)
// {
// LED_R1_8 = 0XFF;
// LED_R9 = 1; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0;
// }
// if(LED_NUM[AMP_TAB[i]] == 10)
// {
// LED_R1_8 = 0XFF;
// LED_R9 = 1; LED_R10 = 1; LED_R11 = 0; LED_R12 = 0;
// }
// if(LED_NUM[AMP_TAB[i]] == 11)
// {
// LED_R1_8 = 0XFF;
// LED_R9 = 1; LED_R10 = 1; LED_R11 = 1; LED_R12 = 0;
// }
// if(LED_NUM[AMP_TAB[i]] == 12)
// {
// LED_R1_8 = 0XFF;
// LED_R9 = 1; LED_R10 = 1; LED_R11 = 1; LED_R12 = 1;
// }
// Delay(2000);
// LED_C1_8 <<= 1;
// }
// LED_C1_8 = 0X00; LED_C9_16 = 0X01;
// for(i = 0; i < 8; i++)
// {
// if(LED_NUM[AMP_TAB[i]] <= 8)
// {
// LED_R1_8 = LED_NUM[AMP_TAB[i]];
// LED_R9 = 0; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0;
// }
// if(LED_NUM[AMP_TAB[i]] == 9)
// {
// LED_R1_8 = 0XFF;
// LED_R9 = 1; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0;
// }
// if(LED_NUM[AMP_TAB[i]] == 10)
// {
// LED_R1_8 = 0XFF;
// LED_R9 = 1; LED_R10 = 1; LED_R11 = 0; LED_R12 = 0;
// }
// if(LED_NUM[AMP_TAB[i]] == 11)
// {
// LED_R1_8 = 0XFF;
// LED_R9 = 1; LED_R10 = 1; LED_R11 = 1; LED_R12 = 0;
// }
// if(LED_NUM[AMP_TAB[i]] == 12)
// {
// LED_R1_8 = 0XFF;
// LED_R9 = 1; LED_R10 = 1; LED_R11 = 1; LED_R12 = 1;
// }
// Delay(2000);
// LED_C9_16 <<= 1;
// }
}
/************************************************
*名 称:ReadADC
*功 能:读取AD转换结果
************************************************/
unsigned char ReadADC(void)
{
ADC_CONTR = ADC_POWER + ADC_START; //启动转换
Delay(50);
while(!(ADC_CONTR & ADC_FLAG)); //等待转换结束
ADC_CONTR = ADC_POWER;
return (ADC_RES << 2 + ADC_RESL);
}
/************************************************
*名 称:sqrt
*功 能:算平方根
************************************************/
short sqrt( unsigned long M) //不懂啊
{
unsigned int N, i;
unsigned long tmp, ttp;
if( M == 0 )
return 0;
N = 0;
tmp = ( M >> 30 );
M <<= 2;
if( tmp > 1 )
{
N ++;
tmp -= N;
}
for( i=15; i>0; i-- )
{
N <<= 1;
tmp <<= 2;
tmp += (M >> 30);
ttp = N;
ttp = (ttp<<1)+1;
M <<= 2;
if( tmp >= ttp )
{
tmp -= ttp;
N ++;
}
}
return N;
}
/************************************************
*名 称:FFT
*功 能:快速傅里叶变换求取频谱
************************************************/
void FFT(void) //基2时分蝶式算法
{
// unsigned char i, j, r, m1, m2, m3, m4, k1, k2; //分别为:级号,蝶群号,运算蝶号,蝶群总数,蝶群长度,运算蝶数,蝶群址,蝶址
// unsigned char p;
// unsigned char MAX = 0;
// short u, v;
// unsigned long ulReal, ulImage;
register unsigned char i,bb,j,k,p,MAX;
register short TR,TI,temp;
unsigned long ulReal;
unsigned long ulImage;
for(i = 0; i < SAMPLE_NUM; i++) //采样
{
FFT_REAL[BIT_RESORT[i]] = ReadADC() << KEEP;
FFT_IMAGE[i] = 0;
}
KEEP_NUM = FFT_REAL[2] >> 4;
if((7 < KEEP_NUM) && (KEEP_NUM <= 8))
KEEP = 1;
else if((4 < KEEP_NUM) && (KEEP_NUM <= 6))
KEEP = 2;
else if((2 < KEEP_NUM) && (KEEP_NUM <= 4))
KEEP = 3;
else
KEEP = 5;
for( i=1; i<=NUM_2_LOG; i++)
{
bb=1;
bb <<= (i-1);
for( j=0; j<=bb-1; j++)
{
p=1;
p <<= (NUM_2_LOG-i);
p = p*j;
for( k=j; k<SAMPLE_NUM; k=k+2*bb)
{
TR = FFT_REAL[k]; TI = FFT_IMAGE[k]; temp = FFT_REAL[k+bb];
FFT_REAL[k] = FFT_REAL[k] + ((FFT_REAL[k+bb]*COS_TAB[p])>>7) + ((FFT_IMAGE[k+bb]*SIN_TAB[p])>>7);
FFT_IMAGE[k] = FFT_IMAGE[k] - ((FFT_REAL[k+bb]*SIN_TAB[p])>>7) + ((FFT_IMAGE[k+bb]*COS_TAB[p])>>7);
FFT_REAL[k+bb] = TR - ((FFT_REAL[k+bb]*COS_TAB[p])>>7) - ((FFT_IMAGE[k+bb]*SIN_TAB[p])>>7);
FFT_IMAGE[k+bb] = TI + ((temp*SIN_TAB[p])>>7) - ((FFT_IMAGE[k+bb]*COS_TAB[p])>>7);
FFT_REAL[k] >>= 1;
FFT_IMAGE[k] >>= 1;
FFT_REAL[k+bb] >>= 1;
FFT_IMAGE[k+bb] >>= 1;
}
}
}
// for(i = 1; i <= NUM_2_LOG; i++)
// {
// m1 = 1 << (i - 1);
// m2 = m1 << 1;
// m3 = 1 << (NUM_2_LOG - i);
// for(j = 0; j < m3; j++)
// {
// m4 = j * m2;
// for(r = 0; r < m1; r++)
// {
// p = r * m3;
// k1 = m4 + r;
// k2 = k1 + m1;
// u = (FFT_REAL[k2] * COS_TAB[p]) >> 7 + (FFT_IMAGE[k2] * SIN_TAB[p]) >> 7;
// v = (FFT_IMAGE[k2] * COS_TAB[p]) >> 7 + (FFT_REAL[k2] * SIN_TAB[p]) >> 7;
// FFT_REAL[k2] = FFT_REAL[k1] - u;
// FFT_IMAGE[k2] = FFT_IMAGE[k1] - v;
// FFT_REAL[k1] = FFT_REAL[k1] + u;
// FFT_IMAGE[k1] = FFT_IMAGE[k1] + v;
// FFT_REAL[k1] >>= 1;
// FFT_IMAGE[k1] >>= 1;
// FFT_REAL[k2] >>= 1;
// FFT_IMAGE[k2] >>= 1;
// }
// }
// }
for(i = 0; i < 16; i++)
{
ulReal = FFT_REAL[i + 1];
ulReal *= ulReal;
ulImage = FFT_IMAGE[i + 1];
ulImage *= ulImage;
AMP_TAB[i] = sqrt(ulImage + ulReal);
if(AMP_TAB[i] < FFT_OUT_MIN)
AMP_TAB[i] = 0;
else
AMP_TAB[i] -= FFT_OUT_MIN;
if(AMP_TAB[i] > MAX)
MAX = AMP_TAB[i];
}
if(MAX > 12)
{
MAX /= 12;
for(i = 0; i < 16; i++)
AMP_TAB[i] /= MAX;
}
}
/**********************************************************
*名 称:Display_zzz
*功 能;显示动画
**********************************************************/
void Display_zzz(void)
{
//逐行扫描-4帧
unsigned char code TAB_LED[4][24] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x07, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x07, 0x00, 0x02, 0x00, 0x07, 0x00, 0xe0, 0x01, 0x40, 0x00, 0x80, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x07, 0x00, 0x02, 0x00, 0x07, 0x00, 0xe0, 0x01, 0x40, 0x00, 0x80, 0x00, 0xe0, 0x01, 0x00, 0xf8, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0xf8}};
unsigned char i, j;
P0 = 0x00; LED_R9 = 0; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0;
for(i = 0; i < 4; i++)
{
for(j = 0; j < 100; j++)
{
LED_C1_8 = TAB_LED[i][2 * 0];
LED_C9_16 = TAB_LED[i][2 * 0 + 1];
LED_R1 = 1;
Delay_ms(2);
LED_R1 = 0;
LED_C1_8 = TAB_LED[i][2 * 1];
LED_C9_16 = TAB_LED[i][2 * 1 + 1];
LED_R2 = 1;
Delay_ms(2);
LED_R2 = 0;
LED_C1_8 = TAB_LED[i][2 * 2];
LED_C9_16 = TAB_LED[i][2 * 2 + 1];
LED_R3 = 1;
Delay_ms(2);
LED_R3 = 0;
LED_C1_8 = TAB_LED[i][2 * 3];
LED_C9_16 = TAB_LED[i][2 * 3 + 1];
LED_R4= 1;
Delay_ms(2);
LED_R4 = 0;
LED_C1_8 = TAB_LED[i][2 * 4];
LED_C9_16 = TAB_LED[i][2 * 4 + 1];
LED_R5 = 1;
Delay_ms(2);
LED_R5 = 0;
LED_C1_8 = TAB_LED[i][2 * 5];
LED_C9_16 = TAB_LED[i][2 * 5 + 1];
LED_R6 = 1;
Delay_ms(2);
LED_R6 = 0;
LED_C1_8 = TAB_LED[i][2 * 6];
LED_C9_16 = TAB_LED[i][2 * 6 + 1];
LED_R7 = 1;
Delay_ms(2);
LED_R7 = 0;
LED_C1_8 = TAB_LED[i][2 * 7];
LED_C9_16 = TAB_LED[i][2 * 7 + 1];
LED_R8 = 1;
Delay_ms(2);
LED_R8 = 0;
LED_C1_8 = TAB_LED[i][8 * 2];
LED_C9_16 = TAB_LED[i][8 * 2 + 1];
LED_R9 = 1;
Delay_ms(2);
LED_R9 = 0;
LED_C1_8 = TAB_LED[i][9 * 2];
LED_C9_16 = TAB_LED[i][9 *2 + 1];
LED_R10 = 1;
Delay_ms(2);
LED_R10 = 0;
LED_C1_8 = TAB_LED[i][10 *2];
LED_C9_16 = TAB_LED[i][10 * 2 + 1];
LED_R11 = 1;
Delay_ms(2);
LED_R11 = 0;
LED_C1_8 = TAB_LED[i][11 * 2];
LED_C9_16 = TAB_LED[i][11 * 2 + 1];
LED_R12 = 1;
Delay_ms(2);
LED_R12 = 0;
}
}
}
/************************************************
*名 称:main
*功 能:主函数
************************************************/
void main()
{
IOInit(); //初始化
TimerInit();
DISP_NUM = 0;
KEEP = 0;
KEEP_NUM = 0;
EA = 1; //开中断
ET1 = 1;
while(1)
{
if(SWITCH_ON == 0)
{
ET0 = 0;
Display_zzz();
}
if(SWITCH_ON == 1)
{
ET0 = 1;
FFT();
}
}
}
/************************************************
*名 称:Timer0Interrupt
*功 能:定时器0中断服务程序-显示
************************************************/
void Timer0Interrupt() interrupt 1
{
Display();
Delay(300);
}
/************************************************
*名 称:Timer1Interrupt
*功 能:定时器1中断服务程序-检测开关状态
************************************************/
void Timer1Interrupt() interrupt 3
{
if(SWITCH == 1)
SWITCH_ON = 1;
if(SWITCH == 0)
SWITCH_ON = 0;
}
复制代码
作者:
somlye
时间:
2016-5-7 10:06
下载保留学习
作者:
ebenyuan
时间:
2016-5-14 14:14
多谢楼主的分享!~~
作者:
无罪之宾
时间:
2016-6-15 23:19
不错的程序,学习学习
作者:
东北那谁
时间:
2016-9-1 05:36
好人,天下好人多
作者:
whsbk
时间:
2016-9-17 07:22
感谢楼主分享,最近在想关于频谱的显示问题,如同一行,假如第一列的不显示,而第二列的显示,在同一时间里这个问题怎么处理
作者:
ntmk
时间:
2016-9-25 00:33
好东西,多谢楼主的分享!~~
作者:
DIY电子
时间:
2016-9-25 07:35
多谢楼主的分享!
作者:
墨轩飞
时间:
2016-11-18 11:15
谢谢楼主分享
作者:
love2008
时间:
2017-6-1 09:02
看上去似乎不错
作者:
wyj191
时间:
2017-9-5 23:38
看上去似乎不错
作者:
tomli
时间:
2017-9-6 08:54
多谢楼主的分享!
作者:
c20160526
时间:
2017-11-9 07:56
我又来了,谢谢楼主
作者:
shaoliping66
时间:
2017-11-15 14:05
谢谢分享。
作者:
一个人丶一座城
时间:
2017-11-23 10:53
谢谢楼主!
作者:
woxinhengda
时间:
2018-8-1 21:07
感谢分享
作者:
woxinhengda
时间:
2018-10-9 21:44
感谢分享 学习学习
作者:
zrb5688
时间:
2019-1-20 17:42
感谢楼主分享。
作者:
1580418512
时间:
2019-6-11 18:42
下载保存,学习
作者:
1AJ1987402
时间:
2020-5-16 12:21
先顶再看,好东西
作者:
super123
时间:
2020-5-22 06:08
谢谢分享,收下了慢慢研究
作者:
KK咯了了
时间:
2020-6-2 00:30
谢谢楼主分享!学习了
作者:
源稚雨
时间:
2020-10-24 20:12
我想知道三极管的作用,,,
作者:
西村瘦马
时间:
2020-12-11 08:45
收藏了
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1