51单片机模拟I2C总线(我见过最好的,与大家共享)

[复制链接]
446|16
 楼主 | 2019-3-31 14:36 | 显示全部楼层 |阅读模式
  1. #include<string.h>
  2.     #include<reg52.h>
  3.     #include<intrins.h>
  4.     #define DELAY_TIME 60 /*经实验,不要小于50!否则可能造成时序混乱*/
  5.     #define TRUE 1
  6.     #define FALSE 0

  7.     sbit SCL=P1^7;/*假设由P1.7和P1.6控制*/
  8.     sbit SDA=P1^6;
复制代码


使用特权

评论回复
 楼主 | 2019-3-31 14:36 | 显示全部楼层
  1. /********** Function Definition 函数定义 ************/

  2.     void DELAY(unsigned int t) /*延时函数*/
  3.     {
  4.         while(t!=0)
  5.             t--;
  6.     }
复制代码

使用特权

评论回复
 楼主 | 2019-3-31 14:37 | 显示全部楼层
  1.     void I2C_Start(void)
  2.     {
  3.         /*启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变*/
  4.         SDA=1;
  5.         SCL=1;
  6.         DELAY(DELAY_TIME);
  7.         SDA=0;
  8.         DELAY(DELAY_TIME);
  9.         SCL=0;
  10.         DELAY(DELAY_TIME);
  11.     }
复制代码

使用特权

评论回复
 楼主 | 2019-3-31 14:37 | 显示全部楼层
  1.     void I2C_Stop(void)
  2.     {
  3.         /*终止I2C总线,当SCL为高电平时使SDA产生一个正跳变*/
  4.         SDA=0;
  5.         SCL=1;
  6.         DELAY(DELAY_TIME);
  7.         SDA=1;
  8.         DELAY(DELAY_TIME);
  9.         SCL=0;
  10.         DELAY(DELAY_TIME);
  11.     }
复制代码

使用特权

评论回复
 楼主 | 2019-3-31 14:37 | 显示全部楼层
  1.    void SEND_0(void)   /* SEND ACK */
  2.     {
  3.         /*发送0,在SCL为高电平时使SDA信号为低*/
  4.         SDA=0;
  5.         SCL=1;
  6.         DELAY(DELAY_TIME);
  7.         SCL=0;
  8.         DELAY(DELAY_TIME);
  9.     }

  10.     void SEND_1(void)
  11.     {
  12.         /*发送1,在SCL为高电平时使SDA信号为高*/
  13.         SDA=1;
  14.         SCL=1;
  15.         DELAY(DELAY_TIME);
  16.         SCL=0;
  17.         DELAY(DELAY_TIME);
  18.     }
复制代码

使用特权

评论回复
 楼主 | 2019-3-31 14:38 | 显示全部楼层
  1.     bit Check_Acknowledge(void)
  2.     {
  3.         /*发送完一个字节后检验设备的应答信号*/
  4.         SDA=1;
  5.         SCL=1;
  6.         DELAY(DELAY_TIME/2);
  7.         F0=SDA;
  8.         DELAY(DELAY_TIME/2);
  9.         SCL=0;
  10.         DELAY(DELAY_TIME);
  11.         if(F0==1)
  12.             return FALSE;
  13.         return TRUE;
  14.     }
复制代码

使用特权

评论回复
 楼主 | 2019-3-31 14:38 | 显示全部楼层
  1. void WriteI2CByte(char b)reentrant
  2.     {
  3.         /*向I2C总线写一个字节*/
  4.         char i;
  5.         for(i=0;i<8;i++)
  6.             if((b<<i)&0x80)
  7.                 SEND_1();
  8.             else
  9.                 SEND_0();
  10.     }
复制代码

使用特权

评论回复
 楼主 | 2019-3-31 14:38 | 显示全部楼层
  1.     char ReadI2CByte(void)reentrant
  2.     {
  3.         /*从I2C总线读一个字节*/
  4.         char b=0,i;
  5.         for(i=0;i<8;i++)
  6.         {
  7.             SDA=1;    /*释放总线*/
  8.             SCL=1;    /*接受数据*/
  9.             DELAY(10);
  10.             F0=SDA;
  11.             DELAY(10);
  12.             SCL=0;
  13.             if(F0==1)
  14.                 {
  15.                     b=b<<1;
  16.                     b=b|0x01;
  17.                 }
  18.             else
  19.                 b=b<<1;
  20.         }
  21.         return b;
  22.     }
复制代码

使用特权

评论回复
 楼主 | 2019-3-31 14:39 | 显示全部楼层
  1. /**********以下为读写24c02的函数**********/
  2. void Write_One_Byte(char addr,char thedata)
  3. {
  4.           bit acktemp=1;
  5.           /*write a byte to mem*/
  6.           I2C_Start();
  7.           WriteI2CByte(0xa0);
  8.           acktemp=Check_Acknowledge();
  9.           WriteI2CByte(addr);/*address*/
  10.           acktemp=Check_Acknowledge();
  11.           WriteI2CByte(thedata);/*thedata*/
  12.           acktemp=Check_Acknowledge();
  13.           I2C_Stop();

  14. }
复制代码

使用特权

评论回复
 楼主 | 2019-3-31 14:39 | 显示全部楼层
  1. void Write_A_Page(char *buffer,char addr)
  2. {
  3.           bit acktemp=1;
  4.           bit wrtmp;
  5.           int i;
  6.           /*write a page to at24c02*/
  7.           I2C_Start();
  8.           WriteI2CByte(0xa0);
  9.           acktemp=Check_Acknowledge();
  10.           WriteI2CByte(addr);/*address*/
  11.           acktemp=Check_Acknowledge();
  12.           for(i=0;i<7;i++)
  13.           {
  14.             WriteI2CByte(buffer[i]);
  15.             if(!Check_Acknowledge())
  16.                 {
  17.                     I2C_Stop();

  18.                 }
  19.            }


  20.           I2C_Stop();




  21. }
复制代码

使用特权

评论回复
 楼主 | 2019-3-31 14:40 | 显示全部楼层
  1. char Read_One_Byte(char addr)
  2. {         bit acktemp=1;
  3.           char mydata;
  4.            /*read a byte from mem*/
  5.           I2C_Start();
  6.           WriteI2CByte(0xa0);
  7.           acktemp=Check_Acknowledge();
  8.           WriteI2CByte(addr);/*address*/
  9.           acktemp=Check_Acknowledge();
  10.           I2C_Start();
  11.           WriteI2CByte(0xa1);
  12.           acktemp=Check_Acknowledge();


  13.           mydata=ReadI2CByte();
  14.           acktemp=Check_Acknowledge();

  15.           return mydata;
  16.           I2C_Stop();
  17. }
复制代码

使用特权

评论回复
 楼主 | 2019-3-31 14:40 | 显示全部楼层
  1. void Read_N_Bytes(char *buffer,char n,char addr)
  2. {
  3.           bit acktemp=1;

  4.           int i=0;
  5.            /*read 8 bytes from mem*/
  6.           I2C_Start();
  7.           WriteI2CByte(0xa0);
  8.           acktemp=Check_Acknowledge();
  9.           WriteI2CByte(addr);/*address*/
  10.           acktemp=Check_Acknowledge();
  11.           I2C_Start();
  12.           WriteI2CByte(0xa1);

  13.           acktemp=Check_Acknowledge();




  14.           for(i=0;i<n;i++)
  15.           {
  16.                 buffer[i]=ReadI2CByte();
  17.                 if(i!=n-1)
  18.                     SEND_0();    /*发送应答*/
  19.                 else
  20.                     SEND_1();    /*发送非应答*/
  21.           }

  22.    I2C_Stop();

  23. }
复制代码

使用特权

评论回复
 楼主 | 2019-3-31 14:40 | 显示全部楼层
  1. void main()
  2. {
  3.           int i;
  4.           char mybyte;
  5.           char myarray[8];
  6.           char myarray2[8];
  7.           char rdarray[16];
  8.          
  9.           for(i=0;i<8;i++)
  10.           {
  11.                 myarray[i]=i;
  12.                 myarray2[i]=i+0x08;   

  13.           }

  14.           Write_One_Byte(0x20,0x28);

  15.           Write_A_Page(myarray,0x10);
  16.           Write_A_Page(myarray2,0x18);

  17.           mybyte=Read_One_Byte(0x20);
  18.           Read_N_Bytes(rdarray,16,0x10);

  19. }
复制代码

使用特权

评论回复
| 2019-4-6 16:15 | 显示全部楼层
有空看看

使用特权

评论回复
| 2019-4-15 17:26 | 显示全部楼层
good

使用特权

评论回复
| 2019-6-2 14:56 | 显示全部楼层
好的,谢谢.

使用特权

评论回复
| 2019-6-8 10:05 | 显示全部楼层
楼主啊,要是没有AT24C,单单讲I2c传送数据的功能来讲,是不是用那段Write()加上一个起始函数就可以了,包括地址位,连Read()都感觉可以没必要写。我自己的体会,希望能解答解答。

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表