• 已解决 73482 个问题
  • 已帮助 5993 位优秀工程师

51单片机能做IIC吗?有没有列程

88f9bc38cc9d5238 2018-09-19 浏览量:1836
51单片机能做IIC吗?有没有列程
0 0 收起

我来回答

上传资料:
选择文件 文件大小不超过15M(格式支持:doc、ppt、xls、pdf、zip、rar、txt)
最佳答案
  • 可以通过IO口模拟IIC

    #include "iic.h"


    /********************************/
    /*函数名称:IICstart
    /*函数输入:无
    /*函数输出:无
    /*函数功能:IIC起始信号
    /*编写日期:2017-8-6
    /********************************/
    void IICstart() //IIC总线起始信号,在SCL为高电平时,SDA出现一个下降沿表示开始
    {
    SCL = 1; SDA = 1; delay_us(1);
    SDA = 0; delay_us(1);
    SCL = 0; delay_us(1);
    }
    /********************************/
    /*函数名称:IICstop
    /*函数输入:无
    /*函数输出:无
    /*函数功能:写数据
    /*编写日期:2017-8-6
    /********************************/
    void IICstop() //IIC总线结束信号,在SCL为高电平时,SDA出现一个上升沿表示结束
    {
    SCL = 0; SDA = 0; delay_us(1);
    SCL = 1; delay_us(1);
    SDA = 1; delay_us(1);
    }
    /********************************/
    /*函数名称:IICwrite
    /*函数输入:dat
    /*函数输出:ack
    /*函数功能:写数据
    /*编写日期:2017-8-6
    /********************************/
    bit IICwrite(uchar dat) //每写成功一位从机都要返回一个应答值(0),不成功返回费应答值(1)
    {
    bit ack;
    uchar mask; //mask为分离出dat每一位的掩码变量

    for(mask=0X80;mask!=0;mask>>=1)
    {
    SDA = mask&dat; //SDA取决于dat这正是我们想要的

    delay_us(1); SCL = 1;
    delay_us(1); SCL = 0;
    }
    SDA = 1; delay_us(1); //释放SDA,如果SDA被拉低读的数始终为0
    SCL = 1; ack = SDA; delay_us(1);
    SCL = 0;

    return ~ack; //应答位取反符合我们的日常逻辑
    }
    /********************************/
    /*函数名称:IICread
    /*函数输入:ack
    /*函数输出:dat
    /*函数功能:读数据
    /*编写日期:2017-8-6
    /********************************/
    uchar IICread(bit ack) //单片机读取数据,此时单片机为从机
    { //应答由从机给出(单片机)
    uchar dat = 0mask;

    SDA = 1;
    for(mask=0X80;mask!=0;mask>>=1)
    {
    SCL = 1; delay_us(1);
    dat |= SDA ? mask : 0;
    SCL = 0; delay_us(1);
    }
    SDA = ~ack; delay_us(1);
    SCL = 1; delay_us(1);
    SCL = 0;

    return dat; //返回读取到的数据
    }
    • 发布于 2018-09-19
    • 举报
    • 评论 0
    • 0
    • 0

其他答案 数量:21
  • 普通89c51没有iic 硬件,需要用两个io口模拟,可以做。eeprom,iic oled 小模块自带的代码就有51的
    • 发布于2018-09-19
    • 举报
    • 评论 0
    • 0
    • 0

  • 可以的,部分有硬件i2c功能,软件模拟也很好用
    • 发布于2018-09-19
    • 举报
    • 评论 0
    • 0
    • 0

  • 当然能做咯,看一下iic的时序图,用单片机的io口模拟就行了。
    • 发布于2018-09-19
    • 举报
    • 评论 0
    • 0
    • 0

  • 可以的,可以通过IO口模拟实现IIC功能
    • 发布于2018-09-19
    • 举报
    • 评论 0
    • 0
    • 0

  • I2C最早也应该是在51上实现的吧,当然支持了,现在是个单片机都可以实现I2C功能,即便没有集成硬件I2C,也能通过软件方式驱动GPIO来实现。
    • 发布于2018-09-19
    • 举报
    • 评论 0
    • 0
    • 0

  • 51没有硬件IIC但是可以模拟,这个问题前面有问过,你可以翻看之前的答案,有三种例程设计!
    • 发布于2018-09-20
    • 举报
    • 评论 0
    • 0
    • 0

  • /*******************************************************************
                         起动总线函数               
    函数原型: void  Start_I2c(void);  
    功能:     启动I2C总线即发送I2C起始条件.  
    ********************************************************************/
    void Start_I2c(void)
    {
      SDA=1;    //发送起始条件的数据信号
      delay_iic(2);//起始条件建立时间大于4.7us延时  
      SCL=1;
      delay_iic(5);//起始条件建立时间大于4.7us延时    
      SDA=0;    //发送起始信号
      delay_iic(4);//起始条件建立时间大于4us延时           
      SCL=0;    //钳住I2C总线,准备发送或接收数据
      delay_iic(4);   
    }
     
    
    /*******************************************************************
                          结束总线函数               
    函数原型: void  Stop_I2c();  
    功能:     结束I2C总线即发送I2C结束条件.  
    ********************************************************************/
    void Stop_I2c(void)
    {
      SDA=0;   //发送结束条件的数据信号
      delay_iic(5);//起始条件建立时间大于4.7us延时  
      SCL=1;   //结束条件建立时间大于4μs
      delay_iic(5);//起始条件建立时间大于4.7us延时  
      SDA=1;   //发送I2C总线结束信号
      delay_iic(5);//起始条件建立时间大于4.7us延时  
    }
    /*******************************************************************
                     字节数据发送函数               
    函数原型: void  SendByte(uchar c);
    功能:     将数据c发送出去可以是地址也可以是数据发完后等待应答并对
              此状态位进行操作.(不应答或非应答都使ack=0)     
            发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
    ********************************************************************/
    void  SendByte(uint8_t c)
    {
     uint8_t BitCnt;
     
     for(BitCnt=0;BitCnt<8;BitCnt++)  //要传送的数据长度为8位
        {
         if((c<<BitCnt)&0x80)SDA=1;   //判断发送位
           else  SDA=0;                
         delay_iic(5);//起始条件建立时间大于4.7us延时  
         SCL=1;               //置时钟线为高,通知被控器开始接收数据位
         delay_iic(5);//起始条件建立时间大于4.7us延时         
         SCL=0; 
        }
    	delay_iic(6);//起始条件建立时间大于4.7us延时  
        SDA=1;                //8位发送完后释放数据线,准备接收应答位
        delay_iic(5);//起始条件建立时间大于4.7us延时   
        SCL=1;
        delay_iic(5);//起始条件建立时间大于4.7us延时    
        if(SDA==1)ack=0;     
           else ack=1;        //判断是否接收到应答信号
        SCL=0;
        delay_iic(5);//起始条件建立时间大于4.7us延时  
    }
     
     
    
    /*******************************************************************
                     字节数据接收函数               
    函数原型: uchar  RcvByte();
    功能:     用来接收从器件传来的数据并判断总线错误(不发应答信号),
              发完后请用应答函数应答从机。  
    ********************************************************************/ 
    uint8_t  RcvByte()
    {
      uint8_t retc;
      uint8_t BitCnt;
      
      retc=0; 
      SDA=1;               //置数据线为输入方式
      for(BitCnt=0;BitCnt<8;BitCnt++)
          {         
            SCL=0;                  //置时钟线为低,准备接收数据位
            delay_iic(6);//起始条件建立时间大于4.7us延时  
            SCL=1;                  //置时钟线为高使数据线上数据有效
            delay_iic(5);//起始条件建立时间大于4.7us延时  
            retc=retc<<1;
            if(SDA==1)retc=retc+1;  //读数据位接收的数据位放入retc中
            delay_iic(5);//起始条件建立时间大于4.7us延时   
          }
      SCL=0;    
      delay_iic(5);//起始条件建立时间大于4.7us延时   
      return(retc);
    }
     
    
    /********************************************************************
                         应答子函数
    函数原型:  void Ack_I2c(bit a);
    功能:      主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
    ********************************************************************/
    void Ack_I2c(bit a)
    {
      
      if(a==0)SDA=0;           //在此发出应答或非应答信号
            else SDA=1;
      delay_iic(5);//起始条件建立时间大于4.7us延时      
      SCL=1;
      delay_iic(5);//起始条件建立时间大于4.7us延时  
      SCL=0;                     //清时钟线,钳住I2C总线以便继续接收
      delay_iic(5);//起始条件建立时间大于4.7us延时  
    }
     
    /*******************************************************************
                     用户接口函数                                   
    *******************************************************************/
    
    /*******************************************************************
                        向有子地址器件发送多字节数据函数               
    函数原型: bit  ISendStr(uchar slauchar subaucahr *suchar no);  
    功能:     从启动总线到发送地址,子地址数据,结束总线的全过程从器件
              地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
              如果返回1表示操作成功,否则操作有误。
    注意:    使用前必须已结束总线。
    ********************************************************************/
    bit ISendStr(uint8_t slauint8_t subauint8_t *suint8_t no)
    {
       uint8_t i;
       Start_I2c();               //启动总线
       SendByte(sla);             //发送器件地址
       if(ack==0)return(0);
       SendByte(suba);            //发送器件子地址
       if(ack==0)return(0);
       for(i=0;i<no;i++)
       {   
         SendByte(*s);            //发送数据
         if(ack==0)return(0);
         s++;
    	 DELAY_MS1(10);
       } 
       Stop_I2c();                //结束总线
       return(1);
    }
    /*******************************************************************
                        向有子地址器件读取多字节数据函数               
    函数原型: bit  ISendStr(uchar slauchar subaucahr *suchar no);  
    功能:     从启动总线到发送地址,子地址读数据,结束总线的全过程从器件
              地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
               如果返回1表示操作成功,否则操作有误。
    注意:    使用前必须已结束总线。
    ********************************************************************/
    bit IRcvStr(uint8_t slauint8_t subauint8_t *suint8_t no)
    {
       uint8_t i;
       Start_I2c();                  //启动总线
       SendByte(sla);                //发送器件地址
       if(ack==0)return(0);
       SendByte(suba);               //发送器件子地址
       if(ack==0)return(0);
       Start_I2c();    				//重新启动总线
       SendByte(sla+1);
       if(ack==0)return(0);
       for(i=0;i<no-1;i++)
       {   
         *s=RcvByte();               //发送数据
          Ack_I2c(0);                //发送就答位  
         s++;
    	DELAY_MS1(5);
       } 
       *s=RcvByte();
       Ack_I2c(1);                   //发送非应位
       Stop_I2c();                   //结束总线 
       return(1);
    }
    • 发布于2018-09-20
    • 举报
    • 评论 0
    • 0
    • 0

  • 51上的IIC多是使用IO口进行模拟的,没有硬件上的IIc
    • 发布于2018-09-20
    • 举报
    • 评论 0
    • 0
    • 0

  • 两个IO模拟IIC就可以了,例程网上比较多。
    • 发布于2018-09-20
    • 举报
    • 评论 0
    • 0
    • 0

  • 51单片机可以用io来模拟IIC

    • 发布于2018-09-21
    • 举报
    • 评论 0
    • 0
    • 0

  • 51单片机的IIC就是使用普通的IO口进行模拟的,只要符合IIC协议就可以正常的痛通信了,这个不难写,但是还是会花一段时间。

    下面的程序是我以前学习蓝桥杯的板子的时候写的,比较简单,是一个使用IIC写EEPROM的程序


    #include<reg52.h>
    #include<intrins.h>
    #define uchar unsigned char
    #define uint unsigned int
    sbit scl=P2^0;
    sbit sda=P2^1;
    uchar code table[]={0xc00xf90xa40xb00x990x920x820xf80x800x90};
    uchar aaccb=0;
    void yan()
    {
          _nop_();_nop_();_nop_();_nop_();_nop_();
      _nop_();_nop_();_nop_();_nop_();_nop_();
    }
    void y4()
    {  
         P2|=0xe0;
         P2&=0x80;
    }
    void y5()
    {
         P2|=0xe0;
    P2&=0xa0;
    }
    void y6()
    {
         P2|=0xe0;
    P2&=0xc0;
    }
    void y7()
    {    
         P2|=0xe0;
    P2&=0xe0;
    }
    void init()
    {
          scl=1;
      yan();
      sda=1;
      yan();
    }
    void start()
    {
         sda=1;
    yan();
    scl=1;
    yan();
    sda=0;
    yan();
    }
    void respons()
    {
        uchar i=0;
    scl=1;
    yan();
    while((sda==1)&&(i<255))
    i++;
    scl=0;
    yan();
    }
    void stop()
    {
        sda=0;
    yan();
    scl=1;
    yan();
    sda=1;
    yan();
    }
    void xsj(uchar dat)
    {
        uchar itemp;
    temp=dat;
    for(i=0;i<8;i++)
    {
       temp=temp<<1;
       scl=0;
       yan();
       sda=CY;   //单片机自动储存进CY
       yan();
       scl=1;
       yan();
    }
    scl=0;
    yan();
    sda=1;
    yan();
    }
    uchar read()
    {
         uchar ik;
    scl=0;
    yan();
    sda=1;
    for(i=0;i<8;i++)
    {
         scl=1;
    yan();
    k=(k<<1)|sda;
    scl=0;
    yan();
    }
    yan();
    return k;
    }
    void noack()
    {
       sda=1;
       yan();
       scl=1;
       yan();
       scl=0;
       yan();

    void write(uchar adduchar dat)
    {
    start();
    xsj(0xa0);
    respons();
    xsj(add);
    respons();
    xsj(dat);
    respons();
    stop();
    }

    uchar ready(uchar add)
    {
        uchar a;
    start();
    xsj(0xa0);
    respons();
    xsj(add);
    respons();
    start();
    xsj(0xa1);
    respons();
        a=read();
    stop();
    return a;
    }
    void yan1(uint i)
    {
         uchar j;
    for(;i>0;i--)
    for(j=110;j>0;j--);
    }
    void display()
    {
         y6();P0=0x01;
    y7();P0=table[b/10];
    yan1(70);
    y6();P0=0x02;
    y7();P0=table[b%10];
    }

    void main()
    {   
    TMOD=0x01;
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    EA=1;TR0=1;ET0=1;   
         init();
         b=ready(7);
    while(1)
    {
         write(7b);
    display();
    }
    }
    void DS()interrupt 1
    {
         TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    aa++;cc++; 
         if(aa==12)
       {
           aa=0;
       b++;
       if(b>=100)
       {
        b=0;
       } 
       }
       if(cc/10%2==0)
       {
       y4();P0=0x55;
       }
    }  

    • 发布于2018-09-21
    • 举报
    • 评论 0
    • 0
    • 0

  • 51没有这个模块,不过可以用引脚来模拟IIC时序
    • 发布于2018-09-21
    • 举报
    • 评论 0
    • 0
    • 0

  • 51单片机系列没有硬件IIC   都是用模拟的IIC  注意时序就行了


    • 发布于2018-09-22
    • 举报
    • 评论 0
    • 0
    • 0

  • IIC可以用模拟的方式来操作,你根据对应的时序来控制就可以
    • 发布于2018-09-23
    • 举报
    • 评论 0
    • 0
    • 0

  • 能做,用两个普通IO来模拟IIC的数据线和时钟线即可
    • 发布于2018-09-24
    • 举报
    • 评论 0
    • 0
    • 0

  • 可以的,51可以通过引脚模块I2C的时序的方式进行I2C通信,可以参考一下原子的模拟I2C代码,直接移植即可。

    • 发布于2018-09-27
    • 举报
    • 评论 0
    • 0
    • 0

  • 51没有对应的IIC模块,要用IO模拟IIC的时序进行IIC通信
    • 发布于2018-09-30
    • 举报
    • 评论 0
    • 0
    • 0

  • 51单片机可以使用IO口模拟IIC,时序并不复杂。
    • 发布于2018-10-20
    • 举报
    • 评论 0
    • 0
    • 0

相关问题

问题达人换一批

51单片机能做IIC吗?有没有列程