[APM32E0] 【APM32E030R Micro-EVB开发板评测】I2C读取FM24C02测试

[复制链接]
30|0
abner_ma 发表于 2025-8-29 15:53 | 显示全部楼层 |阅读模式
本帖最后由 abner_ma 于 2025-8-29 15:56 编辑

一、测评背景与目的
  在嵌入式系统开发中,IIC(Inter-Integrated Circuit)接口因结构简单、占用引脚少等优势,被广泛应用于传感器、存储芯片等外设的通信。APM32E030R8T6 是一款基于 ARM Cortex-M0 + 内核的微控制器,具备丰富的外设资源,其 PF6 和 PF7 引脚可配置为 IIC 接口功能。FM24C02 则是一款常见的 2KB IIC 接口 EEPROM 存储芯片,常用于数据的掉电保存。
  本次测评旨在验证 APM32E030R8T6 的 PF6、PF7 引脚作为 IIC 接口时,与 FM24C02 之间的通信功能是否正常,同时测试其读写性能、稳定性等关键指标,为后续嵌入式项目中该硬件组合的应用提供可靠依据。
硬件:
1.jpg

二、测评环境搭建(一)硬件环境
1. APM32E030R Micro-EVB开发板主控芯片:APM32E030R8T6 微控制器,工作电压 3.3V,主频最高 48MHz。
2. 存储芯片FM24C02是一款基于I²C总线接口的串行EEPROM芯片,容量为2Kbit,支持掉电后数据不丢失,非常适合用于存储关键配置信息、设备ID、校准数据等。它采用SOP8贴片封装,体积小巧,安装方便,适合各种空间受限的电路设计。它最大的亮点之一就是“非易失性存储”,也就是说,即使断电了,里面的数据也不会消失。这在很多需要长期保存参数的设备中非常关键,比如智能仪表、家电控制、工业设备等。而且它支持高频率的读写操作,稳定性强,寿命长,简直是“小身材,大能量”的代表!
3. 硬件连接
◦ APM32E030R8T6 的 PF6 引脚(IIC_SCL)与 FM24C02 的 SCL 引脚相连,PF7 引脚(IIC_SDA)与 FM24C02 的 SDA 引脚相连。
◦ 为保证 IIC 通信的稳定性,在 SCL 和 SDA 引脚上分别串联一个 4.7kΩ 的上拉电阻,将引脚电平拉至 3.3V。
◦ 连接 APM32E030R8T6 和 FM24C02 的 GND 引脚,确保两者共地;为 FM24C02 提供 3.3V 工作电压,与 APM32E030R8T6 的工作电压保持一致。
◦ 搭建调试环境,使用 板载DAP调试器连接 APM32E030R8T6 的调试接口(SWDIO 和 SWCLK),用于程序下载和调试;通过串口将 APM32E030R8T6 与电脑连接,用于输出测试数据和日志。
2.png


(二)软件环境
开发工具:使用 Keil MDK-ARM V5 开发环境,该工具支持 ARM Cortex-M 系列微控制器的程序开发、编译和调试,具备丰富的库函数和调试功能。
固件库:采用 APM32 官方提供的 APM32E030_SDK_V1.0.3库,该固件库包含了 IIC 外设的驱动函数、GPIO 引脚配置函数等,可简化程序开发流程,提高开发效率。
测试程序设计
引脚初始化:配置 PF6 和 PF7 引脚为复用功能模式,将其映射为 IIC 接口的 SCL 和 SDA 引脚;同时配置引脚的输出模式、上拉 / 下拉电阻等参数,确保引脚工作在正确的电气状态。
IIC 外设初始化:设置 IIC 的通信速率(分别测试 100kHz 标准模式和 400kHz 快速模式)、地址模式(7 位地址模式)、时钟占空比等参数;使能 IIC 外设,准备进行通信。
FM24C02 读写函数:编写 FM24C02 的字节写入函数、字节读取函数、页写入函数和页读取函数。其中,字节读写函数用于单个字节数据的写入和读取,页读写函数用于连续多个字节数据的批量写入和读取(FM24C02 的页容量为 8 字节)。
测试逻辑设计:在主函数中,先对 FM24C02 进行初始化;然后执行写入操作,向 FM24C02 的指定地址写入测试数据(包括单个字节数据和多字节页数据);等待写入完成后,执行读取操作,从相同地址读取数据;最后将写入数据和读取数据进行比较,判断读写操作是否成功,并通过串口输出测试结果(成功 / 失败、写入数据、读取数据、通信速率等信息)。
IIC.C
  1. #include "fm24c02_iic.h"
  2. #include "apm32e03x_gpio.h"
  3. #include "apm32e03x_i2c.h"
  4. #include "apm32e03x_rcc.h"

  5. // 定义IIC相关引脚和外设
  6. #define I2C_PORT         I2C1
  7. #define I2C_SCL_PORT     GPIOF
  8. #define I2C_SDA_PORT     GPIOF
  9. #define I2C_SCL_PIN      GPIO_PIN_6
  10. #define I2C_SDA_PIN      GPIO_PIN_7

  11. // FM24C02设备地址和容量
  12. #define FM24C02_ADDR     0xA0  // 7位地址为0x50,写入时为0xA0,读取时为0xA1
  13. #define FM24C02_PAGE_SIZE 8    // 页大小为8字节
  14. #define FM24C02_MAX_ADDR 0xFF  // 最大地址(256字节)

  15. /**
  16. * @brief  初始化IIC外设和相关GPIO引脚
  17. * @param  无
  18. * @retval 无
  19. */
  20. void IIC_Init(void)
  21. {
  22.     GPIO_Config_T gpioConfig;
  23.     I2C_Config_T i2cConfig;
  24.    
  25.     // 使能外设时钟
  26.     RCC_EnableAPB1PeriphClock(RCC_APB1_PERIPH_I2C1);
  27.     RCC_EnableAHBPeriphClock(RCC_AHB_PERIPH_GPIOF);
  28.    
  29.     // 配置SCL和SDA引脚为复用功能
  30.     gpioConfig.mode = GPIO_MODE_AF_OD;      // 开漏输出
  31.     gpioConfig.speed = GPIO_SPEED_50MHz;    // 高速
  32.     gpioConfig.pin = I2C_SCL_PIN | I2C_SDA_PIN;
  33.     GPIO_Config(I2C_SCL_PORT, &gpioConfig);
  34.    
  35.     // 配置I2C外设
  36.     i2cConfig.mode = I2C_MODE_I2C;                  // I2C模式
  37.     i2cConfig.dutyCycle = I2C_DUTYCYCLE_2;          // 占空比1:2
  38.     i2cConfig.ownAddr1 = 0x00;                      // 主机地址(不使用)
  39.     i2cConfig.addrMode = I2C_ADDR_MODE_7BIT;        // 7位地址模式
  40.     i2cConfig.speed = I2C_SPEED_STANDARD;           // 标准模式(100kHz)
  41.     //i2cConfig.speed = I2C_SPEED_FAST;             // 快速模式(400kHz)
  42.     i2cConfig.ackEn = I2C_ACK_ENABLE;               // 使能应答
  43.    
  44.     I2C_Config(I2C_PORT, &i2cConfig);
  45.     I2C_Enable(I2C_PORT);  // 使能I2C外设
  46. }

  47. /**
  48. * @brief  等待IIC操作完成
  49. * @param  timeOut: 超时时间
  50. * @retval 成功返回0,失败返回1
  51. */
  52. uint8_t IIC_WaitForOperation(uint32_t timeOut)
  53. {
  54.     while(timeOut--)
  55.     {
  56.         if(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_BUSY))
  57.             return 0;
  58.     }
  59.     return 1; // 超时
  60. }

  61. /**
  62. * @brief  向FM24C02写入一个字节
  63. * @param  addr: 写入地址(0x00~0xFF)
  64. * @param  data: 要写入的数据
  65. * @retval 成功返回0,失败返回1
  66. */
  67. uint8_t FM24C02_WriteByte(uint8_t addr, uint8_t data)
  68. {
  69.     // 等待总线空闲
  70.     if(IIC_WaitForOperation(0xFFFF))
  71.         return 1;
  72.    
  73.     // 发送起始信号
  74.     I2C_GenerateStart(I2C_PORT);
  75.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_SB));
  76.    
  77.     // 发送设备地址和写命令
  78.     I2C_TxData(I2C_PORT, FM24C02_ADDR);
  79.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_ADDR));
  80.     I2C_ClearAddrFlag(I2C_PORT);  // 清除地址标志
  81.    
  82.     // 发送内存地址
  83.     I2C_TxData(I2C_PORT, addr);
  84.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_TXE));
  85.    
  86.     // 发送数据
  87.     I2C_TxData(I2C_PORT, data);
  88.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_TXE));
  89.    
  90.     // 发送停止信号
  91.     I2C_GenerateStop(I2C_PORT);
  92.    
  93.     // 等待写入完成
  94.     for(uint32_t i = 0; i < 0xFFFF; i++);
  95.    
  96.     return 0;
  97. }

  98. /**
  99. * @brief  从FM24C02读取一个字节
  100. * @param  addr: 读取地址(0x00~0xFF)
  101. * @param  data: 存储读取数据的指针
  102. * @retval 成功返回0,失败返回1
  103. */
  104. uint8_t FM24C02_ReadByte(uint8_t addr, uint8_t *data)
  105. {
  106.     if(data == NULL)
  107.         return 1;
  108.    
  109.     // 等待总线空闲
  110.     if(IIC_WaitForOperation(0xFFFF))
  111.         return 1;
  112.    
  113.     // 发送起始信号
  114.     I2C_GenerateStart(I2C_PORT);
  115.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_SB));
  116.    
  117.     // 发送设备地址和写命令(用于设置读取地址)
  118.     I2C_TxData(I2C_PORT, FM24C02_ADDR);
  119.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_ADDR));
  120.     I2C_ClearAddrFlag(I2C_PORT);
  121.    
  122.     // 发送要读取的内存地址
  123.     I2C_TxData(I2C_PORT, addr);
  124.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_TXE));
  125.    
  126.     // 重新发送起始信号
  127.     I2C_GenerateStart(I2C_PORT);
  128.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_SB));
  129.    
  130.     // 发送设备地址和读命令
  131.     I2C_TxData(I2C_PORT, FM24C02_ADDR | 0x01);
  132.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_ADDR));
  133.     I2C_ClearAddrFlag(I2C_PORT);
  134.    
  135.     // 禁止应答,准备接收最后一个字节
  136.     I2C_DisableAck(I2C_PORT);
  137.    
  138.     // 读取数据
  139.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_RXNE));
  140.     *data = I2C_RxData(I2C_PORT);
  141.    
  142.     // 发送停止信号
  143.     I2C_GenerateStop(I2C_PORT);
  144.    
  145.     // 重新使能应答
  146.     I2C_EnableAck(I2C_PORT);
  147.    
  148.     return 0;
  149. }

  150. /**
  151. * @brief  向FM24C02写入一页数据(最多8字节)
  152. * @param  addr: 起始地址(0x00~0xFF)
  153. * @param  buf: 数据缓冲区
  154. * @param  len: 数据长度(1~8)
  155. * @retval 成功返回0,失败返回1
  156. */
  157. uint8_t FM24C02_WritePage(uint8_t addr, uint8_t *buf, uint8_t len)
  158. {
  159.     if(buf == NULL || len == 0 || len > FM24C02_PAGE_SIZE)
  160.         return 1;
  161.    
  162.     // 检查是否超出页边界
  163.     if(addr + len > ((addr & ~(FM24C02_PAGE_SIZE - 1)) + FM24C02_PAGE_SIZE))
  164.         return 1;
  165.    
  166.     // 等待总线空闲
  167.     if(IIC_WaitForOperation(0xFFFF))
  168.         return 1;
  169.    
  170.     // 发送起始信号
  171.     I2C_GenerateStart(I2C_PORT);
  172.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_SB));
  173.    
  174.     // 发送设备地址和写命令
  175.     I2C_TxData(I2C_PORT, FM24C02_ADDR);
  176.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_ADDR));
  177.     I2C_ClearAddrFlag(I2C_PORT);
  178.    
  179.     // 发送内存地址
  180.     I2C_TxData(I2C_PORT, addr);
  181.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_TXE));
  182.    
  183.     // 发送数据
  184.     for(uint8_t i = 0; i < len; i++)
  185.     {
  186.         I2C_TxData(I2C_PORT, buf[i]);
  187.         while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_TXE));
  188.     }
  189.    
  190.     // 发送停止信号
  191.     I2C_GenerateStop(I2C_PORT);
  192.    
  193.     // 等待写入完成
  194.     for(uint32_t i = 0; i < 0xFFFF; i++);
  195.    
  196.     return 0;
  197. }

  198. /**
  199. * @brief  从FM24C02连续读取多个字节
  200. * @param  addr: 起始地址(0x00~0xFF)
  201. * @param  buf: 存储读取数据的缓冲区
  202. * @param  len: 要读取的数据长度
  203. * @retval 成功返回0,失败返回1
  204. */
  205. uint8_t FM24C02_ReadBuffer(uint8_t addr, uint8_t *buf, uint16_t len)
  206. {
  207.     if(buf == NULL || len == 0 || addr + len > FM24C02_MAX_ADDR + 1)
  208.         return 1;
  209.    
  210.     // 等待总线空闲
  211.     if(IIC_WaitForOperation(0xFFFF))
  212.         return 1;
  213.    
  214.     // 发送起始信号
  215.     I2C_GenerateStart(I2C_PORT);
  216.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_SB));
  217.    
  218.     // 发送设备地址和写命令(用于设置读取地址)
  219.     I2C_TxData(I2C_PORT, FM24C02_ADDR);
  220.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_ADDR));
  221.     I2C_ClearAddrFlag(I2C_PORT);
  222.    
  223.     // 发送要读取的内存地址
  224.     I2C_TxData(I2C_PORT, addr);
  225.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_TXE));
  226.    
  227.     // 重新发送起始信号
  228.     I2C_GenerateStart(I2C_PORT);
  229.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_SB));
  230.    
  231.     // 发送设备地址和读命令
  232.     I2C_TxData(I2C_PORT, FM24C02_ADDR | 0x01);
  233.     while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_ADDR));
  234.     I2C_ClearAddrFlag(I2C_PORT);
  235.    
  236.     // 读取数据
  237.     for(uint16_t i = 0; i < len; i++)
  238.     {
  239.         // 最后一个字节前禁止应答
  240.         if(i == len - 1)
  241.             I2C_DisableAck(I2C_PORT);
  242.         
  243.         while(!I2C_ReadStatusFlag(I2C_PORT, I2C_FLAG_RXNE));
  244.         buf[i] = I2C_RxData(I2C_PORT);
  245.     }
  246.    
  247.     // 发送停止信号
  248.     I2C_GenerateStop(I2C_PORT);
  249.    
  250.     // 重新使能应答
  251.     I2C_EnableAck(I2C_PORT);
  252.    
  253.     return 0;
  254. }

  255. /**
  256. * @brief  向FM24C02写入多个字节(可跨页)
  257. * @param  addr: 起始地址(0x00~0xFF)
  258. * @param  buf: 数据缓冲区
  259. * @param  len: 数据长度
  260. * @retval 成功返回0,失败返回1
  261. */
  262. uint8_t FM24C02_WriteBuffer(uint8_t addr, uint8_t *buf, uint16_t len)
  263. {
  264.     uint8_t bytesToWrite;
  265.    
  266.     if(buf == NULL || len == 0 || addr + len > FM24C02_MAX_ADDR + 1)
  267.         return 1;
  268.    
  269.     while(len > 0)
  270.     {
  271.         // 计算当前页可写入的字节数
  272.         bytesToWrite = FM24C02_PAGE_SIZE - (addr % FM24C02_PAGE_SIZE);
  273.         if(bytesToWrite > len)
  274.             bytesToWrite = len;
  275.         
  276.         // 写入一页数据
  277.         if(FM24C02_WritePage(addr, buf, bytesToWrite) != 0)
  278.             return 1;
  279.         
  280.         // 更新地址、缓冲区指针和剩余长度
  281.         addr += bytesToWrite;
  282.         buf += bytesToWrite;
  283.         len -= bytesToWrite;
  284.     }
  285.    
  286.     return 0;
  287. }
main函数
  1. #include "apm32e03x.h"
  2. #include "fm24c02_iic.h"
  3. #include <stdio.h>

  4. // 测试函数声明
  5. void SystemInit(void);
  6. void UART_Init(void);
  7. int fputc(int ch, FILE *f);

  8. int main(void)
  9. {
  10.     uint8_t writeData = 0x5A;
  11.     uint8_t readData;
  12.     uint8_t pageData[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
  13.     uint8_t readBuffer[8];
  14.     uint8_t multiData[12] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B};
  15.     uint8_t readMulti[12];
  16.    
  17.     // 系统初始化
  18.     SystemInit();
  19.     UART_Init();  // 初始化串口用于输出调试信息
  20.     IIC_Init();   // 初始化IIC接口
  21.    
  22.     printf("FM24C02 IIC Communication Test Start\r\n");
  23.    
  24.     // 测试单个字节读写
  25.     if(FM24C02_WriteByte(0x00, writeData) == 0)
  26.     {
  27.         printf("Write byte 0x%02X to address 0x00 success\r\n", writeData);
  28.         
  29.         if(FM24C02_ReadByte(0x00, &readData) == 0)
  30.         {
  31.             printf("Read byte from address 0x00: 0x%02X\r\n", readData);
  32.             if(readData == writeData)
  33.                 printf("Single byte test: PASS\r\n");
  34.             else
  35.                 printf("Single byte test: FAIL\r\n");
  36.         }
  37.         else
  38.         {
  39.             printf("Read byte failed\r\n");
  40.         }
  41.     }
  42.     else
  43.     {
  44.         printf("Write byte failed\r\n");
  45.     }
  46.    
  47.     // 测试页写入和读取
  48.     if(FM24C02_WritePage(0x10, pageData, 8) == 0)
  49.     {
  50.         printf("Write page data to address 0x10 success\r\n");
  51.         
  52.         if(FM24C02_ReadBuffer(0x10, readBuffer, 8) == 0)
  53.         {
  54.             printf("Read page data: ");
  55.             for(uint8_t i = 0; i < 8; i++)
  56.             {
  57.                 printf("0x%02X ", readBuffer[i]);
  58.             }
  59.             printf("\r\n");
  60.             
  61.             // 验证数据
  62.             uint8_t pass = 1;
  63.             for(uint8_t i = 0; i < 8; i++)
  64.             {
  65.                 if(readBuffer[i] != pageData[i])
  66.                 {
  67.                     pass = 0;
  68.                     break;
  69.                 }
  70.             }
  71.             if(pass)
  72.                 printf("Page test: PASS\r\n");
  73.             else
  74.                 printf("Page test: FAIL\r\n");
  75.         }
  76.         else
  77.         {
  78.             printf("Read page data failed\r\n");
  79.         }
  80.     }
  81.     else
  82.     {
  83.         printf("Write page data failed\r\n");
  84.     }
  85.    
  86.     // 测试跨页写入和读取
  87.     if(FM24C02_WriteBuffer(0x1C, multiData, 12) == 0)
  88.     {
  89.         printf("Write multi-page data to address 0x1C success\r\n");
  90.         
  91.         if(FM24C02_ReadBuffer(0x1C, readMulti, 12) == 0)
  92.         {
  93.             printf("Read multi-page data: ");
  94.             for(uint8_t i = 0; i < 12; i++)
  95.             {
  96.                 printf("0x%02X ", readMulti[i]);
  97.             }
  98.             printf("\r\n");
  99.             
  100.             // 验证数据
  101.             uint8_t pass = 1;
  102.             for(uint8_t i = 0; i < 12; i++)
  103.             {
  104.                 if(readMulti[i] != multiData[i])
  105.                 {
  106.                     pass = 0;
  107.                     break;
  108.                 }
  109.             }
  110.             if(pass)
  111.                 printf("Multi-page test: PASS\r\n");
  112.             else
  113.                 printf("Multi-page test: FAIL\r\n");
  114.         }
  115.         else
  116.         {
  117.             printf("Read multi-page data failed\r\n");
  118.         }
  119.     }
  120.     else
  121.     {
  122.         printf("Write multi-page data failed\r\n");
  123.     }
  124.    
  125.     printf("FM24C02 IIC Communication Test Complete\r\n");
  126.    
  127.     while(1)
  128.     {
  129.         // 主循环
  130.     }
  131. }


三、功能测试(一)单个字节读写测试
  测试步骤
设定 FM24C02 的目标地址为 0x00(可选择任意有效地址,范围 0x00-0xFF)。
调用字节写入函数,向 0x00 地址写入一个字节的测试数据,例如 0x5A。
延时一段时间(FM24C02 的写入周期最大为 5ms,此处设置延时 10ms,确保写入操作完成)。
调用字节读取函数,从 0x00 地址读取数据。
比较写入数据(0x5A)和读取数据,若两者相等,则单个字节读写测试成功;否则失败。
重复上述测试过程 100 次,测试不同的目标地址(如 0x10、0x20、0x50、0xFF 等)和不同的测试数据(如 0x00、0xFF、0xAA、0x33 等),验证测试结果的一致性。
测试结果
  1. 在 100kHz 标准模式和 400kHz 快速模式下,经过 100 次不同地址和不同数据的测试,所有写入数据与读取数据均完全一致,单个字节读写功能正常,无数据错误或 通信失败的情况。
  2.串口输出日志显示,每次读写操作均能在预期时间内完成,无超时或异常报错。
(二)多字节页读写测试
  测试步骤
设定 FM24C02 的起始地址为 0x10(该地址需满足页对齐要求,即起始地址的低 3 位为 0,因 FM24C02 页容量为 8 字节,页地址范围为 0x00-0x07、0x08-0x0F、0x10-0x17 等)。
  准备一个 8 字节的测试数据数组,例如 {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}。
  写入函数,将该数据数组写入起始地址为 0x10 的页中。
  延时 10ms,等待页写入操作完成。
  调用页读取函数,从起始地址为 0x10 的页中读取 8 字节数据,存储到另一个数据数组中。
逐字节比较写入数据数组和读取数据数组,若所有字节均相等,则多字节页读写测试成功;否则失败。
  更换不同的起始页地址(如 0x20、0x30、0x70 等)和不同的测试数据数组(如全 0、全 1、递增数据、随机数据等),重复测试 100 次。
  测试结果
在两种通信速率下,100 次不同页地址和不同数据的测试均全部成功,写入的 8 字节数据与读取数据完全匹配,无数据丢失、错位或错误的情况。
即使在快速模式(400kHz)下,页读写操作依然稳定,未出现因通信速率过高导致的通信异常。

四、测评结论
   本次对 APM32E030R8T6 的 PF6、PF7 引脚读写 IIC 接口 FM24C02 的测评结果表明:APM32E030R8T6硬件IIC功能还是非常可靠的!


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

本版积分规则

认证:项目经理
简介:资深嵌入式开发工程师

97

主题

183

帖子

3

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