STM32的I2C主从机通信

2019-04-02来源: eefocus关键字:STM32  I2C  主从机通信

最近一段时间在做I2C通信协议,需要在两块STM32之间做I2C通信,定的是主机用IO口模拟,从机用的是STM32的硬件I2C,我的项目要求是需要主从机之间能够进行一串数据收发而不出错,实验时在主机方面,利用IO口模拟主机,只需要理解时序就够了,同时将速度能够控制在100K(标准)左右,基本的时序理解网上大把的资料,所以主机这一块几个小时就搞定了,而在做从机时,遇到了困难,本来从机也想用IO口模拟的,但是速度达不到那么快,因此只能选择硬件做从机,现就从机用中断方式开说,总结过程中遇到的几点问题:

1、由于STM32的硬件问题,建议在使用I2C时,将其优先级设为最高。

2、针对程序中除了I2C数据收发,还有别的中断程序或者指令要执行而导致I2C数据传输堵塞时,可以在执行完该段程序后重新初始化I2C。


主机程序如下:


  1 #include "Hal_IIC/I2C.h"
  2 #include "Hal_delay/delay.h"
  3 #include "common.h"
  4 #include "gizwits_product.h"
  5 
  6 extern void delayUs(uint32_t nus);
  7 uint8_t b[5];
  8 extern uint8_t Cookr[5];
  9 extern uint8_t WR_flag;
 10 uint8_t Wifi_SET;  //WIFI状态脚
 11 extern uint8_t Power_flag;         //电磁炉开启关闭标志位
 12 uint8_t Give_Up;
 13 /*--------------------------------------------------------------------------------
 14 调用方式:void IIC_Init(void) 
 15 函数说明:私有函数,I2C专用,函数初始化
 16 ---------------------------------------------------------------------------------*/ 
 17 void IIC_Init(void)
 18 {                         
 19     GPIO_InitTypeDef GPIO_InitStructure;
 20     RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOA, ENABLE );    //使能GPIOA时钟
 21        
 22     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
 23     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
 24     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 25     GPIO_Init(GPIOA, &GPIO_InitStructure);
 26     GPIO_SetBits(GPIOA,GPIO_Pin_11|GPIO_Pin_12);     //PA11,PA12 输出高
 27 }
 28 /*--------------------------------------------------------------------------------
 29 调用方式:void I2CStart(void) 
 30 函数说明:私有函数,I2C专用,开始信号
 31 ---------------------------------------------------------------------------------*/
 32 void IIC_Start(void)
 33 {
 34     SDA_OUT();     //sda线输出
 35     IIC_SDA=1;            
 36     IIC_SCL=1;
 37     delayUs(4);
 38      IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
 39     delayUs(4);
 40     IIC_SCL=0;  //钳住I2C总线,准备发送或接收数据 
 41 }      
 42 /*--------------------------------------------------------------------------------
 43 调用方式:void I2CStop(void) 
 44 函数说明:私有函数,I2C专用,停止信号
 45 ---------------------------------------------------------------------------------*/
 46 void IIC_Stop(void)
 47 {
 48     SDA_OUT();//sda线输出
 49     IIC_SCL=0;
 50     IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 51      delayUs(4);
 52     IIC_SCL=1; 
 53     IIC_SDA=1;//发送I2C总线结束信号
 54     delayUs(4);                                   
 55 }
 56 /*--------------------------------------------------------------------------------
 57 调用方式:I2CAck(void) 
 58 函数说明:私有函数,I2C专用,等待从器件接收方的应答,0表示接受成功,1表示失败
 59 ---------------------------------------------------------------------------------*/
 60 uint8_t IIC_Wait_Ack(void)
 61 {
 62     uint8_t ucErrTime=0;
 63     SDA_IN();      //SDA设置为输入  
 64     IIC_SDA=1;delayUs(1);       
 65     IIC_SCL=1;delayUs(1);     
 66     while(READ_SDA)
 67     {
 68         ucErrTime++;
 69         if(ucErrTime>250)
 70         {
 71             IIC_Stop();
 72             return 1;
 73         }
 74     }
 75     IIC_SCL=0;//时钟输出0        
 76     return 0;  
 77 } 
 78 /*--------------------------------------------------------------------------------
 79 调用方式:void SendAck(void) 
 80 函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。
 81 ---------------------------------------------------------------------------------*/
 82 void IIC_Ack(void)
 83 {
 84     IIC_SCL=0;
 85     SDA_OUT();
 86     IIC_SDA=0;
 87     delayUs(2);
 88     IIC_SCL=1;
 89     delayUs(2);
 90     IIC_SCL=0;
 91 }
 92 /*--------------------------------------------------------------------------------
 93 调用方式:void SendAck(void) 
 94 函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,非应答信号。
 95 ---------------------------------------------------------------------------------*/        
 96 void IIC_NAck(void)
 97 {
 98     IIC_SCL=0;
 99     SDA_OUT();
100     IIC_SDA=1;
101     delayUs(2);
102     IIC_SCL=1;
103     delayUs(2);
104     IIC_SCL=0;
105 }                                          
106 /*--------------------------------------------------------------------------------
107 调用方式:void IIC_Send_Byte(unsigned char ch) 
108 函数说明:私有函数,I2C专用
109 ---------------------------------------------------------------------------------*/      
110 void IIC_Send_Byte(uint8_t txd)
111 {                        
112     uint8_t t;   
113     SDA_OUT();         
114     IIC_SCL=0;//拉低时钟开始数据传输
115     for(t=0;t>7;
118         if((txd&0x80)>>7)
119             IIC_SDA=1;
120         else
121             IIC_SDA=0;
122         txd<<=1;       
123         delayUs(2);   //对TEA5767这三个延时都是必须的
124         IIC_SCL=1;
125         delayUs(2); 
126         IIC_SCL=0;    
127         delayUs(2);
128     }     
129 }         
130 /*--------------------------------------------------------------------------------
131 调用方式:unsigned char IIC_Read_Byte(void) 
132 函数说明:私有函数,I2C专用
133 ---------------------------------------------------------------------------------*/
134 //读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
135 uint8_t IIC_Read_Byte(unsigned char ack)
136 {
137     unsigned char i,receive=0;
138     SDA_IN();//SDA设置为输入
139     for(i=0;i<8;i++ )
140     {
141                 receive<<=1;
142         IIC_SCL=0; 
143         delayUs(5);
144             IIC_SCL=1;
145                 delayUs(5);
146         
147         if(READ_SDA)receive++;   
148          
149   }                     
150     if (!ack)
151         IIC_NAck();//发送nACK
152     else
153         IIC_Ack(); //发送ACK   
154     return receive;
155 }
156 
157 
158 //读温度传感器,温度值是由h的高字节和低字节的高四位组成,总共12位,其中负温度值是由补码形式
159 void T_Read(void)
160 {
161             
162     /***************read start*******************/
163     if(WR_flag==0x02)
164     {
165 
166     IIC_Start();
167         IIC_Send_Byte( 0x30|0x01);          //读操作
168          while(IIC_Wait_Ack());        
169    //     delayMs(500);                         //等待从机处理一个字节地址位
170     Give_Up = IIC_Read_Byte(1);        
171         for(uint8_t i=0;i<4;i++)
172         {
173             b[i] = IIC_Read_Byte(1);
174             printf("%c",b[i]);
175         }
176         b[4] = IIC_Read_Byte(0);
177         printf("%c",b[4]);
178         
179         if((b[0]==0xFA)&&(b[4]==0xFB))
180         {
181           for(uint8_t i=1;i<6;i++)
182           {
183               Cookr[i] = b[i];
184           }    
185 
186         }
187     }    
188    
189     /****************read end********************/
190   /****************write start*****************/
191         if(WR_flag==0x01)
192         {
193             IIC_Start();
194             IIC_Send_Byte(0x30);     //写操作
195             while(IIC_Wait_Ack());
196             IIC_Send_Byte(0xFA);
197             while(IIC_Wait_Ack());
198             delayMs(3);              //延时太低传输数据会出错,因为从机还没处理完数据
199             IIC_Send_Byte(Cookr[1]);
200             while(IIC_Wait_Ack());
201             delayMs(3);
202             IIC_Send_Byte(0x03);
203             while(IIC_Wait_Ack());
204             delayMs(3);
205             IIC_Send_Byte(Power_flag);
206             while(IIC_Wait_Ack());
207             delayMs(3);
208             IIC_Send_Byte(0xFB);
209             while(IIC_Wait_Ack());
210             delayMs(3);
211             IIC_Stop();
212           WR_flag=0x02;    
213         }
214         /***************write end*****************/
215      
216 }

从机使用中断方式


  1 #include "myiic.h"
  2 #include "delay.h"
  3 #include "led.h"
  4 #include "key.h"
  5 #include "usart.h"
  6 
  7 
  8 #define MY_I2C_ADDRESS    0x30                         //模拟从机地址
  9 unsigned char b[5]={0x00,0x00,0x00,0x00,0x00};         //从机接收操作
 10 uint8_t Wifi_Set=0x00;
 11 extern u8 flag;                                        //电磁炉开关中断位
 12 unsigned char a[5]={0xFA,0x00,0x00,0x00,0xFB};         
 13 //初始化IIC
 14 void I2C1_Init(void)
 15 {
 16     GPIO_InitTypeDef GPIO_InitStructure;
 17     I2C_InitTypeDef I2C_InitStructure;
 18     NVIC_InitTypeDef NVIC_InitStructure;
 19     
 20     RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);   // enable APB1 peripheral clock for I2C1
 21     
 22     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  // enable clock for SCL and SDA pins
 23     
 24     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
 25     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 26     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;        //I2C必须开漏输出,实现线与逻辑
 27     GPIO_Init(GPIOB, &GPIO_InitStructure);
 28     
 29     
 30     I2C_InitStructure.I2C_ClockSpeed = 100000;             // configure I2C1 
 31     I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
 32     I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
 33     I2C_InitStructure.I2C_OwnAddress1 = MY_I2C_ADDRESS;
 34     I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
 35     I2C_InitStructure.I2C_AcknowledgedAddress= I2C_AcknowledgedAddress_7bit;
 36     I2C_Init(I2C1, &I2C_InitStructure);
 37 
 38     //setup interrupts
 39     I2C_ITConfig(I2C1, I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF, ENABLE);   
 40 
 41     
 42     // Configure the I2C event priority
 43     NVIC_InitStructure.NVIC_IRQChannel                   = I2C1_EV_IRQn;
 44     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;       //抢占优先级1
 45     NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;       //响应优先级0
 46     NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
 47     NVIC_Init(&NVIC_InitStructure);
 48 
 49     // enable I2C1
 50     I2C_Cmd(I2C1, ENABLE);
 51 }
 52 
 53 
 54 //Clear ADDR by reading SR1, then SR2
 55 
 56 void I2C_clear_ADDR(I2C_TypeDef* I2Cx) {
 57     I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR);
 58     ((void)(I2Cx->SR2));
 59 }
 60 
 61 //Clear STOPF by reading SR1, then writing CR1
 62 
 63 void I2C_clear_STOPF(I2C_TypeDef* I2Cx) {
 64     I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF);
 65     I2C_Cmd(I2Cx, ENABLE);
 66 }
 67 
 68 /*--------------------------------------------------------------------------------
 69 调用方式:void I2C1_EV_IRQHandler(void) 
 70 函数说明:私有函数,I2C专用,中断按键处理函数,从机中断都在这里面执行
 71 ---------------------------------------------------------------------------------*/
 72 
 73 uint8_t data = 0;
 74 uint8_t S_data=0;
 75 void I2C1_EV_IRQHandler(void) 
 76 {
 77 //        KV1=0;                                 //只是一个测试灯
 78         //Clear AF from slave-transmission end
 79         if(I2C_GetITStatus(I2C1, I2C_IT_AF)) 
 80         {
 81             I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
 82         }
 83         //Big state machine response, since doesn't actually keep state
 84         switch(I2C_GetLastEvent(I2C1)) 
 85             {
 86             //SLAVE
 87             //Receive
 88             case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: //EV1
 89                 I2C_clear_ADDR(I2C1);
 90                 break;
 91             case I2C_EVENT_SLAVE_BYTE_RECEIVED: //EV2
 92                 //Read it, so no one is waiting, clears BTF if necessary
 93                 b[data] = I2C_ReceiveData(I2C1);
 94         //      printf("%c",b[data]);
 95                 data++;
 96                 if(data>=5)
 97                 {
 98                                 data=0;
 99                                 if((b[0]==0xFA)&&(b[4]==0xFB))
100                                 {
101                                     a[1]=b[1];
102                                     Wifi_Set=b[2];
103                                     flag=b[3];
104                 //                    printf("%c",a[1]);
105                                 }
106 
107                 }
108                 if(I2C_GetFlagStatus(I2C1, I2C_FLAG_DUALF)) 
109                 {//Secondary Receive
110                 } 
111                 else if(I2C_GetFlagStatus(I2C1, I2C_FLAG_GENCALL)) 
112                 {//General Receive
113                 } 
114                 else 
115                 {//Normal
116                 }
117                 break;
118             case I2C_EVENT_SLAVE_STOP_DETECTED: //End of receive, EV4
119                 I2C_clear_STOPF(I2C1);
120                 break;
121 
122             //Transmit
123             case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: //EV1
124                 I2C_clear_ADDR(I2C1);
125                 //Send first byte
126                I2C_SendData(I2C1, 0x00);
127             
128                 break;
129             case I2C_EVENT_SLAVE_BYTE_TRANSMITTED: //EV3
130                 //Determine what you want to send
131                 //data = 5;
132                 if(I2C_GetFlagStatus(I2C1, I2C_FLAG_DUALF)) 
133                 {//Secondary Transmit
134                 } 
135                 else if(I2C_GetFlagStatus(I2C1, I2C_FLAG_GENCALL)) 
136                 {//General Transmit
137                 } 
138                 else 
139                 {//Normal
140                 }
141                 //Read flag and write next byte to clear BTF if present
142                 I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF);
143                 I2C_SendData(I2C1, a[S_data]);
144                 S_data++;
145                 if(S_data>=5)
146                 S_data=0;
147                 break;
148             case I2C_EVENT_SLAVE_ACK_FAILURE://End of transmission EV3_2
149                 //TODO: Doesn't seem to be getting reached, so just
150                 //check at top-level
151                 I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
152                 break;
153             //Alternative Cases for address match
154             case I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED:    //EV1
155                 break;
156             case I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED: //EV1
157                 break;
158             case I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED:        //EV1
159                 break;
160 
161 
162             //MASTER
163             case I2C_EVENT_MASTER_MODE_SELECT: //EV5, just sent start bit
164                 break;
165             //Receive
166             case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: //EV6, just sent addr    
167                 break;
168             case I2C_EVENT_MASTER_BYTE_RECEIVED: //EV7
169                 break;
170             //Transmit
171             case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: //EV6, just sent addr     
172                 break;
173             case I2C_EVENT_MASTER_BYTE_TRANSMITTING: //EV8, about to send data
174                 break;
175             case I2C_EVENT_MASTER_BYTE_TRANSMITTED: //EV8_2, just sent data
176                 break;
177 
178             //Alternative addressing stuff, not going to worry about
179             case I2C_EVENT_MASTER_MODE_ADDRESS10: //EV9
180                 break;
181             default:
182                 //How the FUCK did you get here?
183                 //I should probably raise some error, but fuck it,
184                 //it's late
185                 break;
186 
187         }
188 
189 
190 }
191 
192 void I2C1_ER_IRQHandler(void) {
193  //       GPIO_SetBits(GPIOD, RED);
194 //    LED3=0;
195         //Can't use nice switch statement, because no fxn available
196         if(I2C_GetITStatus(I2C1,        I2C_IT_SMBALERT)) {
197         } else if(I2C_GetITStatus(I2C1, I2C_IT_TIMEOUT)) {
198         } else if(I2C_GetITStatus(I2C1, I2C_IT_PECERR)) {
199         } else if(I2C_GetITStatus(I2C1, I2C_IT_OVR)) {
200             //Overrun
201             //CLK stretch disabled and receiving
202             //DR has not been read, b4 next byte comes in
203             //effect: lose byte
204             //should:clear RxNE and transmitter should retransmit
205 
206             //Underrun
207             //CLK stretch disabled and I2C transmitting
208             //haven't updated DR since new clock
209             //effect: same byte resent
210             //should: make sure discarded, and write next
211         } else if(I2C_GetITStatus(I2C1, I2C_IT_AF)) {
212             //Detected NACK
213             //Transmitter must reset com
214                 //Slave: lines released
215                 //Master: Stop or repeated Start must must be generated
216                 //Master = MSL bit
217             //Fixup
218             I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
219         } else if(I2C_GetITStatus(I2C1, I2C_IT_ARLO)) {
220             //Arbitration Lost
221             //Goes to slave mode, but can't ack slave address in same transfer
222             //Can after repeat Start though
223         } else if(I2C_GetITStatus(I2C1, I2C_IT_BERR)) {
224             //Bus Error
225             //In slave mode: data discarded, lines released, acts like restart
226             //In master mode: current transmission continues
227         }
228 }


关键字:STM32  I2C  主从机通信 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/2019/ic-news040243682.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:stm32f1xx i2c通讯故障可能原因
下一篇:STM32F030 I2C 从模式中断编程

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32MxCube配置串口
基于上一次将第一章:STM32MxCube 基本使用方法,本章直接讲叙述STM32配置串口2的。查看STM32F407电路图:可得USART2接在PA2、PA3。下面新建STM32MxCube工程,开始配置。这里我们配置IO(定义PF9、PF10引脚为LED)、RCC(使用HSE)、USART(串口)。配置USART(串口)USART的配置有好几种,也是最常见的一种”UART异步串行通信”配置来讲述。选择USART2模式为“asynchronous”(异步通信)对应的引脚自动转换为USART。对于系统时钟应该都知道它的作用,就是驱动整个芯片工作的心脏,如果没有了它,就等于人没有了心跳。时钟的快慢也就决定了程序的快慢。STM32
发表于 2020-05-04
STM32MxCube配置串口
STM32CubeMX学习教程之一:GPIO输出之跑马灯
完整源码下载:https://github.com/simonliu009/STM32CubeMX-GPIO-Control软件版本:STM32CubeMX V4.25.0 System Workbench V2.4固件库版本:STM32Cube FW_F1 V1.6.1硬件:OneNet 麒麟座V2.3在STM32CubeMX中新建项目,选择正确的MCU型号首先设置RCC和SYS,如下图然后根据板子实际情况设置时钟(麒麟座外部晶振是12M,STM32F103x的最高主频是72M),如下图GPIO设置 PC7, PC8, PA12和 PC10为GPIO_OUTPUT, (这是麒麟座V2.3的四个LED管脚),如下图
发表于 2020-05-04
STM32CubeMX学习教程之一:GPIO输出之跑马灯
STM32CubeMX学习--(3)串口通信
Cube配置USART配置在Connectivity中选中USART1MODE = AsynchronousHardware Flow Control = DisableParameter Settings中配置Baud Rate = 115200Word Length = 8bitParity = NoneStop Bits =1Data Direction = Receive and TransmitOver Sampling = 16 SamplesNVIC Setting勾选Enable,Preemption Priority =2生成代码修改代码生成代码后,即可使用HAL_UART_Transmit_IT(&
发表于 2020-04-29
STM32CubeMX系列教程 5.0版本环境开发——2.Uart串行通信功能
;                         PS:在明白原理的情况下建议自己手写一次模拟UART。明白了之后,代码重复的事就由STM32芯片的硬件功能来实现就可以了,你只需要会看逻辑分析仪或者示波器分析数据便可。 所谓硬件功能 就是你把数据填充到寄存器,然后配置好相关参数,他会自动帮你发送出去。通俗点说,自己手写整个协议代码实现实现就像你自己把一个快件送到到别人那里再回来,而硬件功能则是你把快件给快递员,快递员帮你送过去。  明显 后者会帮你节省大量时间和精力。它是一个硬件组成,并且你也为此付费
发表于 2020-04-29
STM32CubeMX系列教程 5.0版本环境开发——2.Uart串行通信功能
串口通信(用CubeMX学习STM32)
前言: STM32串口介绍串行通信是单片机与外部设备或其他计算机交换信息的一个方式, 数据一位一位的按顺序传送, 其优点是只需要一条传输线, 协议简单, 但是缺点就是传送速度较慢。串口是单片机上非常便捷的一个工具, 当写程序需要调试的时候, 它可以很方便的提供调试方法, 只要在一些关键代码执行的地方, 通过串口给串口调试助手发送相关信息, 就可以使我们很方便的查看代码在这个位置的执行情况。下面看一下我所使用的单片机上串口的原理图接线外部的发送端TXD就是单片机串口的接收端USART_RX,   外部接收端RXD就是单片机串口的发送端USART_TXTXD : Transmit(TX) Data(D)  Receive(RX
发表于 2020-04-29
【STM32CubeMX】 串口通信(USART) Printf重定向
STM32CubeMX: Version 4.26.1MDK-ARM: Version 5.24.2开发板: 中移onenet 麒麟座MINI板芯片: STM32F103CBT61.STM32CubeMX设置设置外部时钟源设置Debug设置串口 使用USART1 PA9,PA10设置时钟频率设置USART1详细参数生成MDK-ARM工程2.重定向Printf 及 Scanf主要用到两个函数HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout
发表于 2020-04-29
【STM32CubeMX】 串口通信(USART) Printf重定向
小广播
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件
电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved