当前位置:   article > 正文

STM32——DAC篇(基于f103)_stm32 dac

stm32 dac

技术笔记!

一、DAC简介(了解)

1.1   DAC概念

        传感器信号采集改变电信号,通过ADC转换成单片机可以处理的数字信号,处理后,通过DAC转换成电信号,进而实现对系统的控制。

1.2  DAC的特性参数

1.3  STM32各系列DAC的主要特性

二、DAC工作原理(掌握)

2.1  DAC框图简介

2.2  参考电压/模拟部分电压

2.3  DAC数据格式

2.4  触发源

2.5  DMA请求

2.6  DAC输出电压

三、DAC输出实验(熟悉)

3.1  实验简要(了解)

3.2  DAC寄存器介绍(了解)

3.3  DAC输出实验配置步骤(掌握)

3.4  编程实战:DAC输出实验(掌握)

dac.c

  1. #include "./BSP/DAC/dac.h"
  2. DAC_HandleTypeDef g_dac_handle;
  3. /* DAC初始化函数 */
  4. void dac_init(void)
  5. {
  6. DAC_ChannelConfTypeDef dac_ch_conf;
  7. g_dac_handle.Instance = DAC;
  8. HAL_DAC_Init(&g_dac_handle); /* 初始化DAC */
  9. dac_ch_conf.DAC_Trigger = DAC_TRIGGER_NONE; /* 不使用触发功能 */
  10. dac_ch_conf.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; /* DAC输出缓冲关闭 */
  11. HAL_DAC_ConfigChannel(&g_dac_handle, &dac_ch_conf, DAC_CHANNEL_1); /* 配置DAC通道1 */
  12. HAL_DAC_Start(&g_dac_handle, DAC_CHANNEL_1); /* 开启DAC通道1 */
  13. }
  14. /* DAC MSP初始化函数 */
  15. void HAL_DAC_MspInit(DAC_HandleTypeDef *hdac)
  16. {
  17. if (hdac->Instance == DAC)
  18. {
  19. GPIO_InitTypeDef gpio_init_struct;
  20. __HAL_RCC_DAC_CLK_ENABLE();
  21. __HAL_RCC_GPIOA_CLK_ENABLE();
  22. gpio_init_struct.Pin = GPIO_PIN_4;
  23. gpio_init_struct.Mode = GPIO_MODE_ANALOG;
  24. HAL_GPIO_Init(GPIOA, &gpio_init_struct);
  25. }
  26. }
  27. /* 设置通道输出电压 */
  28. void dac_set_voltage(uint16_t vol)
  29. {
  30. double temp = vol;
  31. temp /= 1000;
  32. temp = temp * 4096 / 3.3;
  33. if (temp >= 4096)temp = 4095; /* 如果值大于等于4096, 则取4095 */
  34. HAL_DAC_SetValue(&g_dac_handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, temp); /* 12位右对齐数据格式设置DAC值 */
  35. }

main.c

  1. #include "./BSP/DAC/dac.h"
  2. DAC_HandleTypeDef g_dac_handle;
  3. /* DAC初始化函数 */
  4. void dac_init(void)
  5. {
  6. DAC_ChannelConfTypeDef dac_ch_conf;
  7. g_dac_handle.Instance = DAC;
  8. HAL_DAC_Init(&g_dac_handle); /* 初始化DAC */
  9. dac_ch_conf.DAC_Trigger = DAC_TRIGGER_NONE; /* 不使用触发功能 */
  10. dac_ch_conf.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; /* DAC输出缓冲关闭 */
  11. HAL_DAC_ConfigChannel(&g_dac_handle, &dac_ch_conf, DAC_CHANNEL_1); /* 配置DAC通道1 */
  12. HAL_DAC_Start(&g_dac_handle, DAC_CHANNEL_1); /* 开启DAC通道1 */
  13. }
  14. /* DAC MSP初始化函数 */
  15. void HAL_DAC_MspInit(DAC_HandleTypeDef *hdac)
  16. {
  17. if (hdac->Instance == DAC)
  18. {
  19. GPIO_InitTypeDef gpio_init_struct;
  20. __HAL_RCC_DAC_CLK_ENABLE();
  21. __HAL_RCC_GPIOA_CLK_ENABLE();
  22. gpio_init_struct.Pin = GPIO_PIN_4;
  23. gpio_init_struct.Mode = GPIO_MODE_ANALOG;
  24. HAL_GPIO_Init(GPIOA, &gpio_init_struct);
  25. }
  26. }
  27. /* 设置通道输出电压 */
  28. void dac_set_voltage(uint16_t vol)
  29. {
  30. double temp = vol;
  31. temp /= 1000;
  32. temp = temp * 4096 / 3.3;
  33. if (temp >= 4096)temp = 4095; /* 如果值大于等于4096, 则取4095 */
  34. HAL_DAC_SetValue(&g_dac_handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, temp); /* 12位右对齐数据格式设置DAC值 */
  35. }

四、DAC输出三角波实验(熟悉)

4.1  实验简要(了解)

4.2  编程实战:DAC输出三角波实验(掌握)

dac.c

  1. #include "./BSP/DAC/dac.h"
  2. #include "./SYSTEM/delay/delay.h"
  3. DAC_HandleTypeDef g_dac_handle;
  4. /* DAC初始化函数 */
  5. void dac_init(void)
  6. {
  7. DAC_ChannelConfTypeDef dac_ch_conf;
  8. g_dac_handle.Instance = DAC;
  9. HAL_DAC_Init(&g_dac_handle);
  10. dac_ch_conf.DAC_Trigger = DAC_TRIGGER_NONE;
  11. dac_ch_conf.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
  12. HAL_DAC_ConfigChannel(&g_dac_handle, &dac_ch_conf, DAC_CHANNEL_1);
  13. HAL_DAC_Start(&g_dac_handle, DAC_CHANNEL_1);
  14. }
  15. /* DAC MSP初始化函数 */
  16. void HAL_DAC_MspInit(DAC_HandleTypeDef *hdac)
  17. {
  18. if (hdac->Instance == DAC)
  19. {
  20. GPIO_InitTypeDef gpio_init_struct;
  21. __HAL_RCC_GPIOA_CLK_ENABLE();
  22. __HAL_RCC_DAC_CLK_ENABLE();
  23. gpio_init_struct.Pin = GPIO_PIN_4;
  24. gpio_init_struct.Mode = GPIO_MODE_ANALOG;
  25. HAL_GPIO_Init(GPIOA, &gpio_init_struct);
  26. }
  27. }
  28. /**
  29. * @brief 设置DAC_OUT1输出三角波
  30. * @note 输出频率 ≈ 1000 / (dt * samples) Khz, 不过在dt较小的时候,比如小于5us时, 由于delay_us
  31. * 本身就不准了(调用函数,计算等都需要时间,延时很小的时候,这些时间会影响到延时), 频率会偏小.
  32. *
  33. * @param maxval : 最大值(0 < maxval < 4096), (maxval + 1)必须大于等于samples/2
  34. * @param dt : 每个采样点的延时时间(单位: us)
  35. * @param samples: 采样点的个数, samples必须小于等于(maxval + 1) * 2 , 且maxval不能等于0
  36. * @param n : 输出波形个数,0~65535
  37. *
  38. * @retval 无
  39. */
  40. void dac_triangular_wave(uint16_t maxval, uint16_t dt, uint16_t samples, uint16_t n)
  41. {
  42. uint16_t i, j;
  43. float incval; /* 递增量 */
  44. float Curval; /* 当前值 */
  45. if(samples > ((maxval + 1) * 2))return ; /* 数据不合法 */
  46. incval = (maxval + 1) / (samples / 2); /* 计算递增量 */
  47. for(j = 0; j < n; j++)
  48. {
  49. Curval = 0;
  50. HAL_DAC_SetValue(&g_dac_handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, Curval); /* 先输出0 */
  51. for(i = 0; i < (samples / 2); i++) /* 输出上升沿 */
  52. {
  53. Curval += incval; /* 新的输出值 */
  54. HAL_DAC_SetValue(&g_dac_handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, Curval);
  55. delay_us(dt);
  56. }
  57. for(i = 0; i < (samples / 2); i++) /* 输出下降沿 */
  58. {
  59. Curval -= incval; /* 新的输出值 */
  60. HAL_DAC_SetValue(&g_dac_handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, Curval);
  61. delay_us(dt);
  62. }
  63. }
  64. }

main.c

  1. int main(void)
  2. {
  3. uint8_t t = 0;
  4. uint8_t key;
  5. HAL_Init(); /* 初始化HAL库 */
  6. sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
  7. delay_init(72); /* 延时初始化 */
  8. usart_init(115200); /* 串口初始化为115200 */
  9. led_init(); /* 初始化LED */
  10. lcd_init(); /* 初始化LCD */
  11. key_init(); /* 初始化按键 */
  12. dac_init(); /* 初始化DAC1_OUT1通道 */
  13. lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
  14. lcd_show_string(30, 70, 200, 16, 16, "DAC Triangular WAVE TEST", RED);
  15. lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
  16. lcd_show_string(30, 110, 200, 16, 16, "KEY0:Wave1 KEY1:Wave2", RED);
  17. lcd_show_string(30, 130, 200, 16, 16, "DAC None", BLUE); /* 提示无输出 */
  18. while (1)
  19. {
  20. t++;
  21. key = key_scan(0); /* 按键扫描 */
  22. if (key == KEY0_PRES) /* 高采样率 , 100hz波形 , 实际只有65.5hz */
  23. {
  24. lcd_show_string(30, 130, 200, 16, 16, "DAC Wave1 ", BLUE);
  25. dac_triangular_wave(4095, 5, 2000, 100); /* 幅值4095, 采样点间隔5us, 2000个采样点, 100个波形 */
  26. lcd_show_string(30, 130, 200, 16, 16, "DAC None ", BLUE);
  27. }
  28. else if (key == KEY1_PRES) /* 低采样率 , 100hz波形 , 实际99.5hz */
  29. {
  30. lcd_show_string(30, 130, 200, 16, 16, "DAC Wave2 ", BLUE);
  31. dac_triangular_wave(4095, 500, 20, 100); /* 幅值4095, 采样点间隔500us, 20个采样点, 100个波形 */
  32. lcd_show_string(30, 130, 200, 16, 16, "DAC None ", BLUE);
  33. }
  34. if (t == 10) /* 定时时间到了 */
  35. {
  36. LED0_TOGGLE(); /* LED0闪烁 */
  37. t = 0;
  38. }
  39. delay_ms(10);
  40. }
  41. }

五、DAC输出正弦波实验(熟悉)

5.1  实验简要(了解)

5.2  DAC输出正弦波实验配置步骤(掌握)

5.3  产生正弦波序列函数介绍(熟悉)

5.4  编程实战:DAC输出正弦波实验(掌握) 

dac.c

  1. #include "./BSP/DAC/dac.h"
  2. DMA_HandleTypeDef g_dma_dac_handle;
  3. DAC_HandleTypeDef g_dac_dma_handle;
  4. extern uint16_t g_dac_sin_buf[4096]; /* 发送数据缓冲区 */
  5. /* DAC DMA输出波形初始化函数 */
  6. void dac_dma_wave_init(void)
  7. {
  8. DAC_ChannelConfTypeDef dac_ch_conf;
  9. __HAL_RCC_DMA2_CLK_ENABLE();
  10. g_dma_dac_handle.Instance = DMA2_Channel3;
  11. g_dma_dac_handle.Init.Direction = DMA_MEMORY_TO_PERIPH;
  12. g_dma_dac_handle.Init.PeriphInc = DMA_PINC_DISABLE;
  13. g_dma_dac_handle.Init.MemInc = DMA_MINC_ENABLE;
  14. g_dma_dac_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  15. g_dma_dac_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  16. g_dma_dac_handle.Init.Mode = DMA_CIRCULAR;
  17. g_dma_dac_handle.Init.Priority = DMA_PRIORITY_MEDIUM;
  18. HAL_DMA_Init(&g_dma_dac_handle);
  19. __HAL_LINKDMA(&g_dac_dma_handle, DMA_Handle1, g_dma_dac_handle);
  20. g_dac_dma_handle.Instance = DAC;
  21. HAL_DAC_Init(&g_dac_dma_handle);
  22. dac_ch_conf.DAC_Trigger = DAC_TRIGGER_T7_TRGO;
  23. dac_ch_conf.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
  24. HAL_DAC_ConfigChannel(&g_dac_dma_handle, &dac_ch_conf, DAC_CHANNEL_1);
  25. HAL_DMA_Start(&g_dma_dac_handle, (uint32_t)g_dac_sin_buf, (uint32_t)&DAC1->DHR12R1, 0);
  26. }
  27. /* DAC MSP初始化函数 */
  28. void HAL_DAC_MspInit(DAC_HandleTypeDef *hdac)
  29. {
  30. if (hdac->Instance == DAC)
  31. {
  32. GPIO_InitTypeDef gpio_init_struct;
  33. __HAL_RCC_GPIOA_CLK_ENABLE();
  34. __HAL_RCC_DAC_CLK_ENABLE();
  35. gpio_init_struct.Pin = GPIO_PIN_4;
  36. gpio_init_struct.Mode = GPIO_MODE_ANALOG;
  37. HAL_GPIO_Init(GPIOA, &gpio_init_struct);
  38. }
  39. }
  40. /**
  41. * @brief DAC DMA使能波形输出
  42. * @note TIM7的输入时钟频率(f)来自APB1, f = 36M * 2 = 72Mhz.
  43. * DAC触发频率 ftrgo = f / ((psc + 1) * (arr + 1))
  44. * 波形频率 = ftrgo / ndtr;
  45. *
  46. * @param ndtr : DMA通道单次传输数据量
  47. * @param arr : TIM7的自动重装载值
  48. * @param psc : TIM7的分频系数
  49. * @retval 无
  50. */
  51. void dac_dma_wave_enable(uint16_t cndtr, uint16_t arr, uint16_t psc)
  52. {
  53. TIM_HandleTypeDef tim7_handle = {0};
  54. TIM_MasterConfigTypeDef tim_mater_config = {0};
  55. __HAL_RCC_TIM7_CLK_ENABLE();
  56. tim7_handle.Instance = TIM7;
  57. tim7_handle.Init.Prescaler = psc;
  58. tim7_handle.Init.Period = arr;
  59. HAL_TIM_Base_Init(&tim7_handle);
  60. tim_mater_config.MasterOutputTrigger = TIM_TRGO_UPDATE;
  61. tim_mater_config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  62. HAL_TIMEx_MasterConfigSynchronization(&tim7_handle, &tim_mater_config);
  63. HAL_TIM_Base_Start(&tim7_handle);
  64. HAL_DAC_Stop_DMA(&g_dac_dma_handle, DAC_CHANNEL_1);
  65. HAL_DAC_Start_DMA(&g_dac_dma_handle, DAC_CHANNEL_1, (uint32_t *)g_dac_sin_buf, cndtr, DAC_ALIGN_12B_R);
  66. }

main.c

  1. uint16_t g_dac_sin_buf[4096]; /* 发送数据缓冲区 */
  2. /**
  3. * @brief 产生正弦波序列函数
  4. * @note 需保证: maxval > samples/2
  5. * @param maxval : 最大值(0 < maxval < 2048)
  6. * @param samples: 采样点的个数
  7. * @retval 无
  8. */
  9. void dac_creat_sin_buf(uint16_t maxval, uint16_t samples)
  10. {
  11. uint8_t i;
  12. float outdata = 0; /* 存放计算后的数字量 */
  13. float inc = (2 * 3.1415962) / samples; /* 计算相邻两个点的x轴间隔 */
  14. if(maxval <= (samples / 2))return ; /* 数据不合法 */
  15. for (i = 0; i < samples; i++)
  16. {
  17. /*
  18. * 正弦波函数解析式:y = Asin(ωx + φ)+ b
  19. * 计算每个点的y值,将峰值放大maxval倍,并将曲线向上偏移maxval到正数区域
  20. * 注意:DAC无法输出负电压,所以需要将曲线向上偏移一个峰值的量,让整个曲线都落在正数区域
  21. */
  22. outdata = maxval * sin(inc * i) + maxval;
  23. if (outdata > 4095)
  24. outdata = 4095; /* 上限限定 */
  25. //printf("%f\r\n",outdata);
  26. g_dac_sin_buf[i] = outdata;
  27. }
  28. }
  29. int main(void)
  30. {
  31. uint8_t t = 0;
  32. uint8_t key;
  33. HAL_Init(); /* 初始化HAL库 */
  34. sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
  35. delay_init(72); /* 延时初始化 */
  36. usart_init(115200); /* 串口初始化为115200 */
  37. led_init(); /* 初始化LED */
  38. lcd_init(); /* 初始化LCD */
  39. key_init(); /* 初始化按键 */
  40. dac_dma_wave_init();
  41. lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
  42. lcd_show_string(30, 70, 200, 16, 16, "DAC DMA Sine WAVE TEST", RED);
  43. lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
  44. lcd_show_string(30, 110, 200, 16, 16, "KEY0:3Khz KEY1:30Khz", RED);
  45. dac_creat_sin_buf(2048, 100);
  46. dac_dma_wave_enable(100, 10 - 1, 72 - 1); /* 100Khz触发频率, 100个点, 得到1Khz的正弦波 */
  47. while (1)
  48. {
  49. t++;
  50. key = key_scan(0); /* 按键扫描 */
  51. if (key == KEY0_PRES) /* 高采样率 */
  52. {
  53. dac_creat_sin_buf(2048, 100);
  54. dac_dma_wave_enable(100, 10 - 1, 24 - 1); /* 300Khz触发频率, 100个点, 得到最高3KHz的正弦波. */
  55. }
  56. else if (key == KEY1_PRES) /* 低采样率 */
  57. {
  58. dac_creat_sin_buf(2048, 10);
  59. dac_dma_wave_enable(10, 10 - 1, 24 - 1); /* 300Khz触发频率, 10个点, 可以得到最高30KHz的正弦波. */
  60. }
  61. if (t == 40) /* 定时时间到了 */
  62. {
  63. LED0_TOGGLE(); /* LED0闪烁 */
  64. t = 0;
  65. }
  66. delay_ms(5);
  67. }
  68. }

六、PWM DAC实验(熟悉)

6.1, PWM DAC应用背景(了解)

6.2, PWM DAC技术实现原理(了解)
6.2.1,什么是PWM DAC技术?

6.2.2,用分段函数表示PWM波

6.2.3,将PWM波分段函数进行傅里叶级数展开

6.2.4,PWM DAC的分辨率

6.2.5,8位分辨率下对RC滤波器的设计要求

6.2.6,PWM DAC二阶低通滤波器原理图

6.3,编程实战: PWM DAC实验(掌握)

pwmdac.c

  1. #include "./BSP/PWMDAC/pwmdac.h"
  2. TIM_HandleTypeDef g_timx_pwm_chy_handle;
  3. /* PWM DAC初始化 */
  4. void pwmdac_init(uint16_t arr, uint16_t psc)
  5. {
  6. TIM_OC_InitTypeDef timx_oc_pwm_chy = {0};
  7. g_timx_pwm_chy_handle.Instance = TIM1;
  8. g_timx_pwm_chy_handle.Init.Prescaler = psc;
  9. g_timx_pwm_chy_handle.Init.Period = arr;
  10. g_timx_pwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
  11. g_timx_pwm_chy_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  12. HAL_TIM_PWM_Init(&g_timx_pwm_chy_handle);
  13. timx_oc_pwm_chy.OCMode = TIM_OCMODE_PWM1;
  14. timx_oc_pwm_chy.Pulse = 0;
  15. timx_oc_pwm_chy.OCPolarity = TIM_OCPOLARITY_HIGH;
  16. HAL_TIM_PWM_ConfigChannel(&g_timx_pwm_chy_handle, &timx_oc_pwm_chy, TIM_CHANNEL_1);
  17. HAL_TIM_PWM_Start(&g_timx_pwm_chy_handle, TIM_CHANNEL_1);
  18. }
  19. /* TIM MSP初始化函数 */
  20. void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
  21. {
  22. if(htim->Instance == TIM1)
  23. {
  24. GPIO_InitTypeDef gpio_init_struct;
  25. __HAL_RCC_GPIOA_CLK_ENABLE();
  26. __HAL_RCC_TIM1_CLK_ENABLE();
  27. gpio_init_struct.Pin = GPIO_PIN_8;
  28. gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 推挽复用 */
  29. gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
  30. gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
  31. HAL_GPIO_Init(GPIOA, &gpio_init_struct);
  32. }
  33. }
  34. /* 设置PWM DAC输出电压 */
  35. void pwmdac_set_voltage(uint16_t vol)
  36. {
  37. float temp = vol;
  38. temp /= 1000;
  39. temp = temp * 256 / 3.3;
  40. __HAL_TIM_SET_COMPARE(&g_timx_pwm_chy_handle, TIM_CHANNEL_1, temp);
  41. }

main.c

  1. int main(void)
  2. {
  3. uint16_t adcx;
  4. float temp;
  5. HAL_Init(); /* 初始化HAL库 */
  6. sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
  7. delay_init(72); /* 延时初始化 */
  8. usart_init(115200); /* 串口初始化为115200 */
  9. led_init(); /* 初始化LED */
  10. lcd_init(); /* 初始化LCD */
  11. adc_init(); /* 初始化ADC */
  12. pwmdac_init(256 - 1, 0);
  13. pwmdac_set_voltage(2800);
  14. lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
  15. lcd_show_string(30, 70, 200, 16, 16, "ADC TEST", RED);
  16. lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
  17. lcd_show_string(30, 110, 200, 16, 16, "ADC1_CH1_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */
  18. while (1)
  19. {
  20. adcx = adc_get_result();
  21. temp = (float)adcx * (3.3 / 4096); /* 获取计算后的带小数的实际电压值,比如3.1111 */
  22. adcx = temp; /* 赋值整数部分给adcx变量,因为adcx为u16整形 */
  23. lcd_show_xnum(134, 110, adcx, 1, 16, 0, BLUE); /* 显示电压值的整数部分,3.1111的话,这里就是显示3 */
  24. temp -= adcx; /* 把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111 */
  25. temp *= 1000; /* 小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。 */
  26. lcd_show_xnum(150, 110, temp, 3, 16, 0X80, BLUE);/* 显示小数部分(前面转换为了整形显示),这里显示的就是111. */
  27. LED0_TOGGLE();
  28. delay_ms(100);
  29. }
  30. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/974951
推荐阅读
相关标签
  

闽ICP备14008679号