STM32开发 -- 串口详解

发布者:EnigmaticSoul最新更新时间:2019-08-30 来源: eefocus关键字:STM32  串口 手机看文章 扫描二维码
随时随地手机看文章

讲完GPIO,接下来看一下串口。

串口通信,已经讲了很多次了。这次主要想看的是STM32单片机怎么配置串口。

S5PV210开发 – 通信

S5PV210开发 – UART 详解

S5PV210开发 – 串口驱动开发

UNIX再学习 – RS485 串口编程

汽车行驶姿态 – 串口通信

日常生活小技巧 – UART 回环测试


一、通信接口

处理器与外部设备通信的两种方式:


并行通信:

-传输原理:数据各个位同时传输。

-优点:速度快

-缺点:占用引脚资源多


这里写图片描述

串行通信:

-传输原理:数据按位顺序传输。

-优点:占用引脚资源少

-缺点:速度相对较慢

这里写图片描述

串行通信,按照数据传送方向,分为:

单工:

数据传输只支持数据在一个方向上传输

这里写图片描述

半双工:

允许数据在两个方向上传输,但是,在某一时刻,只允许数

据在一个方向上传输,它实际上是一种切换方向的单工通信;

这里写图片描述

全双工:

允许数据同时在两个方向上传输,因此,全双工通信是两个

单工通信方式的结合,它要求发送设备和接收设备都有独立

的接收和发送能力。


这里写图片描述

串行通信的通信方式:

**同步通信:**带时钟同步信号传输。

如:SPI,IIC通信接口

**异步通信:**不带时钟同步信号。

如:UART(通用异步收发器),单总线


常见的串行通信接口:

这里写图片描述


二、STM32的串口通信接口

UART:通用异步收发器(universal asynchronous receiver and transmitter)

USART:通用同步异步收发器(universal synchronous asynchronous receiver and transmitter)


其中:

通用同步异步收发器(USART)

小容量产品:是指闪存存储器容量在16K至32K字节之间的STM32F101xx、 STM32F102xx和STM32F103xx微控制器。

中容量产品:是指闪存存储器容量在64K至128K字节之间的STM32F101xx、 STM32F102xx和STM32F103xx微控制器。

大容量产品:是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控制器。

互联型产品:是指STM32F105xx和STM32F107xx微控制器。

除非特别说明,本章描述的模块适用于整个STM32F10xxx微控制器系列。


我使用的是 STM32F105xx,所以是互联型产品,包含3个USART和2个UART。(USART1/USART2/USART3/UART4/UART5)


三、UART异步通信方式引脚连接方法

-RXD:数据输入引脚。数据接收。

-TXD:数据发送引脚。数据发送。

串口交叉线

这里写图片描述

串口直通线

这里写图片描述


四、UART异步通信方式特点

● 全双工的,异步通信

● NRZ标准格式

● 分数波特率发生器系统

─ 发送和接收共用的可编程波特率,最高达4.5Mbits/s

● 可编程数据字长度(8位或9位)

● 可配置的停止位-支持1或2个停止位

● LIN主发送同步断开符的能力以及LIN从检测断开符的能力

─ 当USART硬件配置成LIN时,生成13位断开符;检测10/11位断开符

● 发送方为同步传输提供时钟

● IRDA SIR 编码器解码器

─ 在正常模式下支持3/16位的持续时间

● 智能卡模拟功能

─ 智能卡接口支持ISO7816-3标准里定义的异步智能卡协议

─ 智能卡用到的0.5和1.5个停止位

● 单线半双工通信

● 可配置的使用DMA的多缓冲器通信

─ 在SRAM里利用集中式DMA缓冲接收/发送字节

● 单独的发送器和接收器使能位

● 检测标志

─ 接收缓冲器满

─ 发送缓冲器空

─ 传输结束标志

● 校验控制

─ 发送校验位

─ 对接收数据进行校验

● 四个错误检测标志

─ 溢出错误

─ 噪音错误

─ 帧错误

─ 校验错误

● 10个带标志的中断源

─ CTS改变

─ LIN断开符检测

─ 发送数据寄存器空

─ 发送完成

─ 接收数据寄存器满

─ 检测到总线为空闲

─ 溢出错误

─ 帧错误

─ 噪音错误

─ 校验错误

● 多处理器通信 – 如果地址不匹配,则进入静默模式

● 从静默模式中唤醒(通过空闲总线检测或地址标志检测)

● 两种唤醒接收器的方式:地址位(MSB,第9位),总线空闲


五、串口通信过程


这里写图片描述

六、STM32串口异步通信需要定义的参数

起始位

数据位(8位或者9位)

奇偶校验位(第9位)

停止位(1,15,2位)

波特率设置

这里写图片描述


七、串口配置

串口设置的一般步骤可以总结为如下几个步骤:

1、串口时钟使能,GPIO时钟使能

2、串口复位

3、GPIO端口模式设置

4、串口参数初始化

5、开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)

6、使能串口

7、编写中断处理函数


下面, 我们就简单介绍下这几个与串口基本配置直接相关的几个固件库函数。 这些函数和定义主要分布在 stm32f10x_usart.h 和stm32f10x_usart.c 文件中。

1.串口时钟使能。 串口是挂载在 APB2 下面的外设,所以使能函数为:


RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1);


2.串口复位。 当外设出现异常的时候可以通过复位设置,实现该外设的复位,然后重新配置这个外设达到让其重新工作的目的。一般在系统刚开始配置外设的时候,都会先执行复位该外设的操作。 复位的是在函数 USART_DeInit()中完成:


void USART_DeInit(USART_TypeDef* USARTx);//串口复位


比如我们要复位串口 1,方法为:


USART_DeInit(USART1); //复位串口 1


3.串口参数初始化。 串口初始化是通过 USART_Init()函数实现的,


void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);


这个函数的第一个入口参数是指定初始化的串口标号,这里选择 USART1。

第二个入口参数是一个 USART_InitTypeDef 类型的结构体指针, 这个结构体指针的成员变量用来设置串口的一些参数。 一般的实现格式为:


USART_InitStructure.USART_BaudRate = bound; //波特率设置;

USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为 8 位数据格式

USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位

USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位

USART_InitStructure.USART_HardwareFlowControl

= USART_HardwareFlowControl_None; //无硬件数据流控制

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式


从上面的初始化格式可以看出初始化需要设置的参数为:波特率,字长,停止位,奇偶校验位,硬件数据流控制,模式(收,发)。 我们可以根据需要设置这些参数。

4.数据发送与接收。 STM32 的发送与接收是通过数据寄存器 USART_DR 来实现的,这是一个双寄存器,包含了 TDR 和 RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到数据的时候,也是存在该寄存器内。

STM32 库函数操作 USART_DR 寄存器发送数据的函数是:


void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);


通过该函数向串口寄存器 USART_DR 写入一个数据。

STM32 库函数操作 USART_DR 寄存器读取串口接收到的数据的函数是:


uint16_t USART_ReceiveData(USART_TypeDef* USARTx);


通过该函数可以读取串口接受到的数据。

5.串口状态。 串口的状态可以通过状态寄存器 USART_SR 读取。 USART_SR 的各位描述如图 9.1.1 所示:

这里写图片描述

这里我们关注一下两个位,第 5、 6 位 RXNE 和 TC。

RXNE(读数据寄存器非空),当该位被置 1 的时候,就是提示已经有数据被接收到了,并且可以读出来了。这时候我们要做的就是尽快去读取 USART_DR,通过读 USART_DR 可以将该位清零,也可以向该位写 0,直接清除。

TC(发送完成),当该位被置位的时候,表示 USART_DR 内的数据已经被发送完成了。如果设置了这个位的中断,则会产生中断。该位也有两种清零方式: 1)读 USART_SR,写USART_DR。 2)直接向该位写 0。

状态寄存器的其他位我们这里就不做过多讲解,大家需要可以查看中文参考手册。

在我们固件库函数里面,读取串口状态的函数是:


FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);


这个函数的第二个入口参数非常关键, 它是标示我们要查看串口的哪种状态, 比如上面讲解的RXNE(读数据寄存器非空)以及 TC(发送完成)。例如我们要判断读寄存器是否非空(RXNE), 操作库函数的方法是:


USART_GetFlagStatus(USART1, USART_FLAG_RXNE);


我们要判断发送是否完成(TC),操作库函数的方法是:


USART_GetFlagStatus(USART1, USART_FLAG_TC);


这些标识号在 MDK 里面是通过宏定义定义的:


#define USART_IT_PE ((uint16_t)0x0028)

#define USART_IT_TXE ((uint16_t)0x0727)

#define USART_IT_TC ((uint16_t)0x0626)

#define USART_IT_RXNE ((uint16_t)0x0525)

#define USART_IT_IDLE ((uint16_t)0x0424)

#define USART_IT_LBD ((uint16_t)0x0846)

#define USART_IT_CTS ((uint16_t)0x096A)

#define USART_IT_ERR ((uint16_t)0x0060)

#define USART_IT_ORE ((uint16_t)0x0360)

#define USART_IT_NE ((uint16_t)0x0260)

#define USART_IT_FE ((uint16_t)0x0160)


6.串口使能。 串口使能是通过函数 USART_Cmd()来实现的,这个很容易理解,使用方法是:


USART_Cmd(USART1, ENABLE); //使能串口


7.开启串口响应中断。 有些时候当我们还需要开启串口中断,那么我们还需要使能串口中断,使能串口中断的函数是:


void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT,

FunctionalState NewState)


这个函数的第二个入口参数是标示使能串口的类型, 也就是使能哪种中断, 因为串口的中断类型有很多种。 比如在接收到数据的时候(RXNE 读数据寄存器非空),我们要产生中断,那么我们开启中断的方法是:


USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断,接收到数据中断


我们在发送数据结束的时候(TC, 发送完成) 要产生中断,那么方法是:


USART_ITConfig(USART1, USART_IT_TC, ENABLE);


8.获取相应中断状态。 当我们使能了某个中断的时候,当该中断发生了,就会设置状态寄存器中的某个标志位。 经常我们在中断处理函数中,要判断该中断是哪种中断,使用的函数是:


ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)


比如我们使能了串口发送完成中断,那么当中断发生了, 我们便可以在中断处理函数中调用这个函数来判断到底是否是串口发送完成中断,方法是:


USART_GetITStatus(USART1, USART_IT_TC)


返回值是 SET,说明是串口发送完成中断发生。


八、串口程序完整代码

参看:USART串口通信配置


#include "stm32f10x.h"

u8 Uart1_Get_Flag  = 0;

// 串口初始化函数

void My_USART1_Init(void)

{

    GPIO_InitTypeDef GPIO_InitStrue;

    USART_InitTypeDef USART_InitStrue;

    NVIC_InitTypeDef NVIC_InitStrue;


    // 1,使能GPIOA,USART1时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);


    // 2,设置PGIO工作模式-PA9 PA10复用为串口1

    GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出

    GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;//USART1_TX PA.9

    GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;

    GPIO_Init(GPIOA,&GPIO_InitStrue); //初始化 GPIOA.9


    GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入

    GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;//USART1_RX PA.10

    GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;

    GPIO_Init(GPIOA,&GPIO_InitStrue); //初始化 GPIOA.10


    // 3,串口1初始化配置

    USART_InitStrue.USART_BaudRate=115200;//波特率设置

    USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件数据流控制

    USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;//收发模式

    USART_InitStrue.USART_Parity=USART_Parity_No; //无奇偶校验位

    USART_InitStrue.USART_StopBits=USART_StopBits_1; //一个停止位

    USART_InitStrue.USART_WordLength=USART_WordLength_8b;//字长为 8 位


    USART_Init(USART1,&USART_InitStrue);//初始化串口


    // 4,打开串口1

    USART_Cmd(USART1,ENABLE);//使能串口


    // 5,使能串口1中断-接收数据完成中断

    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启中断


    // 6,设置中断优先级-主函数中设置中断优先级分组

    NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;

    NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;//IRQ 通道使能

    NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级 1

    NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;//子优先级 1

    NVIC_Init(&NVIC_InitStrue);//中断优先级初始化


}


void USART1_Puts(char * str)

{

    while(*str)

    {

        USART_SendData(USART1, *str++);

        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

    }

}


// 中断服务函数

void USART1_IRQHandler(void)

{

    u8 res;

    if(USART_GetITStatus(USART1,USART_IT_RXNE))// 接收到数据

    {

        USART_ClearITPendingBit(USART1,USART_IT_RXNE);

        res= USART_ReceiveData(USART1); // 获得串口1接收到的数据

    Uart1_Get_Flag=1;

    }

}


// 主函数

int main(void)

{   

    // 设置中断优先级分组位2 - 2位抢占2位相应

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);


    // 调用函数 初始化USART1相关引脚配置

    My_USART1_Init();

    if (Uart1_Get_Flag){

   Uart1_Get_Flag = 0;

   USART1_Puts(res);

    }


return 0;

}


九、串口其他需要了解的

串口相关寄存器

上面串口部分其实基本上已经讲完了。

但是我们用的库函数版本是3.5的。在串口配置中还要配置USART 时钟的。

首先看下串口相关的寄存器:


USART_SR 状态寄存器

USART_DR 数据寄存器

USART_BRR 波特率寄存器

USART_CR1 控制寄存器


具体的配置看STM32中文参考手册了解一下,直接用串口库函数就好了。


十、串口操作相关库函数

获取状态标志位函数-操作USART_SR寄存器

// 获取状态标志位

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);

// 清除状态标志位

void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);

// 获取中断状态标志位

ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);

// 清除中断状态标志位

void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);


接收发送数据函数-操作USART_DR寄存器

// 发送数据到串口(通过写USART_DR寄存器发送数据)

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);

// 接收数据(从USART_DR寄存器读取接收到的数据)

uint16_t USART_ReceiveData(USART_TypeDef* USARTx);


串口配置函数

// 串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能

void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);

// 使能串口

void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);

// 使能相关中断

void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);


我们用的库函数V3.5里面还有:


这里写图片描述

串口复位

void USART_DeInit(USART_TypeDef* USARTx)

串口时钟的初始化:

void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct)

串口通信DMA中断

void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, 

所以除了上述的串口配置,还可以添加如下的配置:


USART_InitTypeDef USART_InitStrue;

    USART_ClockInitTypeDef  USART_CLK_InitStrue;

    USART_InitStrue.USART_BaudRate            = baud_rate;//波特率设置

    USART_InitStrue.USART_WordLength          = USART_WordLength_8b;//字长为 8 位

    USART_InitStrue.USART_StopBits            = USART_StopBits_1;//一个停止位

    USART_InitStrue.USART_Parity              = USART_Parity_No ;//无奇偶校验位

    USART_InitStrue.USART_HardwareFlowControl =    USART_HardwareFlowControl_None;//无硬件数据流控制

[1] [2]
关键字:STM32  串口 引用地址:STM32开发 -- 串口详解

上一篇:STM32F4串口接收(HAL库)使用笔记
下一篇:STM32开发 -- STM32初识

推荐阅读最新更新时间:2024-11-13 13:00

STM32芯片如何使用片内参考电压实现模拟看门狗
STM32芯片的ADC模块往往都支持模拟看门狗功能,即可以对单个或多个通道开启模拟转换值的监测。当模拟通道ADC值超出设定的阈值时可以产生模拟看门狗事件并可触发看门狗中断。【注:下面截图或数据都是基于STM32L4系列芯片的,其它STM32系列与其类似。】 结合上图,当选定的ADC通道的转换结果比设置的阈值上限还高或比设定的阈值下限还低时都可以通过硬件触发模拟看门狗事件或中断。 假设现有STM32用户有这样一个应用需求,他希望STM32的供电电压低于一定程度时就提示低压报警,然后软件将进行相关处理。 关于这个应用需求,我们就可以利用片内的一个参考电压和模拟看门狗来实现。 我们知道,STM32芯片内部都内置了一个比
[单片机]
<font color='red'>STM32</font>芯片如何使用片内参考电压实现模拟看门狗
STM32操作 I/O 口的步骤
先来总结一下 STM32 操作 I/O 口的步骤(以精英板为例): ① 使能 I/O 口时钟,调用函数为RCC_APB2PeriphClockCmd(); ② 初始化 I/O 参数,调用GPIO_Init(); ③ 操作 I/O 口 看了STM32操作 I/O 口的步骤,是不是一头雾水,因为我们以前学习51单片机的时候,根本没有这么麻烦,I/O 想输入就直接读,想输出就直接赋值,串口、AD转化、外部中断等等也都是想用就用,不需要单独配置时钟。 51单片机的这种做法确实很方便,不需要有乱七八糟的设置就能让芯片跑起来,但是随之带来的就是所谓的功耗问题。换句话来说就是一些资源根本用不上,但是芯片却还给它分配资源,即增加了芯片的负担,
[单片机]
STC-C51串口问题
STC11L32XE STC11L48XE STC11L60XE 串口问题 1. 这个3个芯片都有2个串口,(RXD/P1.6、TXD/P1.7)---Port1串口 和 (RXD/P3.0、TXD/3.1)---Port3串口。这个2个串口,不能同时使用,只能分时复用,通过AUXR1来选择,如下图: 2. 在使用STC软件烧写程序的时候,只能使用Port3进行烧写,这是因为在boot烧写程序中把这个串口固定了,只能用这个串口烧写。
[单片机]
J-link在MKD5下在线调试STM32
一、手动安装匹配的装置包 装上MDK5后,是和之前的版本不冲突的,之前的KEIL4 for C51和forARM都可以留着不必卸载。可以另外建立一个安装目录,两者相安无事。 在MDK5新建工程,和之前的版本有很大不同。如果第一次用,之前选择目标型号的那个对话框里,只有ARM内核可选,没有具体的单片机型号。估计是因为发展到现在单片机不同厂商的不同产品已经太多了,如果囊括所有的device,会是开发环境变得非常庞大,而且平时搞开发,可能很长一段时间里用的就那么一两款。 新建工程后需要安装和目标单片机相匹配的device(如果是将MDK4建立的工程导入到MDK5中,也许要下载这个东西)。 选择合适的devic
[单片机]
J-link在MKD5下在线调试<font color='red'>STM32</font>
STM32 模拟IIC协议驱动TEA5767
IIC驱动程序参考自《ALIENTEK MINISTM32 实验16 IIC实验》,做了简单的修改就轻易驱动TEA5767。至于TEA5767内部寄存器的配置就不说了。看程序: 文件:I2C_Driver.h #ifndef __I2C_Driver_H #define __I2C_Driver_H #define uchar unsigned char #define uint unsigned short int #define ulint unsigned int #define delay_nus 2 //IO方向设置 #define SDA_IN() {GPIOB- CRH&=0XFFFF0FFF;
[单片机]
<font color='red'>STM32</font> 模拟IIC协议驱动TEA5767
STM32开发笔记1: STM32F407时钟配置
单片机型号:STM32F407 本文讲解STMF407时钟的使用及其配置方法。 1、STM32F407的分类 a、LSI是低速内部时钟,RC震荡器,频率为32KHz左右。供独立看门狗和自动唤醒单元使用。 b、LSE是低速外部时钟,接频率为32.768KHz的石英晶体。这个主要是RTC的时钟源。 c、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz-26MHz。 d、HSI是高速内部时钟,RC振荡器,频率为16MHz。可以直接作为系统时钟或者用作PLL输入。 e、PLL为锁相环倍频输出,STM32F4有两个PLL: 主P
[单片机]
<font color='red'>STM32</font>开发笔记1: STM32F407时钟配置
Stm32外部中断以及NVIC笔记
1.外部中断 1.概念: 1 :当某种事件发生时,CPU自动停止所干的事 从而去临时处理突发事件 2 :对于Stm32F103rc而言,一共有60个可屏蔽中断(外部中断),16个内核中断 2.设置方法: 1 :初始化相关的IO口 2 :开启复用时钟,设置IO口和中断线的映射关系 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断,需要使能AFIO时钟 3 开启与该IO口想对的线上中断和设置触发条件 库函数: GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5); E
[单片机]
<font color='red'>Stm32</font>外部中断以及NVIC笔记
stm32 精确电压测量法(内部参考电压)
芯片型号:stm32l051c8(其它型号请参考datasheet,仅供参考) 使用ADC采集电压时若使用外部参考电压,如果外部电压变化,且低于正常LDO工作电压时,输出的电压将发生改变,导致基准电压改变而导致ADC电压出现偏差,因此在该芯片上查看datasheet后得知,厂家已经为我们考虑到这种情况,并在出厂时将类似于基准电压的值写在flash中。该值的环境:25°C, VDD = 3V时的情况,可以直接地址访问读取,我读取了两个芯片的值,大概在1670值左右。通过该值我们就有一个标准。 接下来看参考手册中对该款芯片的介绍, 我们可以看到,通过读取ADC IN17可以获得内部参考电压值,假设我们现在要读取电池电量,需
[单片机]
<font color='red'>stm32</font> 精确电压测量法(内部参考电压)
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多往期活动

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved