超级精简系列之十:超级精简的IO模拟SPI的C实现应用值读写FLASH状态寄存器

原创 嵌入式Lee 2024-01-06 08:00

一. 应用 SPIFLASH状态寄存器的读写

以上实现了IO模拟SPI接口,整个过程很自然,参考时序图操作IO即可。是骡子是马拉出来遛遛。那么我们就继续基于此来进行SPIFALSH的操作,以W25Q32FV为例,先实现状态寄存器的读写,然后再实现FLASH的读写实现FLASH编辑器的工具。

W25Q32FV手册参考《https://www.winbond.com/hq/product/code-storage-flash-memory/serial-nor-flash/?__locale=en&partNo=W25Q32FV

4.1 W25Q32FV的状态寄存器

我们先从手册找到对应的指令表

3个状态寄存器分别都有对应的读写指令。

 

在实现时我们可以对应的数组通过索引来匹配命令

#define CMD_RD_SR1 0x05
#define CMD_WR_SR1 0x01
#define CMD_RD_SR2 0x35
#define CMD_WR_SR2 0x31
#define CMD_RD_SR3 0x15
#define CMD_WR_SR3 0x11
#define CMD_WR_EN 0x06
#define CMD_WR_DIS 0x04
const uint8_t s_cmd_rd_sr[3]={CMD_RD_SR1,CMD_RD_SR2,CMD_RD_SR3};
const uint8_t s_cmd_wr_sr[3]={CMD_WR_SR1,CMD_WR_SR2,CMD_WR_SR3};

然后查看具体命令的时序图

我们看到读寄存器很简单,拉低CS发送指令字节,下一个字节就是返回的寄存器值。持续给SCK和保持CS低则重复输出寄存器值。

 

写寄存器,也很简单,拉低CS先发命令字节,然后发数据字节,拉高CS即可。

 

 

然后我们再来看状态寄存器值的含义

状态寄存器0,6位对应保护位,WEL是写使能状态,BUSY是是否正在操作忙状态,这两位比较重要。一般操作完要检查BUSY是否为0才能继续,写之前要判断WEL是否为1可写。

该寄存器值默认值为0.

 

状态寄存器2

该寄存器默认值也是0,具体含义参考手册。

 

状态寄存器3,该寄存器默认值0x60.

DRV1DRV0都是1

 

 

4.2 W25Q32FV的状态寄存器的读写驱动

以上从手册了解状态寄存器的足够多的信息,于是就可以开始写代码了。

我们还是面向对象,考虑可移植性。

W25Q32FV.h

先抽象对SPI接口的依赖,设计设备类结构体

typedef void    (*w25qxx_spi_enable_pf)(void);                                       /**< SPI接口使能 */
typedef void (*w25qxx_spi_disable_pf)(void); /**< SPI接口禁能 */
typedef int (*w25qxx_spi_trans_pf)(uint8_t* tx, uint8_t* rx, uint32_t size); /**< SPI读写接口 */
typedef void (*w25qxx_spi_init_pf)(void); /**< 初始化接口 */
typedef void (*w25qxx_spi_deinit_pf)(void); /**< 解除初始化接口 */
/**
* \struct w25qxx_dev_st
* 接口结构体
*/
typedef struct
{
w25qxx_spi_enable_pf enable; /**< SPI接口使能 */
w25qxx_spi_disable_pf disbale; /**< SPI接口禁能 */
w25qxx_spi_trans_pf trans; /**< SPI读写接口 */
w25qxx_spi_init_pf init; /**< 初始化接口 */
w25qxx_spi_deinit_pf deinit; /**< 解除初始化接口 */
uint8_t* buffer; /**< 缓存地址 */
} w25qxx_dev_st;

然后确认接口

/**
* \fn w25qxx_init
* 初始化
* \param[in] dev \ref w25qxx_dev_st
*/
void w25qxx_init(w25qxx_dev_st* dev);
/**
* \fn w25qxx_deinit
* 解除初始化
* \param[in] dev \ref w25qxx_dev_st
*/
void w25qxx_deinit(w25qxx_dev_st* dev);
/**
* \fn w25qxx_rd_sr
* 读状态寄存器
* \param[in] dev \ref w25qxx_dev_st
* \param[in] sr 状态寄存器序号0~2
* \param[out] val 存储读到的值
* \return 参考w25qxx_spi_trans_pf的返回值
*/
int w25qxx_rd_sr(w25qxx_dev_st* dev, uint8_t sr, uint8_t* val);
/**
* \fn w25qxx_wr_sr
* 写状态寄存器
* \param[in] dev \ref w25qxx_dev_st
* \param[in] sr 状态寄存器序号0~2
* \param[in] val 待写入的值
* \return 参考w25qxx_spi_trans_pf的返回值
*/
int w25qxx_wr_sr(w25qxx_dev_st* dev, uint8_t sr, uint8_t val);
/**
* \fn w25qxx_wr_enable
* 写使能
* \param[in] dev \ref w25qxx_dev_st
* \return 参考w25qxx_spi_trans_pf的返回值
*/
int w25qxx_wr_enable(w25qxx_dev_st* dev);
/**
* \fn w25qxx_wr_disable
* 写禁止
* \param[in] dev \ref w25qxx_dev_st
* \return 参考w25qxx_spi_trans_pf的返回值
*/
int w25qxx_wr_disable(w25qxx_dev_st* dev);

最后就是实现接口,W25Q32FV.c

命令定义和初始化解除初始化实现

#define CMD_RD_SR1 0x05
#define CMD_WR_SR1 0x01
#define CMD_RD_SR2 0x35
#define CMD_WR_SR2 0x31
#define CMD_RD_SR3 0x15
#define CMD_WR_SR3 0x11
#define CMD_WR_EN 0x06
#define CMD_WR_DIS 0x04
const uint8_t s_cmd_rd_sr[3]={CMD_RD_SR1,CMD_RD_SR2,CMD_RD_SR3};
const uint8_t s_cmd_wr_sr[3]={CMD_WR_SR1,CMD_WR_SR2,CMD_WR_SR3};
void w25qxx_init(w25qxx_dev_st* dev){
dev->init();
}
/**
* \fn w25qxx_deinit
* 解除初始化
* \param[in] dev \ref w25qxx_dev_st
*/
void w25qxx_deinit(w25qxx_dev_st* dev){
dev->deinit();
}

读状态寄存器

/**
* \fn w25qxx_rd_sr
* 读状态寄存器
* \param[in] dev \ref w25qxx_dev_st
* \param[in] sr 状态寄存器序号0~2
* \param[out] val 存储读到的值
* \return 参考w25qxx_spi_trans_pf的返回值
*/
int w25qxx_rd_sr(w25qxx_dev_st* dev, uint8_t sr, uint8_t* val){
int res;
uint8_t tx[2];
uint8_t rx[2];
if((dev == 0) || (val == 0))
{
return -1;
}
if(sr >= sizeof(s_cmd_rd_sr)/sizeof(s_cmd_rd_sr[0]))
{
return -1;
}
tx[0]=s_cmd_rd_sr[sr];
tx[1]=0xFF;
dev->enable();
res = dev->trans(tx,rx,2);
dev->disbale();
*val = rx[1];
return res;
}

写状态寄存器

/**
* \fn w25qxx_wr_sr
* 写状态寄存器
* \param[in] dev \ref w25qxx_dev_st
* \param[in] sr 状态寄存器序号0~2
* \param[in] val 待写入的值
* \return 参考w25qxx_spi_trans_pf的返回值
*/
int w25qxx_wr_sr(w25qxx_dev_st* dev, uint8_t sr, uint8_t val){
int res;
uint8_t tx[2];
if((dev == 0) || (val == 0))
{
return -1;
}
if(sr >= sizeof(s_cmd_wr_sr)/sizeof(s_cmd_wr_sr[0]))
{
return -1;
}
tx[0]=s_cmd_wr_sr[sr];
tx[1]=val;
dev->enable();
res = dev->trans(tx,0,2);
dev->disbale();
return res;
}

写使能和禁止

int w25qxx_wr_enable(w25qxx_dev_st* dev){
int res;
uint8_t tx[1];
if(dev == 0)
{
return -1;
}
tx[0]=CMD_WR_EN;
dev->enable();
res = dev->trans(tx,0,1);
dev->disbale();
return res;
}
int w25qxx_wr_disable(w25qxx_dev_st* dev){
int res;
uint8_t tx[1];
if(dev == 0)
{
return -1;
}
tx[0]=CMD_WR_DIS;
dev->enable();
res = dev->trans(tx,0,1);
dev->disbale();
return res;
}

可以看到实现非常简单,具备高可移植性。

4.3 测试

我们还是基于之前的命令行实现,来添加命令进行测试

shell_func.c

申明实现函数,g_shell_cmd_list_ast中添加命令

static void wrsrfunc(uint8_t* param);
static void rdsrfunc(uint8_t* param);
static void wrenfunc(uint8_t* param);
static void wrdisfunc(uint8_t* param);
{ (uint8_t*)"wrsr", wrsrfunc, (uint8_t*)"wrsr sr val"},
{ (uint8_t*)"rdsr", rdsrfunc, (uint8_t*)"rdsr sr"},
{ (uint8_t*)"wren", wrenfunc, (uint8_t*)"wren"},
{ (uint8_t*)"wrdis", wrdisfunc, (uint8_t*)"wrdis"},

实现IO操作接口和设备实例

static void io_spi_port_init(void)
{
}
static void io_spi_port_deinit(void)
{
}
static void io_spi_port_cs_write(uint8_t val)
}
static void io_spi_port_sck_write(uint8_t val)
{
}
static void io_spi_port_mosi_write(uint8_t val)
{
}
static uint8_t io_spi_port_miso_read(void)
{
}
static void io_spi_port_delay(uint32_t delay)
{
}
static io_spi_dev_st io_spi_dev=
{
.cs_write = io_spi_port_cs_write,
.deinit = io_spi_port_deinit,
.delay_pf = io_spi_port_delay,
.delayns = 100,
.init = io_spi_port_init,
.miso_read = io_spi_port_miso_read,
.mode = 3,
.mosi_write = io_spi_port_mosi_write,
.msb = 1,
.sck_write = io_spi_port_sck_write,
};

实现flash依赖的接口和设备实例

static void w25qxx_port_enable(void){
io_spi_enable(&io_spi_dev);
}
static void w25qxx_port_disable(void){
io_spi_disable(&io_spi_dev);
}
static int w25qxx_port_trans(uint8_t* tx, uint8_t* rx, uint32_t size){
return io_spi_trans(&io_spi_dev, tx, rx, size);
}
static void w25qxx_port_init(void){
io_spi_init(&io_spi_dev);
}
static void w25qxx_port_deinit(void){
io_spi_deinit(&io_spi_dev);
}
static w25qxx_dev_st w25qxx_dev=
{
.deinit = w25qxx_port_deinit,
.disbale = w25qxx_port_disable,
.enable = w25qxx_port_enable,
.init = w25qxx_port_init,
.trans = w25qxx_port_trans,
};

实现写命令

void wrsrfunc(uint8_t* param){
uint32_t sr;
uint32_t val;
uint8_t* p = param;
while(1)
{
if((*p > 'z') || (*p < 'a'))
{
break;
}
else
{
p++;
}
}
while(1)
{
if(*p != ' ')
{
break;
}
else
{
p++;
}
}
sr = atoi((const char*)p);
while(1)
{
if((*p > '9') || (*p < '0'))
{
break;
}
else
{
p++;
}
}
while(1)
{
if(*p != ' ')
{
break;
}
else
{
p++;
}
}
val = atoi((const char*)p);
w25qxx_init(&w25qxx_dev);
w25qxx_wr_sr(&w25qxx_dev, sr, val);
w25qxx_deinit(&w25qxx_dev);
}

实现读命令

void rdsrfunc(uint8_t* param){
uint32_t sr;
uint8_t val=0;
uint8_t* p = param;
while(1)
{
if((*p > 'z') || (*p < 'a'))
{
break;
}
else
{
p++;
}
}
while(1)
{
if(*p != ' ')
{
break;
}
else
{
p++;
}
}
sr = atoi((const char*)p);
w25qxx_init(&w25qxx_dev);
w25qxx_rd_sr(&w25qxx_dev, sr, &val);
w25qxx_deinit(&w25qxx_dev);
printf("val = %d\r\n",val);
}

实现使能禁止命令

void wrenfunc(uint8_t* param){
(void)param;
w25qxx_init(&w25qxx_dev);
w25qxx_wr_enable(&w25qxx_dev);
w25qxx_deinit(&w25qxx_dev);
}
void wrdisfunc(uint8_t* param){
(void)param;
w25qxx_init(&w25qxx_dev);
w25qxx_wr_disable(&w25qxx_dev);
w25qxx_deinit(&w25qxx_dev);
}

进入命令行help查看添加的命令

 

模式3测试

写使能/禁能测试

先写使能读出寄存器0值为1bit1=1 WEL=1

然后写禁止读出寄存器0变为0.

sh>

wren

rdsr 0

val = 2

wrdis

rdsr 0

val = 0

波形如下

 

注意如果这里要将寄存器0改为0必须要

Wren使能,然后wrsr 0 22而不是写0

sh>

rdsr 0

val = 252

wrsr 0 2

rdsr 0

val = 252

wren

rdsr 0

val = 254    此时已经写使能但是wrsr 0 0不能写0

wrsr 0 0

rdsr 0

val = 254

wrsr 0 2    wrsr 0 22才能写0

rdsr

val = 0

写寄存器0

先要写使能

wren

然后写

wrsr 0 252

最后读

rdsr 0

sh>

wren

wrsr 0 252

rdsr 0

val = 252

可以看到回读值正确。

波形如下

 

读寄存器0

命令rdsr 0

sh>

rdsr 0

val = 0

逻辑分析仪抓到信号如下

 

读寄存器1

命令rdsr 1

sh>

rdsr 1

val = 0

逻辑分析仪抓到信号如下

 

读寄存器2

命令rdsr 2

sh>

rdsr 2

val = 96

逻辑分析仪抓到信号如下

 

模式0测试

io_spi_dev.mode改为0

写使能/禁能测试

先写使能读出寄存器0值为1bit1=1 WEL=1

然后写禁止读出寄存器0变为0.

sh>

wren

rdsr 0

val = 2

wrdis

rdsr 0

val = 0

波形如下

 

写寄存器0

先要写使能

wren

然后写

wrsr 0 252

最后读

rdsr 0

sh>

wren

wrsr 0 252

rdsr 0

val = 252

可以看到回读值正确。

波形如下

 

读寄存器0

命令rdsr 0

sh>

rdsr 0

val = 0

逻辑分析仪抓到信号如下

可见空闲时SCK是低,最后CS拉高后SCK为高是因为deinit了,io引脚被默认拉高了,cs之前空闲是低的。

 

读寄存器1

命令rdsr 1

sh>

rdsr 1

val = 0

逻辑分析仪抓到信号如下

读寄存器2

命令rdsr 2

sh>

rdsr 2

val = 96

逻辑分析仪抓到信号如下

评论
  • 物联网(IoT)的快速发展彻底改变了从智能家居到工业自动化等各个行业。由于物联网系统需要高效、可靠且紧凑的组件来处理众多传感器、执行器和通信设备,国产固态继电器(SSR)已成为满足中国这些需求的关键解决方案。本文探讨了国产SSR如何满足物联网应用的需求,重点介绍了它们的优势、技术能力以及在现实场景中的应用。了解物联网中的固态继电器固态继电器是一种电子开关设备,它使用半导体而不是机械触点来控制负载。与传统的机械继电器不同,固态继电器具有以下优势:快速切换:确保精确快速的响应,这对于实时物联网系统至
    克里雅半导体科技 2025-01-03 16:11 175浏览
  • 彼得·德鲁克被誉为“现代管理学之父”,他的管理思想影响了无数企业和管理者。然而,关于他的书籍分类,一种流行的说法令人感到困惑:德鲁克一生写了39本书,其中15本是关于管理的,而其中“专门写工商企业或为企业管理者写的”只有两本——《为成果而管理》和《创新与企业家精神》。这样的表述广为流传,但深入探讨后却发现并不完全准确。让我们一起重新审视这一说法,解析其中的矛盾与根源,进而重新认识德鲁克的管理思想及其著作的真正价值。从《创新与企业家精神》看德鲁克的视角《创新与企业家精神》通常被认为是一本专为企业管
    优思学院 2025-01-06 12:03 59浏览
  • 在测试XTS时会遇到修改产品属性、SElinux权限、等一些内容,修改源码再编译很费时。今天为大家介绍一个便捷的方法,让OpenHarmony通过挂载镜像来修改镜像内容!触觉智能Purple Pi OH鸿蒙开发板演示。搭载了瑞芯微RK3566四核处理器,树莓派卡片电脑设计,支持开源鸿蒙OpenHarmony3.2-5.0系统,适合鸿蒙开发入门学习。挂载镜像首先,将要修改内容的镜像传入虚拟机当中,并创建一个要挂载镜像的文件夹,如下图:之后通过挂载命令将system.img镜像挂载到sys
    Industio_触觉智能 2025-01-03 11:39 115浏览
  •     为控制片内设备并且查询其工作状态,MCU内部总是有一组特殊功能寄存器(SFR,Special Function Register)。    使用Eclipse环境调试MCU程序时,可以利用 Peripheral Registers Viewer来查看SFR。这个小工具是怎样知道某个型号的MCU有怎样的寄存器定义呢?它使用一种描述性的文本文件——SVD文件。这个文件存储在下面红色字体的路径下。    例:南京沁恒  &n
    电子知识打边炉 2025-01-04 20:04 56浏览
  • 本文介绍Linux系统更换开机logo方法教程,通用RK3566、RK3568、RK3588、RK3576等开发板,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。制作图片开机logo图片制作注意事项(1)图片必须为bmp格式;(2)图片大小不能大于4MB;(3)BMP位深最大是32,建议设置为8;(4)图片名称为logo.bmp和logo_kernel.bmp;开机
    Industio_触觉智能 2025-01-06 10:43 63浏览
  • 车身域是指负责管理和控制汽车车身相关功能的一个功能域,在汽车域控系统中起着至关重要的作用。它涵盖了车门、车窗、车灯、雨刮器等各种与车身相关的功能模块。与汽车电子电气架构升级相一致,车身域发展亦可以划分为三个阶段,功能集成愈加丰富:第一阶段为分布式架构:对应BCM车身控制模块,包含灯光、雨刮、门窗等传统车身控制功能。第二阶段为域集中架构:对应BDC/CEM域控制器,在BCM基础上集成网关、PEPS等。第三阶段为SOA理念下的中央集中架构:VIU/ZCU区域控制器,在BDC/CEM基础上集成VCU、
    北汇信息 2025-01-03 16:01 186浏览
  • 这篇内容主要讨论三个基本问题,硅电容是什么,为什么要使用硅电容,如何正确使用硅电容?1.  硅电容是什么首先我们需要了解电容是什么?物理学上电容的概念指的是给定电位差下自由电荷的储藏量,记为C,单位是F,指的是容纳电荷的能力,C=εS/d=ε0εrS/4πkd(真空)=Q/U。百度百科上电容器的概念指的是两个相互靠近的导体,中间夹一层不导电的绝缘介质。通过观察电容本身的定义公式中可以看到,在各个变量中比较能够改变的就是εr,S和d,也就是介质的介电常数,金属板有效相对面积以及距离。当前
    知白 2025-01-06 12:04 94浏览
  • 在快速发展的能源领域,发电厂是发电的支柱,效率和安全性至关重要。在这种背景下,国产数字隔离器已成为现代化和优化发电厂运营的重要组成部分。本文探讨了这些设备在提高性能方面的重要性,同时展示了中国在生产可靠且具有成本效益的数字隔离器方面的进步。什么是数字隔离器?数字隔离器充当屏障,在电气上将系统的不同部分隔离开来,同时允许无缝数据传输。在发电厂中,它们保护敏感的控制电路免受高压尖峰的影响,确保准确的信号处理,并在恶劣条件下保持系统完整性。中国国产数字隔离器经历了重大创新,在许多方面达到甚至超过了全球
    克里雅半导体科技 2025-01-03 16:10 122浏览
  • 自动化已成为现代制造业的基石,而驱动隔离器作为关键组件,在提升效率、精度和可靠性方面起到了不可或缺的作用。随着工业技术不断革新,驱动隔离器正助力自动化生产设备适应新兴趋势,并推动行业未来的发展。本文将探讨自动化的核心趋势及驱动隔离器在其中的重要角色。自动化领域的新兴趋势智能工厂的崛起智能工厂已成为自动化生产的新标杆。通过结合物联网(IoT)、人工智能(AI)和机器学习(ML),智能工厂实现了实时监控和动态决策。驱动隔离器在其中至关重要,它确保了传感器、执行器和控制单元之间的信号完整性,同时提供高
    腾恩科技-彭工 2025-01-03 16:28 166浏览
  • 随着市场需求不断的变化,各行各业对CPU的要求越来越高,特别是近几年流行的 AIOT,为了有更好的用户体验,CPU的算力就要求更高了。今天为大家推荐由米尔基于瑞芯微RK3576处理器推出的MYC-LR3576核心板及开发板。关于RK3576处理器国产CPU,是这些年的骄傲,华为手机全国产化,国人一片呼声,再也不用卡脖子了。RK3576处理器,就是一款由国产是厂商瑞芯微,今年第二季推出的全新通用型的高性能SOC芯片,这款CPU到底有多么的高性能,下面看看它的几个特性:8核心6 TOPS超强算力双千
    米尔电子嵌入式 2025-01-03 17:04 37浏览
  • 光耦合器,也称为光隔离器,是一种利用光在两个隔离电路之间传输电信号的组件。在医疗领域,确保患者安全和设备可靠性至关重要。在众多有助于医疗设备安全性和效率的组件中,光耦合器起着至关重要的作用。这些紧凑型设备经常被忽视,但对于隔离高压和防止敏感医疗设备中的电气危害却是必不可少的。本文深入探讨了光耦合器的功能、其在医疗应用中的重要性以及其实际使用示例。什么是光耦合器?它通常由以下部分组成:LED(发光二极管):将电信号转换为光。光电探测器(例如光电晶体管):检测光并将其转换回电信号。这种布置确保输入和
    腾恩科技-彭工 2025-01-03 16:27 171浏览
  • 每日可见的315MHz和433MHz遥控模块,你能分清楚吗?众所周知,一套遥控设备主要由发射部分和接收部分组成,发射器可以将控制者的控制按键经过编码,调制到射频信号上面,然后经天线发射出无线信号。而接收器是将天线接收到的无线信号进行解码,从而得到与控制按键相对应的信号,然后再去控制相应的设备工作。当前,常见的遥控设备主要分为红外遥控与无线电遥控两大类,其主要区别为所采用的载波频率及其应用场景不一致。红外遥控设备所采用的射频信号频率一般为38kHz,通常应用在电视、投影仪等设备中;而无线电遥控设备
    华普微HOPERF 2025-01-06 15:29 59浏览
  • PLC组态方式主要有三种,每种都有其独特的特点和适用场景。下面来简单说说: 1. 硬件组态   定义:硬件组态指的是选择适合的PLC型号、I/O模块、通信模块等硬件组件,并按照实际需求进行连接和配置。    灵活性:这种方式允许用户根据项目需求自由搭配硬件组件,具有较高的灵活性。    成本:可能需要额外的硬件购买成本,适用于对系统性能和扩展性有较高要求的场合。 2. 软件组态   定义:软件组态主要是通过PLC
    丙丁先生 2025-01-06 09:23 61浏览
  • 在智能家居领域中,Wi-Fi、蓝牙、Zigbee、Thread与Z-Wave等无线通信协议是构建短距物联局域网的关键手段,它们常在实际应用中交叉运用,以满足智能家居生态系统多样化的功能需求。然而,这些协议之间并未遵循统一的互通标准,缺乏直接的互操作性,在进行组网时需要引入额外的网关作为“翻译桥梁”,极大地增加了系统的复杂性。 同时,Apple HomeKit、SamSung SmartThings、Amazon Alexa、Google Home等主流智能家居平台为了提升市占率与消费者
    华普微HOPERF 2025-01-06 17:23 59浏览
  • 根据Global Info Research项目团队最新调研,预计2030年全球封闭式电机产值达到1425百万美元,2024-2030年期间年复合增长率CAGR为3.4%。 封闭式电机是一种电动机,其外壳设计为密闭结构,通常用于要求较高的防护等级的应用场合。封闭式电机可以有效防止外部灰尘、水分和其他污染物进入内部,从而保护电机的内部组件,延长其使用寿命。 环洋市场咨询机构出版的调研分析报告【全球封闭式电机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球封闭式电机总体规
    GIRtina 2025-01-06 11:10 68浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦