找回密码
 立即注册
楼主: 灰太狼8888

用【STCAI-万能实验板】做实验 用I2S音频播放方式实现电子琴

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:255
  • 最近打卡:2026-03-27 00:15:39
已绑定手机

11

主题

78

回帖

651

积分

高级会员

积分
651
发表于 2026-3-12 23:43:50 来自手机 | 显示全部楼层
自带流水灯程序测试OK,采用3.3V  5V电源均正常。
IMG_20260312_234014.jpg
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:255
  • 最近打卡:2026-03-27 00:15:39
已绑定手机

11

主题

78

回帖

651

积分

高级会员

积分
651
发表于 2026-3-14 07:13:15 来自手机 | 显示全部楼层
可以演奏了。但是音效播放结束有“砰砰声”,大佬们有没有遇到过,要怎么解决?

mmexport1773443341386.mp4

3.78 MB, 下载次数: 2

回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:255
  • 最近打卡:2026-03-27 00:15:39
已绑定手机

11

主题

78

回帖

651

积分

高级会员

积分
651
发表于 2026-3-17 23:02:40 | 显示全部楼层
终于完成了。代码如下:


  1. //=================== 头文件包含 ============================================
  2. #include "STC32G144K246.H"
  3. #include "intrins.h"
  4. #include "yinxiao1.h"
  5. #include "yinxiao2.h"
  6. #include "yinxiao3.h"
  7. #include "yinxiao4.h"
  8. #include "yinxiao5.h"
  9. #include "yinxiao6.h"
  10. #include "yinxiao7.h"
  11. //=================== 主时钟和采样率定义宏 =================================
  12. #define FOSC 96000000UL      // 系统主时钟 96MHz (由PLL产生)
  13. #define PLL_CLK 480000000UL  // PLL输出时钟 480MHz
  14. #define SampleRate 16000     // 定义采样率
  15. //=================== I2S配置 ============================================
  16. #define MCKOE 0 // I2S主时钟输出使能, 0:禁止I2S主时钟输出, 1:允许I2S主时钟输出
  17. #define I2SEN 0x04 // I2S使能位, 0x00:关闭, 0x04:使能
  18. #define I2S_MODE 2 // I2S模式, 0:从发送, 1:从接收, 2:主发送, 3:主接收,
  19. #define PCMSYNC 0  // PCM同步模式, 0: 长同步, 1: 短同步
  20. #define STD_MODE 0 // I2S标准模式, 0: I2S标准格式, 1: MSB对齐格式, 2:LSB对齐格式, 3:PCM模式
  21. #define CKPOL 0           // I2S时钟极性, 0:SCLK空闲时为低电平, 1:SCLK空闲时为高电平
  22. #define DATLEN 0   // 数据长度, 0:16位, 1:24位, 2:32位, 3:保留
  23. #define CHLEN 0           // 声道长度(在PCM模式下), 0:16位, 1: 32位
  24. // 分频系数计算
  25. #define I2S_MCLKDIV (FOSC / (8 * 16 * 2 * SampleRate))
  26. #define I2S_BCLKDIV (FOSC / (16 * 2 * SampleRate))
  27. //=================== 音频处理参数 ========================================
  28. #define MAX_ACTIVE 2         // 最大同时播放数
  29. #define VOLUME_SCALE 2       // 音量衰减系数,防止多个音频同时播放时溢出
  30. //=================== 类型定义 ============================================
  31. typedef unsigned char u8;
  32. typedef unsigned int u16;
  33. typedef unsigned long u32;
  34. typedef signed int s16;
  35. typedef signed long s32;
  36. // 扩展音频索引变量
  37. u16 yinxiao1_index;
  38. u16 yinxiao2_index;
  39. u16 yinxiao3_index;
  40. u16 yinxiao4_index;
  41. u16 yinxiao5_index;
  42. u16 yinxiao6_index;
  43. u16 yinxiao7_index;
  44. // 扩展音频播放状态
  45. bit yinxiao1;
  46. bit yinxiao2;
  47. bit yinxiao3;
  48. bit yinxiao4;
  49. bit yinxiao5;
  50. bit yinxiao6;
  51. bit yinxiao7;
  52. // 时间戳变量
  53. u16 start_time1;
  54. u16 start_time2;
  55. u16 start_time3;
  56. u16 start_time4;
  57. u16 start_time5;
  58. u16 start_time6;
  59. u16 start_time7;
  60. u16 current_time;
  61. // 按键状态变量
  62. bit key1_pressed;
  63. bit key2_pressed;
  64. bit key3_pressed;
  65. bit key4_pressed;
  66. bit key5_pressed;
  67. bit key6_pressed;
  68. bit key7_pressed;
  69. s16 buffer[2];
  70. bit flip;
  71. bit flip_local;
  72. //=================== 延时函数 ==============================================
  73. void delay_ms(u16 ms)
  74. {
  75.     u16 i;
  76.     while(ms--)
  77.     {
  78.         i = 4000;
  79.         while(i--);
  80.     }
  81. }
  82. //=================== PLL时钟初始化 ==========================================
  83. void pll_init(void)
  84. {
  85.     HPLLCR = 0x10;           // 选择HIRC作为PLL输入
  86.     HPLLPDIV = 8;            // 预分频8, HIRC 48MHz/8 = 6MHz
  87.     HPLLCR |= 0x0e;          // 倍频80, 6MHz*80 = 480MHz
  88.     HPLLCR |= 0x80;          // 使能HPLL
  89.    
  90.     delay_ms(10);
  91.    
  92.     CLKDIV = 5;              // 系统时钟分频: 480MHz/5 = 96MHz
  93.     CLKSEL = 0x04;           // 选择HPLL/2作为主时钟源
  94.    
  95.     delay_ms(10);
  96. }
  97. //=================== 计算活跃音频数量的函数 =================================
  98. u8 get_active_count(void)
  99. {
  100.     u8 count = 0;
  101.     if (yinxiao1) count++;
  102.     if (yinxiao2) count++;
  103.     if (yinxiao3) count++;
  104.     if (yinxiao4) count++;
  105.     if (yinxiao5) count++;
  106.     if (yinxiao6) count++;
  107.     if (yinxiao7) count++;
  108.     return count;
  109. }
  110. //=================== 查找最旧音频的函数 ====================================
  111. u8 find_oldest_channel(u8 exclude_channel)
  112. {
  113.     u16 oldest_time = 0xFFFF;
  114.     u8 oldest_channel = 0;
  115.    
  116.     if (yinxiao1 && (1 != exclude_channel) && start_time1 < oldest_time) {
  117.         oldest_time = start_time1;
  118.         oldest_channel = 1;
  119.     }
  120.     if (yinxiao2 && (2 != exclude_channel) && start_time2 < oldest_time) {
  121.         oldest_time = start_time2;
  122.         oldest_channel = 2;
  123.     }
  124.     if (yinxiao3 && (3 != exclude_channel) && start_time3 < oldest_time) {
  125.         oldest_time = start_time3;
  126.         oldest_channel = 3;
  127.     }
  128.     if (yinxiao4 && (4 != exclude_channel) && start_time4 < oldest_time) {
  129.         oldest_time = start_time4;
  130.         oldest_channel = 4;
  131.     }
  132.     if (yinxiao5 && (5 != exclude_channel) && start_time5 < oldest_time) {
  133.         oldest_time = start_time5;
  134.         oldest_channel = 5;
  135.     }
  136.     if (yinxiao6 && (6 != exclude_channel) && start_time6 < oldest_time) {
  137.         oldest_time = start_time6;
  138.         oldest_channel = 6;
  139.     }
  140.     if (yinxiao7 && (7 != exclude_channel) && start_time7 < oldest_time) {
  141.         oldest_time = start_time7;
  142.         oldest_channel = 7;
  143.     }
  144.    
  145.     return oldest_channel;
  146. }
  147. //=================== 停止指定音频的函数 ====================================
  148. void stop_channel(u8 channel)
  149. {
  150.     switch(channel) {
  151.         case 1: yinxiao1 = 0; yinxiao1_index = 0; start_time1 = 0; break;
  152.         case 2: yinxiao2 = 0; yinxiao2_index = 0; start_time2 = 0; break;
  153.         case 3: yinxiao3 = 0; yinxiao3_index = 0; start_time3 = 0; break;
  154.         case 4: yinxiao4 = 0; yinxiao4_index = 0; start_time4 = 0; break;
  155.         case 5: yinxiao5 = 0; yinxiao5_index = 0; start_time5 = 0; break;
  156.         case 6: yinxiao6 = 0; yinxiao6_index = 0; start_time6 = 0; break;
  157.         case 7: yinxiao7 = 0; yinxiao7_index = 0; start_time7 = 0; break;
  158.     }
  159. }
  160. //=================== 启动指定音频的函数 ====================================
  161. void start_channel(u8 channel)
  162. {
  163.     switch(channel) {
  164.         case 1: yinxiao1 = 1; yinxiao1_index = 0; start_time1 = current_time; break;
  165.         case 2: yinxiao2 = 1; yinxiao2_index = 0; start_time2 = current_time; break;
  166.         case 3: yinxiao3 = 1; yinxiao3_index = 0; start_time3 = current_time; break;
  167.         case 4: yinxiao4 = 1; yinxiao4_index = 0; start_time4 = current_time; break;
  168.         case 5: yinxiao5 = 1; yinxiao5_index = 0; start_time5 = current_time; break;
  169.         case 6: yinxiao6 = 1; yinxiao6_index = 0; start_time6 = current_time; break;
  170.         case 7: yinxiao7 = 1; yinxiao7_index = 0; start_time7 = current_time; break;
  171.     }
  172. }
  173. //=================== 8位无符号转16位有符号 ==================================
  174. s16 convert_u8_to_s16(u8 sample)
  175. {
  176.     // 8位无符号(0-255)转16位有符号(-32768-32767)
  177.     // 静音值128 -> 0
  178.     return ((s16)(sample - 0x80)) << 8;
  179. }
  180. //=================== 固定音量衰减 ==========================================
  181. s16 apply_fixed_volume(s32 sum)
  182. {
  183.     // 固定衰减,确保多个音频同时播放时不会溢出
  184.     // 最多同时播放2个音频,衰减2倍足够
  185.     sum = sum / VOLUME_SCALE;
  186.    
  187.     // 硬限幅,防止极端情况
  188.     if (sum > 32767) {
  189.         return 32767;
  190.     } else if (sum < -32768) {
  191.         return -32768;
  192.     } else {
  193.         return (s16)sum;
  194.     }
  195. }
  196. //=================== 主函数 ==============================================
  197. void main(void)
  198. {
  199.     u8 active_count;
  200.     u8 oldest_channel;
  201.     s32 temp_sum;
  202.    
  203.     // 初始化系统
  204.     WTST = 0x00;
  205.     CKCON = 0x00;
  206.     EAXFR = 1;
  207.     // 初始化PLL时钟
  208.     pll_init();
  209.     // 初始化IO口
  210.     P2M0 = 0x00;
  211.     P2M1 = 0x00;
  212.     P2PU = 0xff;                
  213.        
  214.     P7M0 = 0x00;
  215.     P7M1 = 0x00;
  216.     P7PU = 0xff;        
  217.     I2SMD = 0xff;
  218.     I2SSR = 0x00;
  219.     I2SCR = 0x80 + 0x00;
  220.     HSCLKDIV = 1;
  221.     I2S_CLKDIV = 1;
  222.     I2SMCKDIV = I2S_MCLKDIV;
  223.     I2SPRH = (MCKOE << 1) + (I2S_BCLKDIV & 1);
  224.     I2SPRL = I2S_BCLKDIV / 2;
  225.     I2SCFGH = I2S_MODE;
  226.     I2SCFGL = (PCMSYNC << 7) + (STD_MODE << 4) + (CKPOL << 3) + (DATLEN << 1) + CHLEN;
  227.     P_SW3 = (P_SW3 & 0x3f) | (2 << 6);
  228.     I2SCFGH |= I2SEN;
  229.     // 初始化音频播放状态
  230.     yinxiao1_index = 0; yinxiao1 = 0; start_time1 = 0;
  231.     yinxiao2_index = 0; yinxiao2 = 0; start_time2 = 0;
  232.     yinxiao3_index = 0; yinxiao3 = 0; start_time3 = 0;
  233.     yinxiao4_index = 0; yinxiao4 = 0; start_time4 = 0;
  234.     yinxiao5_index = 0; yinxiao5 = 0; start_time5 = 0;
  235.     yinxiao6_index = 0; yinxiao6 = 0; start_time6 = 0;
  236.     yinxiao7_index = 0; yinxiao7 = 0; start_time7 = 0;
  237.     current_time = 0;
  238.     // 初始化按键状态
  239.     key1_pressed = 0; key2_pressed = 0; key3_pressed = 0; key4_pressed = 0;
  240.     key5_pressed = 0; key6_pressed = 0; key7_pressed = 0;
  241.     // 初始化双缓冲区
  242.     flip = 0;
  243.     flip_local = 0;
  244.     buffer[0] = 0;
  245.     buffer[1] = 0;
  246.     EA = 1;  // 开启全局中断
  247.     while (1)
  248.     {
  249.         if (flip_local != flip)
  250.         {
  251.             temp_sum = 0;
  252.             
  253.             // 更新时间计数器
  254.             current_time++;
  255.             if (current_time > 60000) {
  256.                 current_time = 0;
  257.                 if (yinxiao1) start_time1 = current_time;
  258.                 if (yinxiao2) start_time2 = current_time;
  259.                 if (yinxiao3) start_time3 = current_time;
  260.                 if (yinxiao4) start_time4 = current_time;
  261.                 if (yinxiao5) start_time5 = current_time;
  262.                 if (yinxiao6) start_time6 = current_time;
  263.                 if (yinxiao7) start_time7 = current_time;
  264.             }
  265.             
  266.             // 按键检测
  267.             if (P71 == 0) {
  268.                 if (!key1_pressed) {
  269.                     key1_pressed = 1;
  270.                     if (yinxiao1) {
  271.                         yinxiao1_index = 0;
  272.                         start_time1 = current_time;
  273.                     } else {
  274.                         active_count = get_active_count();
  275.                         if (active_count >= MAX_ACTIVE) {
  276.                             oldest_channel = find_oldest_channel(1);
  277.                             if (oldest_channel != 0) {
  278.                                 stop_channel(oldest_channel);
  279.                             }
  280.                         }
  281.                         start_channel(1);
  282.                     }
  283.                 }
  284.             } else {
  285.                 key1_pressed = 0;
  286.             }
  287.             
  288.             if (P72 == 0) {
  289.                 if (!key2_pressed) {
  290.                     key2_pressed = 1;
  291.                     if (yinxiao2) {
  292.                         yinxiao2_index = 0;
  293.                         start_time2 = current_time;
  294.                     } else {
  295.                         active_count = get_active_count();
  296.                         if (active_count >= MAX_ACTIVE) {
  297.                             oldest_channel = find_oldest_channel(2);
  298.                             if (oldest_channel != 0) {
  299.                                 stop_channel(oldest_channel);
  300.                             }
  301.                         }
  302.                         start_channel(2);
  303.                     }
  304.                 }
  305.             } else {
  306.                 key2_pressed = 0;
  307.             }
  308.             
  309.             if (P73 == 0) {
  310.                 if (!key3_pressed) {
  311.                     key3_pressed = 1;
  312.                     if (yinxiao3) {
  313.                         yinxiao3_index = 0;
  314.                         start_time3 = current_time;
  315.                     } else {
  316.                         active_count = get_active_count();
  317.                         if (active_count >= MAX_ACTIVE) {
  318.                             oldest_channel = find_oldest_channel(3);
  319.                             if (oldest_channel != 0) {
  320.                                 stop_channel(oldest_channel);
  321.                             }
  322.                         }
  323.                         start_channel(3);
  324.                     }
  325.                 }
  326.             } else {
  327.                 key3_pressed = 0;
  328.             }               
  329.             
  330.             if (P74 == 0) {
  331.                 if (!key4_pressed) {
  332.                     key4_pressed = 1;
  333.                     if (yinxiao4) {
  334.                         yinxiao4_index = 0;
  335.                         start_time4 = current_time;
  336.                     } else {
  337.                         active_count = get_active_count();
  338.                         if (active_count >= MAX_ACTIVE) {
  339.                             oldest_channel = find_oldest_channel(4);
  340.                             if (oldest_channel != 0) {
  341.                                 stop_channel(oldest_channel);
  342.                             }
  343.                         }
  344.                         start_channel(4);
  345.                     }
  346.                 }
  347.             } else {
  348.                 key4_pressed = 0;
  349.             }
  350.             if (P75 == 0) {
  351.                 if (!key5_pressed) {
  352.                     key5_pressed = 1;
  353.                     if (yinxiao5) {
  354.                         yinxiao5_index = 0;
  355.                         start_time5 = current_time;
  356.                     } else {
  357.                         active_count = get_active_count();
  358.                         if (active_count >= MAX_ACTIVE) {
  359.                             oldest_channel = find_oldest_channel(5);
  360.                             if (oldest_channel != 0) {
  361.                                 stop_channel(oldest_channel);
  362.                             }
  363.                         }
  364.                         start_channel(5);
  365.                     }
  366.                 }
  367.             } else {
  368.                 key5_pressed = 0;
  369.             }
  370.             if (P76 == 0) {
  371.                 if (!key6_pressed) {
  372.                     key6_pressed = 1;
  373.                     if (yinxiao6) {
  374.                         yinxiao6_index = 0;
  375.                         start_time6 = current_time;
  376.                     } else {
  377.                         active_count = get_active_count();
  378.                         if (active_count >= MAX_ACTIVE) {
  379.                             oldest_channel = find_oldest_channel(6);
  380.                             if (oldest_channel != 0) {
  381.                                 stop_channel(oldest_channel);
  382.                             }
  383.                         }
  384.                         start_channel(6);
  385.                     }
  386.                 }
  387.             } else {
  388.                 key6_pressed = 0;
  389.             }
  390.             if (P77 == 0) {
  391.                 if (!key7_pressed) {
  392.                     key7_pressed = 1;
  393.                     if (yinxiao7) {
  394.                         yinxiao7_index = 0;
  395.                         start_time7 = current_time;
  396.                     } else {
  397.                         active_count = get_active_count();
  398.                         if (active_count >= MAX_ACTIVE) {
  399.                             oldest_channel = find_oldest_channel(7);
  400.                             if (oldest_channel != 0) {
  401.                                 stop_channel(oldest_channel);
  402.                             }
  403.                         }
  404.                         start_channel(7);
  405.                     }
  406.                 }
  407.             } else {
  408.                 key7_pressed = 0;
  409.             }
  410.             // 音频混合处理 - 简单累加,不做动态调整
  411.             if (yinxiao1) {
  412.                 temp_sum += convert_u8_to_s16(yinxiao1_pcm[yinxiao1_index++]);
  413.                 if (yinxiao1_index >= yinxiao1_pcm_len) {
  414.                     yinxiao1 = 0;
  415.                     yinxiao1_index = 0;
  416.                     start_time1 = 0;
  417.                 }
  418.             }
  419.             
  420.             if (yinxiao2) {
  421.                 temp_sum += convert_u8_to_s16(yinxiao2_pcm[yinxiao2_index++]);
  422.                 if (yinxiao2_index >= yinxiao2_pcm_len) {
  423.                     yinxiao2 = 0;
  424.                     yinxiao2_index = 0;
  425.                     start_time2 = 0;
  426.                 }
  427.             }
  428.             
  429.             if (yinxiao3) {
  430.                 temp_sum += convert_u8_to_s16(yinxiao3_pcm[yinxiao3_index++]);
  431.                 if (yinxiao3_index >= yinxiao3_pcm_len) {
  432.                     yinxiao3 = 0;
  433.                     yinxiao3_index = 0;
  434.                     start_time3 = 0;
  435.                 }
  436.             }
  437.             
  438.             if (yinxiao4) {
  439.                 temp_sum += convert_u8_to_s16(yinxiao4_pcm[yinxiao4_index++]);
  440.                 if (yinxiao4_index >= yinxiao4_pcm_len) {
  441.                     yinxiao4 = 0;
  442.                     yinxiao4_index = 0;
  443.                     start_time4 = 0;
  444.                 }
  445.             }
  446.             
  447.             if (yinxiao5) {
  448.                 temp_sum += convert_u8_to_s16(yinxiao5_pcm[yinxiao5_index++]);
  449.                 if (yinxiao5_index >= yinxiao5_pcm_len) {
  450.                     yinxiao5 = 0;
  451.                     yinxiao5_index = 0;
  452.                     start_time5 = 0;
  453.                 }
  454.             }
  455.             
  456.             if (yinxiao6) {
  457.                 temp_sum += convert_u8_to_s16(yinxiao6_pcm[yinxiao6_index++]);
  458.                 if (yinxiao6_index >= yinxiao6_pcm_len) {
  459.                     yinxiao6 = 0;
  460.                     yinxiao6_index = 0;
  461.                     start_time6 = 0;
  462.                 }
  463.             }
  464.             
  465.             if (yinxiao7) {
  466.                 temp_sum += convert_u8_to_s16(yinxiao7_pcm[yinxiao7_index++]);
  467.                 if (yinxiao7_index >= yinxiao7_pcm_len) {
  468.                     yinxiao7 = 0;
  469.                     yinxiao7_index = 0;
  470.                     start_time7 = 0;
  471.                 }
  472.             }
  473.             
  474.             // 固定音量衰减,确保不溢出
  475.             buffer[flip_local] = apply_fixed_volume(temp_sum);
  476.             flip_local = flip;
  477.         }
  478.     }
  479. }
  480. //=================== I2S中断服务函数 ======================================
  481. void I2S_ISR(void) interrupt I2S_VECTOR
  482. {
  483.     if (I2SSR & 0x02)
  484.     {
  485.         if (I2SSR & 0x04)
  486.         {
  487.             I2SDRH = (u8)(buffer[flip] >> 8);
  488.             I2SDRL = (u8)(buffer[flip] & 0xFF);
  489.         }
  490.         else
  491.         {
  492.             I2SDRH = (u8)(buffer[flip] >> 8);
  493.             I2SDRL = (u8)(buffer[flip] & 0xFF);
  494.             flip = !flip;
  495.         }
  496.     }
  497. }
复制代码
哪位大佬有灵感菇的那个魔性音乐的音频?我想换上去试试


编译后的程序: 电子琴.hex (371.92 KB, 下载次数: 0)

主程序: main.c (17.66 KB, 下载次数: 0)
音频文件: yinxiao1.h (154.56 KB, 下载次数: 0) yinxiao2.h (152 KB, 下载次数: 0) yinxiao3.h (85.68 KB, 下载次数: 0) yinxiao4.h (121.39 KB, 下载次数: 0) yinxiao5.h (126.49 KB, 下载次数: 0) yinxiao6.h (89.5 KB, 下载次数: 0) yinxiao7.h (79.3 KB, 下载次数: 0)
B站视频:[url=【电子琴还能这样做?那换一组劲爆的音频文件不是要起飞?】https://www.bilibili.com/video/B ... e8ecff012a751924660]【电子琴还能这样做?那换一组劲爆的音频文件不是要起飞?】https://www.bilibili.com/video/B ... e8ecff012a751924660[/url]
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:201
  • 最近打卡:2026-03-27 08:59:17
已绑定手机

3

主题

86

回帖

514

积分

高级会员

积分
514
发表于 2026-3-18 08:01:39 | 显示全部楼层
接各种嵌入式兼职,传感器,电机驱动等软硬件
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:255
  • 最近打卡:2026-03-27 00:15:39
已绑定手机

11

主题

78

回帖

651

积分

高级会员

积分
651
发表于 2026-3-18 13:09:44 来自手机 | 显示全部楼层
有小伙伴说我视频里差点弹错键,没关系,我准备给你们上点科技。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:255
  • 最近打卡:2026-03-27 00:15:39
已绑定手机

11

主题

78

回帖

651

积分

高级会员

积分
651
发表于 2026-3-19 22:07:34 来自手机 | 显示全部楼层
焊一组光电开关,准备读纸带
IMG_20260319_192700.jpg
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-3-27 09:04 , Processed in 0.112752 second(s), 65 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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