[APM32E1] 【APM32E103xE测评】基于APM32E103的RGB七彩渐变呼吸灯

[复制链接]
 楼主| lilijin1995 发表于 2022-8-14 21:32 | 显示全部楼层 |阅读模式
本帖最后由 lilijin1995 于 2022-8-16 14:04 编辑

【APM32E103xE测评】基于APM32E103的RGB七彩渐变呼吸灯附送渐变算法并配置1ms Systick移植了MultiTimer
非常荣幸在“二姨家”申请到了“APM32E103ZE MINI板”,由于手头上有一个简单的控灯项目,所以直接想在APM32E103ZE跑跑看;
本贴分以下几个部分:

  • 硬件介绍:
      硬件主要有12V的RGB灯板和RGB-MOS管驱动板;如下图
微信图片_20220814215342.jpg
另有原理图如下:
微信截图_20220814215616.png 微信截图_20220814215636.png

  • 软件介绍:
      软件主要分两部分:
      1. MultiTimer移植:          MultiTimer是开源项目 ,一款可无限扩展的软件定时器,作者0x1abin,目前收获 95 个 star,遵循 MIT 开源许可协议。MultiTimer 是一个软件定时器扩展模块,可无限扩展你所需的定时器任务,取代传统的标志位判断方式, 更优雅更便捷地管理程序的时间触发时序。
         首先需要配置Systick为1ms中断一次SysTick_Config(SystemCoreClock / 1000),
  1. int main(void)
  2. {
  3.     SysTick_Config(SystemCoreClock / 1000);
  4.     Board_Init();   
  5.     while(1)
  6.     {
  7.           MultiTimerYield();
  8.     }
  9. }
并在SysTick_Handler中自加
  1. void SysTick_Handler(void)
  2. {
  3.     tick++;
  4. }<span style="background-color: rgb(255, 255, 255);">        </span>
接着我们添加MultiTimer代码
  1. #include "MultiTimer.h"
  2. #include <stdio.h>
  3. /* Timer handle list head. */
  4. static MultiTimer* timerList = NULL;
  5. /* Timer tick */
  6. static PlatformTicksFunction_t platformTicksFunction = NULL;
  7. int MultiTimerInstall(PlatformTicksFunction_t ticksFunc)
  8. {
  9.     platformTicksFunction = ticksFunc;
  10.     return 0;
  11. }
  12. int MultiTimerStart(MultiTimer* timer, uint64_t timing, MultiTimerCallback_t callback, void* userData)
  13. {
  14.     if (!timer || !callback ) {
  15.         return -1;
  16.     }
  17.     MultiTimer** nextTimer = &timerList;
  18.     /* Remove the existing target timer. */
  19.     for (; *nextTimer; nextTimer = &(*nextTimer)->next) {
  20.         if (timer == *nextTimer) {
  21.             *nextTimer = timer->next; /* remove from list */
  22.             break;
  23.         }
  24.     }
  25.     /* Init timer. */
  26.     timer->deadline = platformTicksFunction() + timing;
  27.     timer->callback = callback;
  28.     timer->userData = userData;
  29.     /* Insert timer. */
  30.     for (nextTimer = &timerList;; nextTimer = &(*nextTimer)->next) {
  31.         if (!*nextTimer) {
  32.             timer->next = NULL;
  33.             *nextTimer = timer;
  34.             break;
  35.         }
  36.         if (timer->deadline < (*nextTimer)->deadline) {
  37.             timer->next = *nextTimer;
  38.             *nextTimer = timer;
  39.             break;
  40.         }
  41.     }
  42.     return 0;
  43. }
  44. int MultiTimerStop(MultiTimer* timer)
  45. {
  46.     MultiTimer** nextTimer = &timerList;
  47.     /* Find and remove timer. */
  48.     for (; *nextTimer; nextTimer = &(*nextTimer)->next) {
  49.         MultiTimer* entry = *nextTimer;
  50.         if (entry == timer) {
  51.             *nextTimer = timer->next;
  52.             break;
  53.         }
  54.     }
  55.     return 0;
  56. }
  57. int MultiTimerYield(void)
  58. {
  59.     MultiTimer* entry = timerList;
  60.     for (; entry; entry = entry->next) {
  61.         /* Sorted list, just process with the front part. */
  62.         if (platformTicksFunction() < entry->deadline) {
  63.             return (int)(entry->deadline - platformTicksFunction());
  64.         }
  65.         /* remove expired timer from list */
  66.         timerList = entry->next;

  67.         /* call callback */
  68.         if (entry->callback) {
  69.             entry->callback(entry, entry->userData);
  70.         }
  71.     }
  72.     return 0;
  73. }


最后我们直接开两个定时器即两个线程,一个作为按键扫描,一个作为灯光的控制
  1. #include "Board.h"
  2. #if defined (APM32E103_MINI)
  3. #include "Board_APM32E103_MINI.c"
  4. #include "RGB.h"
  5. #include "KEY.h"
  6. volatile uint64_t tick = 0;
  7. MultiTimer timer1;
  8. MultiTimer timer2;

  9. uint64_t PlatformTicksGetFunc(void)
  10. {
  11.     return tick;
  12. }

  13. void RGBTimer1Callback(MultiTimer* timer, void *userData)
  14. {
  15.     switch(RGB_Eff)
  16.     {
  17.     case DYN_RGB:
  18.     {
  19.         GradientDreamColor();
  20.     }
  21.     break;
  22.     case DYN_RED:
  23.     {
  24.         GradientDreamSingleColor(DYN_RED);
  25.     }
  26.     break;
  27.     case DYN_ORANGE:
  28.     {
  29.         GradientDreamSingleColor(DYN_ORANGE);
  30.     }
  31.     break;
  32.     case DYN_YELLOW:
  33.     {
  34.         GradientDreamSingleColor(DYN_YELLOW);
  35.     }
  36.     break;
  37.     case DYN_GREE:
  38.     {
  39.         GradientDreamSingleColor(DYN_GREE);
  40.     }
  41.     break;
  42.     case DYN_CYAN:
  43.     {
  44.         GradientDreamSingleColor(DYN_CYAN);
  45.     }
  46.     break;
  47.     case DYN_BLUE:
  48.     {
  49.         GradientDreamSingleColor(DYN_BLUE);
  50.     }
  51.     break;
  52.     case DYN_PURPLE:
  53.     {
  54.         GradientDreamSingleColor(DYN_PURPLE);
  55.     }
  56.     break;
  57.     case STATICK_RED:
  58.     {
  59.         SetRGB_PWM(0xFF,0x00,0x00);
  60.     }
  61.     break;
  62.     case STATICK_ORANGE:
  63.     {
  64.         SetRGB_PWM(225,69,0);
  65.     }
  66.     break;
  67.     case STATICK_YELLOW:
  68.     {
  69.         SetRGB_PWM(0xFF,0xFF,0x00);
  70.     }
  71.     break;
  72.     case STATICK_GREEN:
  73.     {
  74.         SetRGB_PWM(0x00,0xFF,0x00);
  75.     }
  76.     break;
  77.     case STATICK_CYAN:
  78.     {
  79.         SetRGB_PWM(0x00,0xFF,0xFF);
  80.     }
  81.     break;
  82.     case STATICK_BLUE:
  83.     {
  84.         SetRGB_PWM(0x00,0x00,0xFF);
  85.     }
  86.     break;
  87.     case STATICK_PURPLE:
  88.     {
  89.         SetRGB_PWM(0xFF,0x00,0xFF);
  90.     }
  91.     break;
  92.     case STATICK_WHITE:
  93.     {
  94.         SetRGB_PWM(0xFF,0xFF,0xFF);
  95.     }
  96.     break;
  97.     case STATICK_BLACK:
  98.     {
  99.         SetRGB_PWM(0x00,0x00,0x00);
  100.     }
  101.     break;
  102.     default:
  103.         break;
  104.     }
  105.     MultiTimerStart(timer, 10, RGBTimer1Callback, userData);
  106. }

        2. KEY驱动:
  1. #include "KEY.h"
  2. #include "main.h"
  3. void KEY_Init(void)
  4. {
  5.     GPIO_Config_T GPIO_ConfigStruct;
  6.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
  7.     GPIO_ConfigStruct.pin = GPIO_PIN_0|GPIO_PIN_1;                          //PB0--TMR3_CH3
  8.     GPIO_ConfigStruct.mode = GPIO_MODE_IN_PU;
  9.     GPIO_Config(GPIOA, &GPIO_ConfigStruct);
  10. }
  11. u8 KEY_Handler(void)
  12. {
  13.           static u8 key1bounce=0,key2bounce=0;
  14.           u8 key=0;
  15.                 if(GPIO_ReadInputBit(GPIOA,GPIO_PIN_0)==BIT_RESET)
  16.                 {
  17.                         key1bounce=1;
  18.                 }else{
  19.                         if(key1bounce)
  20.                         {
  21.                                 key|=0x01;
  22.                         }
  23.                         key1bounce=0;
  24.                         
  25.                 }
  26.                 if(GPIO_ReadInputBit(GPIOA,GPIO_PIN_1)==BIT_RESET)
  27.                 {
  28.                         key2bounce=1;
  29.                 }else{
  30.                         if(key2bounce)
  31.                         {
  32.                                 key|=0x02;
  33.                         }
  34.                         key2bounce=0;
  35.                         
  36.                 }        
  37.                 return key;
  38. }
         3. RGB驱动:
  1. /*!
  2. * [url=home.php?mod=space&uid=288409]@file[/url]        RGB.c
  3. *
  4. * [url=home.php?mod=space&uid=247401]@brief[/url]       This file provides firmware functions to manage Leds and push-buttons
  5. *
  6. * [url=home.php?mod=space&uid=895143]@version[/url]     V1.0.0
  7. *
  8. * [url=home.php?mod=space&uid=212281]@date[/url]        2021-07-26
  9. *
  10. */

  11. #include "RGB.h"
  12. #include "main.h"

  13. //RGB
  14. RGB_LED_EFFECT RGB_Eff=DYN_RGB;

  15. void RGB_Init(void)
  16. {
  17.     GPIO_Config_T GPIO_ConfigStruct;
  18.     TMR_BaseConfig_T TMR_TimeBaseStruct;
  19.     TMR_OCConfig_T OCcongigStruct;

  20.     RCM_EnableAPB2PeriphClock((RCM_APB2_PERIPH_T)(RCM_APB2_PERIPH_GPIOA | RCM_APB2_PERIPH_GPIOB));
  21.     RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3);

  22.     GPIO_ConfigStruct.pin = GPIO_PIN_6|GPIO_PIN_7;//PA6--TMR3_CH1
  23.     GPIO_ConfigStruct.mode = GPIO_MODE_AF_PP;          //PA7--TMR3_CH2
  24.     GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
  25.     GPIO_Config(GPIOA, &GPIO_ConfigStruct);

  26.     GPIO_ConfigStruct.pin = GPIO_PIN_0;                          //PB0--TMR3_CH3
  27.     GPIO_ConfigStruct.mode = GPIO_MODE_AF_PP;
  28.     GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
  29.     GPIO_Config(GPIOB, &GPIO_ConfigStruct);

  30.     TMR_TimeBaseStruct.clockDivision = TMR_CLOCK_DIV_1;
  31.     TMR_TimeBaseStruct.countMode = TMR_COUNTER_MODE_UP;
  32.     TMR_TimeBaseStruct.division = 71;
  33.     TMR_TimeBaseStruct.period = 255;
  34.     TMR_ConfigTimeBase(TMR3, &TMR_TimeBaseStruct);

  35.     OCcongigStruct.idleState = TMR_OC_IDLE_STATE_RESET;
  36.     OCcongigStruct.mode = TMR_OC_MODE_PWM1;
  37.     OCcongigStruct.nIdleState = TMR_OC_NIDLE_STATE_RESET;
  38.     OCcongigStruct.nPolarity = TMR_OC_NPOLARITY_HIGH;
  39.     OCcongigStruct.outputNState = TMR_OC_NSTATE_ENABLE;
  40.     OCcongigStruct.outputState = TMR_OC_STATE_ENABLE;
  41.     OCcongigStruct.polarity = TMR_OC_POLARITY_HIGH;
  42.     OCcongigStruct.pulse = 0;
  43.     TMR_ConfigOC1(TMR3, &OCcongigStruct);
  44.     TMR_ConfigOC2(TMR3, &OCcongigStruct);
  45.     TMR_ConfigOC3(TMR3, &OCcongigStruct);

  46.     TMR_ConfigOC1Preload(TMR3, TMR_OC_PRELOAD_ENABLE);
  47.     TMR_ConfigOC2Preload(TMR3, TMR_OC_PRELOAD_ENABLE);
  48.     TMR_ConfigOC3Preload(TMR3, TMR_OC_PRELOAD_ENABLE);
  49.     TMR_EnableAUTOReload(TMR3);
  50.     TMR_Enable(TMR3);
  51.     TMR_EnablePWMOutputs(TMR3);
  52. }
  53. void SetRGB_PWM(u16 R,u16 G,u16 B)
  54. {
  55.     TMR3->CC1=R;
  56.     TMR3->CC2=G;
  57.     TMR3->CC3=B;
  58. }
  59. const u8 R[8]= {255,191,127,0,0,0,150,255};
  60. const u8 G[8]= {0,69,127,255,127,0,2,0};
  61. const u8 B[8]= {0,0,0,0,127,255,134,0};
  62. unsigned char abs0(int num)
  63. {
  64.     if(num>0) return num;
  65.     num = -num;
  66.     return (unsigned char) num;
  67. }
  68. u8 ColorToColor(u8 r0,u8 g0,u8 b0, u8 r1,u8 g1,u8 b1,float* RedStep,float* GreenStep,float* BlueStep)
  69. {
  70.     unsigned char Red0, Green0, Blue0;  // 起始三原色
  71.     unsigned char Red1, Green1, Blue1;  // 结果三原色
  72.     int                          RedMinus, GreenMinus, BlueMinus;        // 颜色差(color1 - color0)
  73.     u8 NStep;
  74.     //unsigned long color;                                                        // 结果色
  75.     // 绿 红 蓝 三原色分解
  76.     Red0   = r0;
  77.     Green0 = g0;
  78.     Blue0  = b0;
  79.     Red1   = r1;
  80.     Green1 = g1;
  81.     Blue1  = b1;
  82.     // 计算需要多少步(取差值的最大值)
  83.     RedMinus   = Red1 - Red0;
  84.     GreenMinus = Green1 - Green0;
  85.     BlueMinus  = Blue1 - Blue0;

  86.     NStep = ( abs0(RedMinus) > abs0(GreenMinus) ) ? abs0(RedMinus):abs0(GreenMinus);
  87.     NStep = ( NStep > abs0(BlueMinus) ) ? NStep:abs0(BlueMinus);

  88.     // 计算出各色步进值
  89.     RedStep[0]   = (float)RedMinus   / NStep;
  90.     GreenStep[0] = (float)GreenMinus / NStep;
  91.     BlueStep[0]  = (float)BlueMinus  / NStep;

  92.     // 渐变开始
  93. //        for(i=0; i<NStep; i++)
  94. //        {
  95. //                Red1   = Red0   + (int)(RedStep   * i);
  96. //                Green1 = Green0 + (int)(GreenStep * i);
  97. //                Blue1  = Blue0  + (int)(BlueStep  * i);
  98. //
  99. //                //color  = Green1<<16 | Red1<<8 | Blue1;         // 合成  绿红蓝
  100. //                SetPWM_for_RGB(Red1,Green1,Blue1);
  101. //
  102. //                DelayMs(1);                                                // 渐变速度
  103. //        }
  104.     // 渐变结束

  105.     return NStep;
  106. }

  107. void GradientDreamSingleColor(RGB_LED_EFFECT type)
  108. {
  109.     unsigned char Red, Green, Blue;  // 结果三原色
  110.     static  u8  first=0,tick=0,cStep=0,tp=1,rgb=0;
  111.     static float RedStep, GreenStep, BlueStep;
  112.     static RGB_LED_EFFECT typelast=DYN_RED;
  113.     if(typelast!=type)
  114.     {
  115.         SetRGB_PWM(0,0,0);
  116.     }
  117.     typelast=type;

  118.     if(first==0)
  119.     {
  120.         first=1;
  121.         switch(type)
  122.         {
  123.         case DYN_RED:
  124.         {
  125.             rgb=0;
  126.             if(tp==0)
  127.             {
  128.                 tp=1;
  129.                 cStep=ColorToColor(R[rgb],G[rgb],B[rgb],0,0,0,&RedStep,&GreenStep,&BlueStep);
  130.             } else {
  131.                 tp=0;
  132.                 cStep=ColorToColor(0,0,0,R[rgb],G[rgb],B[rgb],&RedStep,&GreenStep,&BlueStep);
  133.             }
  134.         }
  135.         break;
  136.         case DYN_ORANGE:
  137.         {
  138.             rgb=1;
  139.             if(tp==0)
  140.             {
  141.                 tp=1;
  142.                 cStep=ColorToColor(R[rgb],G[rgb],B[rgb],0,0,0,&RedStep,&GreenStep,&BlueStep);
  143.             } else {
  144.                 tp=0;
  145.                 cStep=ColorToColor(0,0,0,R[rgb],G[rgb],B[rgb],&RedStep,&GreenStep,&BlueStep);
  146.             }
  147.         }
  148.         break;
  149.         case DYN_YELLOW:
  150.         {
  151.             rgb=2;
  152.             if(tp==0)
  153.             {
  154.                 tp=1;
  155.                 cStep=ColorToColor(R[rgb],G[rgb],B[rgb],0,0,0,&RedStep,&GreenStep,&BlueStep);
  156.             } else {
  157.                 tp=0;
  158.                 cStep=ColorToColor(0,0,0,R[rgb],G[rgb],B[rgb],&RedStep,&GreenStep,&BlueStep);
  159.             }
  160.         }
  161.         break;
  162.         case DYN_GREE:
  163.         {
  164.             rgb=3;
  165.             if(tp==0)
  166.             {
  167.                 tp=1;
  168.                 cStep=ColorToColor(R[rgb],G[rgb],B[rgb],0,0,0,&RedStep,&GreenStep,&BlueStep);
  169.             } else {
  170.                 tp=0;
  171.                 cStep=ColorToColor(0,0,0,R[rgb],G[rgb],B[rgb],&RedStep,&GreenStep,&BlueStep);
  172.             }
  173.         }
  174.         break;
  175.         case DYN_CYAN:
  176.         {
  177.             rgb=4;
  178.             if(tp==0)
  179.             {
  180.                 tp=1;
  181.                 cStep=ColorToColor(R[rgb],G[rgb],B[rgb],0,0,0,&RedStep,&GreenStep,&BlueStep);
  182.             } else {
  183.                 tp=0;
  184.                 cStep=ColorToColor(0,0,0,R[rgb],G[rgb],B[rgb],&RedStep,&GreenStep,&BlueStep);
  185.             }
  186.         }
  187.         break;
  188.         case DYN_BLUE:
  189.         {
  190.             rgb=5;
  191.             if(tp==0)
  192.             {
  193.                 tp=1;
  194.                 cStep=ColorToColor(R[rgb],G[rgb],B[rgb],0,0,0,&RedStep,&GreenStep,&BlueStep);
  195.             } else {
  196.                 tp=0;
  197.                 cStep=ColorToColor(0,0,0,R[rgb],G[rgb],B[rgb],&RedStep,&GreenStep,&BlueStep);
  198.             }
  199.         }
  200.         break;
  201.         case DYN_PURPLE:
  202.         {
  203.             rgb=6;
  204.             if(tp==0)
  205.             {
  206.                 tp=1;
  207.                 cStep=ColorToColor(R[rgb],G[rgb],B[rgb],0,0,0,&RedStep,&GreenStep,&BlueStep);
  208.             } else {
  209.                 tp=0;
  210.                 cStep=ColorToColor(0,0,0,R[rgb],G[rgb],B[rgb],&RedStep,&GreenStep,&BlueStep);
  211.             }
  212.         }
  213.         break;
  214.         default:
  215.             break;


  216.         }

  217.     } else {

  218.         if(tick<cStep)
  219.         {
  220.             if(tp==0)
  221.             {
  222.                 Red   =0+ (int)(RedStep   * tick);
  223.                 Green = 0+ (int)(GreenStep * tick);
  224.                 Blue  =  0+(int)(BlueStep  *tick);
  225.             } else {
  226.                 Red   =R[rgb]   + (int)(RedStep   * tick);
  227.                 Green = G[rgb]   + (int)(GreenStep * tick);
  228.                 Blue  = B[rgb]   + (int)(BlueStep  *tick);
  229.             }

  230.             SetRGB_PWM(Red,Green,Blue);

  231.         } else {
  232.             tick=0;
  233.             first=0;
  234.         }
  235.         tick++;

  236.     }
  237. }


  238. void GradientDreamColor(void)
  239. {
  240.     unsigned char Red, Green, Blue;  // 结果三原色
  241.     static  u8  first=0,i=0,tick=0,cStep=0;
  242.     static float RedStep, GreenStep, BlueStep;

  243.     static  u16  delaytick=0;
  244.     if(delaytick++>5)
  245.     {
  246.         delaytick=0;
  247.         if(first==0)
  248.         {
  249.             first=1;
  250.             cStep=ColorToColor(R[i],G[i],B[i],R[i+1],G[i+1],B[i+1],&RedStep,&GreenStep,&BlueStep);
  251.         } else {

  252.             if(tick<cStep)
  253.             {
  254.                 Red   =R[i]   + (int)(RedStep   * tick);
  255.                 Green = G[i]   + (int)(GreenStep * tick);
  256.                 Blue  = B[i]   + (int)(BlueStep  *tick);
  257.                 SetRGB_PWM(Red,Green,Blue);

  258.             } else {
  259.                 tick=0;
  260.                 if(++i>=7)
  261.                 {
  262.                     i=0;

  263.                 }
  264.                 first=0;
  265.             }
  266.             tick++;
  267.         }
  268.     }
  269. }



最后实验可以看我们的视频:
https://www.bilibili.com/video/BV1ZT411A77M/?vd_source=2bbde87de845d5220b1d8ba075c12fb0

并附上代码

APM32E10x_SDK_V1.0.zip

1.62 MB, 下载次数: 13

lajfda001 发表于 2022-8-16 10:17 | 显示全部楼层
代码整洁,没有任何的瑕疵,感谢楼主的分享。
单片小菜 发表于 2022-8-16 10:51 | 显示全部楼层
你用的是最小系统板吗?还是别的?
jflahdink09 发表于 2022-8-16 11:17 | 显示全部楼层
可以传一下视频吗?看看视频的效果如何
 楼主| lilijin1995 发表于 2022-8-16 13:58 | 显示全部楼层
jflahdink09 发表于 2022-8-16 11:17
可以传一下视频吗?看看视频的效果如何

https://www.bilibili.com/video/BV1ZT411A77M/?vd_source=2bbde87de845d5220b1d8ba075c12fb0
 楼主| lilijin1995 发表于 2022-8-16 13:59 | 显示全部楼层
单片小菜 发表于 2022-8-16 10:51
你用的是最小系统板吗?还是别的?

二姨家发的APM32E103xE Mini板
单片小菜 发表于 2022-8-16 16:20 | 显示全部楼层
lilijin1995 发表于 2022-8-16 13:59
二姨家发的APM32E103xE Mini板

厉害的,不错,不错的!
juliestephen 发表于 2022-8-16 19:53 | 显示全部楼层
这个如何调整占空比呢?  
 楼主| lilijin1995 发表于 2022-8-17 10:08 | 显示全部楼层
juliestephen 发表于 2022-8-16 19:53
这个如何调整占空比呢?
  1. void SetRGB_PWM(u16 R,u16 G,u16 B)
  2. {
  3.     TMR3->CC1=R;
  4.     TMR3->CC2=G;
  5.     TMR3->CC3=B;
  6. }



设置比较值就可以
wengh2016 发表于 2022-8-18 17:23 | 显示全部楼层
使用pwm吗   
duo点 发表于 2022-8-18 17:30 来自手机 | 显示全部楼层
厉害了,不错不错
duo点 发表于 2022-8-18 17:30 来自手机 | 显示全部楼层
支持一下
uiint 发表于 2022-8-18 17:58 | 显示全部楼层
APM32E103性能怎么样  
 楼主| lilijin1995 发表于 2022-9-7 09:23 | 显示全部楼层
uiint 发表于 2022-8-18 17:58
APM32E103性能怎么样

强大,很强
lzbf 发表于 2022-9-8 08:43 | 显示全部楼层
这个可以驱动ws8212吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

56

主题

165

帖子

8

粉丝
快速回复 在线客服 返回列表 返回顶部

56

主题

165

帖子

8

粉丝
快速回复 在线客服 返回列表 返回顶部