SJA1000+C51

发布者:云淡风轻2014最新更新时间:2016-08-16 来源: eefocus关键字:SJA1000  C51 手机看文章 扫描二维码
随时随地手机看文章
#include "CANBUS.H"

//-------------------------------------define  variable------------------------------------
unsigned char receive_counter = 0;
unsigned char alc = 1;
unsigned char ecc = 1;

/************************************************************************
*函数原型:  bit   CAN_CREATE_COMMUNATION(void)
*参数说明:  无
*返回值:                *
*    0 ; 表示SJA1000接口正常
*    1 ; 表示SJA1000与处理器接口不正常
*
*说明:该函数用于检测CAN控制器的接口是否正常
************************************************************************/
bit   CAN_CREATE_COMMUNATION(void)
{
    unsigned char temp_data;
    bit Flag;
    REG_TEST = 0xAA;   //写入测试值
    temp_data = REG_TEST;
    if(temp_data == 0xaa)
    {
       Flag=0;                   //读测试正确
    }
    else
    {
       Flag=1;
    }
    if(!Flag)
    {
       REG_TEST = 0x55;   //写入测试值
       temp_data = REG_TEST;
       if(temp_data == 0x55)
       {
           Flag=0;    //读测试正确
           REG_TEST = 0x00;
       }
       else
       {
           Flag=1;
       }
    }
    return (Flag);
}
/************************************************************************
*函数原型:      bit   CAN_ENTRY_RETMODEL(void)                         *
*参数说明:  无                                                         *
*返回值:                                                               *
*           0 ; 表示成功进入复位工作模式                               *
*           1 ; 表示不能进入复位工作模式                               *
*                                                                      * 
*说明:      CAN控制器进入复位工作模式                                  *
************************************************************************/ 
bit   CAN_ENTRY_RETMODEL(void)
{
     bit flag;
     unsigned char ErrorCount=20;
     unsigned char temp_data = REG_MODE;
     while(ErrorCount --)
     {
          REG_MODE = temp_data|RM_MODE;
          temp_data =  REG_MODE;        
          if( (temp_data & RM_MODE) != 0)
          {
        flag=0;                               
        break;
    }
    else
    {
        flag=1;                             
    }
      }
      return(flag);
}

/************************************************************************
*函数原型:   bit CAN_QUIT_RETMODEL(void) 
*参数说明:  无     
*返回值:     
*     0 ; 表示成功退出复位工作模式 
*     1 ; 表示不能退出复位工作模式                   
*说明:   CAN控制器退出复位工作模式  
***********************************************************************/ 
bit CAN_QUIT_RETMODEL(void)
{
     bit flag;
     unsigned char ErrorCount=20;
     unsigned char temp_data = REG_MODE;
     while(ErrorCount --)
     {
          REG_MODE = temp_data&0xfe;
          temp_data = REG_MODE;     
          if((temp_data&0x01) == 0)
          {
       flag=0;          
       break;
   }
   else
   {
       flag=1;        
   }
     }
     return(flag);
}

 /*********************************************************************************
 **函数原型:  char SJASetBandRateStandard(unsigned char  BandRateSize)
 **参数说明:  BandRateSize     标准常用波特率(Kbps)    
 **     0    5
 **     1    10
 **     2    20
 **     3    40
 **     4    50
 **     5    80
 **     6    100
 **     7    125
 **     8    200
 **     9    250
 **     10     400
 **     11     500
 **     12     666
 **     13     800
 **     14     1000     
 **返回值:   
 **     0       ; 设置总线定时器成功
 **     SJA_SETBTR_ERR    ; 设置总线定时器错
 **     SJA_NOBTRSIZE     ;波特率不能设为此值
 **
 **说明:  该函数用于设定在系统晶体为16MHZ时,常用的标准波特率的值。
 **    参数BandRateSize只能为0~14,其它的值会返回SJA_NOBTRSIZE错误
 **    本函数只能用于复位模式
 ***************************************************************************************/
unsigned  char  code  SJA_BTR_CODETAB[]={
  0xbf,0xff,      //;5KBPS的预设值
  0x67,0x2f,      //;10KBPS的预设值
  0x53,0x2F,      //;20KBPS的预设值
  0x87,0xFF,      //;40KBPS的预设值
  0x47,0x2F,      //;50KBPS的预设值
  0x83,0xFF,      //;80KBPS的预设值
  0x43,0x2f,      //;100KBPS的预设值
  0x03,0x1c,      //;125KBPS的预设值
  0x81,0xfa,      //;200KBPS的预设值
  0x01,0x1c,      //;250KBPS的预设值
  0x80,0xfa,      //;400KBPS的预设值
  0x00,0x1c,      //;500KBPS的预设值
  0x80,0xb6,      //;666KBPS的预设值
  0x00,0x16,      //;800KBPS的预设值
  0x00,0x14     //;1000KBPS的预设值
};
bit CAN_SET_BANDRATE(unsigned char CAN_ByteRate)
{
    bit ErrorFlag =1;
    unsigned char temp_data;   
    unsigned char ErrorCount = 0x20;     //32次报错
    if(CAN_ByteRate>14)
    {
        ErrorFlag =1;
    }
    else{
        while(--ErrorCount)
        {
             REG_BTR0 = SJA_BTR_CODETAB[CAN_ByteRate*2];
             REG_BTR1 = SJA_BTR_CODETAB[CAN_ByteRate*2+1];
             temp_data = REG_BTR0;
             if(temp_data != SJA_BTR_CODETAB[CAN_ByteRate*2])
             {
                  continue;
             }
             temp_data = REG_BTR1;
             if(temp_data != SJA_BTR_CODETAB[CAN_ByteRate*2+1])
             {
           continue;
             }
             ErrorFlag=0;
             break;
         }//while结束
   
     }
     return  ErrorFlag ;
}

/*************************************************************************
*函数原型: CAN_SET_OBJECT    
*参数说明:      
*    CAN_ACR0-3:存放验收代码寄存器(ACR)的参数设置
*    CAN_AMR0-3:存放接收屏蔽寄存器(AMR)的参数设置
*返回值:     
*     0 ;通信对象设置成功  
*     1 ;通信对象设置失败  
*说明:设置CAN节点的通讯对象,允许接收的报文ID号
*  允许接收的报文,是由AMR和ACR共同决定的.
*    满足以下条件的ID号的报文才可以被接收  
*[(ID.29-ID.0)≡(AC.29-AC.0)]||(AM.29-AM.0)≡11111111  
*    该子程序只能用于复位模式                                 *    
*************************************************************************/
bit CAN_SET_OBJECT(unsigned char  CAN_ACR0,unsigned char  CAN_ACR1,
                   unsigned char  CAN_ACR2,unsigned char  CAN_ACR3,
                   unsigned char  CAN_AMR0,unsigned char  CAN_AMR1,
                   unsigned char  CAN_AMR2,unsigned char  CAN_AMR3)
{
     bit ErrorFlag =1;
     unsigned char temp_data;   
     unsigned char ErrorCount = 0x20;     //32次报错
     while(ErrorCount--)
     {
          REG_ACR0 = CAN_ACR0;
          REG_ACR1 = CAN_ACR1;
          REG_ACR2 = CAN_ACR2;
          REG_ACR3 = CAN_ACR3;
          REG_AMR0 = CAN_AMR0;
          REG_AMR1 = CAN_AMR1;
          REG_AMR2 = CAN_AMR2;
          REG_AMR3 = CAN_AMR3;

          temp_data = REG_ACR0; 
          if(temp_data!= CAN_ACR0)    //校验写入值
          {
               continue;
          }
          temp_data = REG_ACR1;
          if(temp_data!= CAN_ACR1)    //校验写入值
          {
        continue;
          }
          temp_data = REG_ACR2;
          if(temp_data != CAN_ACR2)    //校验写入值
          {
        continue;
          }
          temp_data = REG_ACR3;
          if(temp_data != CAN_ACR3)    //校验写入值
          {
    continue;
          }
          temp_data = REG_AMR0;
          if(temp_data != CAN_AMR0)    //校验写入值
          {
      continue;
          }
          temp_data = REG_AMR1;
          if(temp_data != CAN_AMR1)    //校验写入值
          {
  continue;
          }
          temp_data = REG_AMR2;
          if(temp_data != CAN_AMR2)    //校验写入值
          {
  continue;
          }
          temp_data = REG_AMR3;
          if(temp_data != CAN_AMR3)    //校验写入值
          {
                continue;
          }
          ErrorFlag =0;
          break;
     }
     return ErrorFlag;
}
/************************************************************************
*函数原型: bit CAN_SET_OUTCLK(unsigned char Out_Control,unsigned char Clock_Out);   
*参数说明:                 
*    Out_Control:存放输出控制寄存器 (OCR)的参数设置
*    Clock_Out:存放时钟分频寄存器 (CDR) 的参数设置
*                      
*返回值:                
*     0 ;设置成功                 
*     1 ;设置失败                
*                       
*说明:设置SJA1000的输出模式和时钟分频 。该子程序只能用于复位模式                                   *    
************************************************************************/
bit  CAN_SET_OUTCLK (unsigned char Out_Control,unsigned char  Clock_Out)
{  
     bit ErrorFlag =1;
     unsigned char temp_data;  
     unsigned char ErrorCount = 0x20;     //32次报错
     while(ErrorCount--)
     {
         REG_OCR = Out_Control;
         REG_CDR = Clock_Out;
         temp_data = REG_OCR;
         if(temp_data != Out_Control)    //校验写入值
         {
              continue;
         }
         temp_data = REG_CDR;
         if(temp_data != Clock_Out)    //校验写入值
         {
               continue;
         }
         ErrorFlag =0;
         break;
     }
     return ErrorFlag;
}
/************************************************************************
*函数原型:   bit SJA_Init(void)   
*参数说明:  无      
*返回值:      
*     0 ; 表示初始化CAN成功   
*     1 ; 表示不能初始化CAN   
*   不同的要求需要修改    
*说明:   初始化CAN控制器波特率 分频和输出方式 ACK AMR等
***********************************************************************/ 
void SJA_Init(void)
{
        unsigned char temp_data;
        bit flag;
        delay(125);
        SJARst = 0;
        delay(125);
        SJARst = 1;
        delay(125);

        //write 0xaa 0x55 to REG_TEST
        flag = CAN_CREATE_COMMUNATION();
        if(flag)
        {
             ERR_flag = hard_ERR;
             goto EXIT;
        }

        flag = CAN_ENTRY_RETMODEL();
        if(flag)   //复位模式中
        {
             ERR_flag = Init_ERR;
             goto EXIT;
        }

        flag = CAN_SET_BANDRATE(ByteRate_500k);
        if(flag)
        {
             ERR_flag = Init_ERR;
             goto EXIT;
        }
        flag = CAN_SET_OUTCLK(0x1a,0xc8);
        if(flag)  //输出正常模式  推免方式 TX0
        {         //CDR.7=1 pelican模式 CDR.6=1只有RX0被激活 关clockout
            ERR_flag = Init_ERR;
            goto EXIT;
        }
   
        REG_RBSA = 0x00;

        //ACR and AMR
        flag = CAN_SET_OBJECT(0x20,0x20,0x20,0x20,0x00,0x00,0x00,0x00);
        if(flag)
        {
             ERR_flag = Init_ERR;
             goto EXIT;
        }

        REG_IR_ABLE = 0x89;   //中断使能


        //REG_MODE = 0x0c;  //mod.2=1进入自接收模式 mod.3选择单个验收滤波器(32bit)
        REG_MODE = AFM_MODE;
        REG_MODE = AFM_MODE;    //mod.2=0正常模式 mod.3选择单个验收滤波器(32bit)
        flag = CAN_QUIT_RETMODEL();
        if(flag)
        {
            ERR_flag = Init_ERR;
            goto EXIT;
        }

        delay(100);
        CAN_node_ID();
        Rx_node_Num();
EXIT:   return ;
}

/************************************************************************
*函数原型:  bit  Rx_node_Num( )                               
*参数说明:  no                                           
*返回值:                             
*    此函数可以根据用户需在更改和删除              
*说明:配置CAN控制器接收缓冲器情况 
************************************************************************/
void Rx_node_Num()
{        // 如果RX信息计数器为空则LED0亮
        unsigned char temp_Num;
        temp_Num = REG_Receive_Counter;
        if(temp_Num == 0)
        {
                LED0 = OFF;
        }
        else LED0 = ON;
        return ;
}

/************************************************************************
*函数原型:  can_test( )                               
*参数说明:  no                                           
*返回值:                             
*   此函数可以根据用户需在更改和删除              
*说明:只用于硬件测试,全部CAN配置在内,只用此函数只可测试节点情况 
************************************************************************/
void can_test(void)
{
        unsigned char temp_data;
        temp_data = REG_SR;
        if((temp_data & DOS_SR) == DOS_SR)       //数据溢出状态
        {
              REG_CMD |= 0x0c;             //clear over status and realve RX_FIFO
              REG_CMD |= 0x0c;
        }
        if((temp_data & TBS_SR) == TBS_SR)      //发送缓冲区状态  1释放
        {
              REG_RxBuffer0 = 0x88;         //EFF 标准帧SFF,长度为8
//              REG_RxBuffer1=0x00;
//              REG_RxBuffer2=0x00;
//              REG_RxBuffer3=0x00;
//              REG_RxBuffer4=0x08;        //ID.4-ID.0 and bit2~0 no use

              REG_DataBuffer1 = 'x';
              REG_DataBuffer2 = 'i';
              REG_DataBuffer3 = 'a';
              REG_DataBuffer4 = 'o';
              REG_DataBuffer5 = 'z';
              REG_DataBuffer6 = 'h';
              REG_DataBuffer7 = 'a';
              REG_DataBuffer8 = 'o';
        }
        CAN_cmd(TR_CMD);               //TX request 请求
        temp_data = REG_SR;
        temp_data &= TBS_SR;              //TX buffer status 发送状态
        while(temp_data == TBS_SR)        //检查是否发送完成
        {
              ecc = REG_ECC;
              temp_data = REG_SR;
              temp_data &= 0X20;
         }
}
/************************************************************************
*函数原型:  Rx_Data( )                               
*参数说明:  no                                           
*返回值:                             
*  设置不同的缓冲区需修改不同的接收缓冲变量              
*说明:   定义了Rx_buffer缓冲区
************************************************************************/
void Rx_Data()
{
        unsigned char temp_data;
        temp_data = REG_SR;
        F0 = 1;
        if((temp_data & RBS_SR) == 0)        //RBS Rx buffer status  1-RXFIFO have message
        {
             goto EXIT1;
        }
        Rx_buffer.dlen = REG_RxBuffer0;   //node message
        temp_data = Rx_buffer.dlen;

        Rx_buffer.did1 = REG_RxBuffer1;   //node message ID
        Rx_buffer.did2 = REG_RxBuffer2;
        Rx_buffer.did3 = REG_RxBuffer3;
        Rx_buffer.did4 = REG_RxBuffer4;

        temp_data = Rx_buffer.dlen;
        if( (temp_data & 0x40) == 0x00)
        {
             Rx_buffer.ddata[0] = REG_DataBuffer1;  //message data
             Rx_buffer.ddata[1] = REG_DataBuffer2;
             Rx_buffer.ddata[2] = REG_DataBuffer3;
             Rx_buffer.ddata[3] = REG_DataBuffer4;
             Rx_buffer.ddata[4] = REG_DataBuffer5;
             Rx_buffer.ddata[5] = REG_DataBuffer6;
             Rx_buffer.ddata[6] = REG_DataBuffer7;
             Rx_buffer.ddata[7] = REG_DataBuffer8;
             F0 = 0;
        }
        //F0 = 0;                                 //realve Rx buffer succefe
        CAN_cmd(RRB_CMD);                       //send realve commd to SJA1000
EXIT1:  return;
}
/************************************************************************
*函数原型:  bit  CAN_node_ID( )                               
*参数说明:  no                                           
*返回值:                             
*    此函数可以根据用户需在更改              
*说明:配置CAN控制器识别符ID,为了便于测试配置REG_CAN_TXBUF3为开关ID 
************************************************************************/
void CAN_node_ID(void)
{
        unsigned char idata temp_data;
        P1 = 0xf8;
        temp_data = P1;
        temp_data = (temp_data >> 3);
        if( (temp_data & 0x1F) > 0x09 )
        {
                temp_data = (temp_data & 0x1F) + 0x37;
        }
        else temp_data = (temp_data & 0x0F) + 0x30;
        REG_TxBuffer0 = 0x80;      //frame is EFF  data leng is 0
        REG_TxBuffer1 = 0x00;
        REG_TxBuffer2 = 0x00;
        REG_TxBuffer3 = temp_data;
        REG_TxBuffer4 = 0x00;    //ID.4-ID.0 and bit2~0 no use
}
/************************************************************************
*函数原型:  Tx_data( )                               
*参数说明:  no                                           
*返回值:                             
*    此函数可以根据用户需在更改             
*说明:由全局变量Tx_buffer作缓冲,接收CAN读出的信息. 
************************************************************************/
void Tx_data()
{
        unsigned char temp_data;
        temp_data = REG_SR;
        F0 = 1;
        if( (temp_data & TCS_SR) == 0)
        {
              ERR_flag = no_TCS;
              goto EXIT2;
        }
        if( (temp_data & TBS_SR)== TBS_SR )    //Tx buffer is  empty?
        {
              REG_TxBuffer0 |= (Tx_buffer.dlen & 0x0F);       //EFF 标准帧SFF,长度为8

              REG_DataBuffer1 = Tx_buffer.ddata[0];
              REG_DataBuffer2 = Tx_buffer.ddata[1];
              REG_DataBuffer3 = Tx_buffer.ddata[2];
              REG_DataBuffer4 = Tx_buffer.ddata[3];
              REG_DataBuffer5 = Tx_buffer.ddata[4];
              REG_DataBuffer6 = Tx_buffer.ddata[5];
              REG_DataBuffer7 = Tx_buffer.ddata[6];
              REG_DataBuffer8 = Tx_buffer.ddata[7];
              CAN_cmd(TR_CMD);       //TR=1
              F0 = 0;
         }
         else  ERR_flag = no_TBS;
EXIT2:   return ;
}

/************************************************************************
*函数原型:  bit  CAN_cmd( )                               
*参数说明:  no                                           
*返回值:                             
*    此函数可以根据用户需在更改和删除              
*说明:     写命令操作 
************************************************************************/
void CAN_cmd(unsigned char cmd)
{
        REG_CMD = cmd;
}

/************************************************************************
*函数原型:  SJA_ERR( )                               
*参数说明:  no                                           
*返回值:                             
*    此函数可以根据用户需在更改和删除              
*说明:仿真时可以知道出象牙在哪里,也呆增加其他显示作错误提示
************************************************************************/
void SJA_ERR(void)
{
       unsigned char bdata temp_data;
       temp_data = ERR_flag;
       if( (ERR_flag & hard_ERR) == hard_ERR)  //硬件错误进入死循环
       {
             while(1);
       }
       ERR_flag = temp_data;
       while( (ERR_flag & Init_ERR) == Init_ERR ) //初始化错误一直等到初始化完功
       {
             SJA_Init();
             ERR_flag = temp_data;
       }
}

关键字:SJA1000  C51 引用地址:SJA1000+C51

上一篇:C语言在8051单片机上的扩展
下一篇:STC12C2052AD 系列单片机的看门狗

推荐阅读最新更新时间:2024-03-16 15:05

使用C51实现PID算法
真正要用PID算法的时候,发现书上的代码在我们51上来实现还不是那么容易的事情。简单的说来,就是不能直接调用。仔细分析你可以发现,教材上的、网上现行的PID实现 的C语言代码几乎都是用浮点型的数据来做的,可以想象,如果我们的计算使用浮点数据,那我们的51单片机来运行的话会有多痛苦。 所以,本人自己琢磨着弄了一个整型变量来实现了PID算法,由于是用整型数来做的,所以也不是很精确,但是对于很多的使用场合,这个精度也够了。关于系数 和采样电压全部是放大10倍处理的。所以精度不是很高,但是也不是那么低,大部分的场合都够用了。实在觉得精度不够,可以再放大10倍或者100倍处理, 但是要注意不超出整个数据类型的范围就可以了。 本人做的
[单片机]
TLC549模数转换C51程序
/******************************************* 程序功能:将采集的模拟量数据转换为数字量数据, 并在P2口的流水灯上体现出来。 涉及芯片:TLC549 ********************************************/ #include reg52.h #define uint unsigned int #define uchar unsigned char sbit clock=P3^3;//时钟线 sbit dout=P3^4;//数据输出端 sbit cs=P3^5;//片选(低电平有效) void delay(uint t) { while(t
[单片机]
C51编程10-I/O口综合练习
I/O口综合实践项目 1)矩阵键盘键盘的每一个按键,进行编码键值码(1~16); 2)单片将对应的键值码转换为数码管编码; 3)数码管持续显示键值码(0~15); 4)按下按键,释放按键后,持续持续显示键值码,直到下一次按键被按下为止。 软件系统框图如下: 功能需求分析: 按下按键,释放按键后,持续持续显示键值码,直到下一次按键被按下为止。当按键被按下,才会产生键值码,当手释放后,键值码为0。如果需要按下按键后释放,还有显示,需要将数据保存起来。 由于键值码最多只有两位数,因此建立以下的一维数组进行数组储存键值码。 uchar table2 ={0,0}; 新增inputNum
[单片机]
<font color='red'>C51</font>编程10-I/O口综合练习
KeilC51使用详解 (二)
第三章 Keil C51 vs 标准C 深入理解并应用C51对标准ANSIC的扩展是学习C51的关键之一。因为大多数扩展功能都是直接针对8051系列CPU硬件的。大致有以下8类:l 8051存储类型及存储区域l 存储模式l 存储器类型声明l 变量类型声明l 位变量与位寻址l 特殊功能寄存器(SFR)l C51指针l 函数属性具体说明如下(8031为缺省CPU)。 第一节 Keil C51扩展关键字 C51 V4.0版本有以下扩展关键字(共19个):_at_ idata sfr16 alien interrupt smallbdata large _t
[单片机]
C51单片机 写一个外部中断(入门单片机)
代码部分 void main() { /*---------------EA,IT,EX必须写-------------*/ EA=1; //开启总中断 IT1=1; //中断触发模式 //=0为低电平触发,=1为下降沿触发 EX1=1; //外部中断允许位 while(1) { led1=0; } } void int1() interrupt 0 { led=~led1; } 解释: 1.外部中断(按键中断)最最重要的部分就是EA,IT,EX三条语句,这三条是必不可少的。 2.EA是中断总开关,类似家里电闸的总闸,总闸
[单片机]
<font color='red'>C51</font>单片机 写一个外部中断(入门单片机)
C51中断讲解
一、中断的概念 CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生);CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务);待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断 。 引起CPU中断的根源,称为中断源。中断源向CPU提出的中断请求。CPU暂时中断原来的事务A,转去处理事件B。对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。实现上述中断功能的部件称为中断系统。 随着计算机技术的应用,人们发现中断技术不仅解决了快速主机与慢速I/O设备的数据传送问题,而且还具有如下优点: 分时操作。CPU可以分时为多个I/O
[单片机]
<font color='red'>C51</font>中断讲解
C51单片机外部中断的触发方式
1. 电平触发方式 ○ CPU采样外部中断引脚电平 ○ 低电平,则硬件置1(IE=1) ○ 高电平,则硬件清0(IE=0) ○ 外部中断引脚的低电平要一直保持,直到CPU响应外部中断 ○ CPU响应中断后,会硬件将IE清0(IE=0),但是不会取消掉外部中断引脚的低电平,因此需要硬件加软件清除低电平(p133) 2. 下降沿触发方式 ○ CPU采样外部中断的引脚电平 ○ 如果上一个机器周期电平为高,下一个机器周期电平为低,则硬件置1(IE=1) ○ 等待CPU响应中断 ○ CPU响应中断,硬件清0(IE=0)
[单片机]
<font color='red'>C51</font>单片机外部中断的触发方式
深入理解C51对标准ANSIC的扩展
深入理解并应用C51对标准ANSIC的扩展是学习C51的关键之一。因为大多数扩展功能都是直接针对8051系列CPU硬件的。大致有以下8类: 8051存储类型及存储区域 存储模式 存储器类型声明 变量类型声明 位变量与位寻址 特殊功能寄存器(SFR) C51指针 函数属性   具体说明如下(8031为缺省CPU)。 第一节 Keil C51扩展关键字 C51 V4.0版本有以下扩展关键字(共19个): _at_ idata sfr16 alien interrupt small bdata large _task_ Code bit pdata using reentrant xdata compact sbi
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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