博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AT24C02使用详解
阅读量:6494 次
发布时间:2019-06-24

本文共 5602 字,大约阅读时间需要 18 分钟。

---恢复内容开始---

这篇文章是写给一个学弟看的,关于IIC,关于24C02的单字节写入\读取..页写入和读取,,学弟总是害怕协议,,,我总是对人家说,本来就这样的,协议就是人家这样规定的,,,如果你早生几十年你也可能规定个IIC协议......

我的单片机和24C02通信,,,我的单片机就叫主机,,,24C02叫从机

先看IIC

 

IIC协议规定开始传输数据的时候要先发一个起始信号,,,目的应该是告诉从机要开始通信了,准备准备

终止信号就是拜拜啦,再见!

起始信号就是 在SCL在高电平期间SDA来一个下降沿,,终止信号就是在SCL在高电平期间SDA来一个上升沿(所以协议上才会说,在正常传输数据的时候,只有在SCL为低电平的时候,数据线SDA的高低电平状态才允许改变,要不然岂不是和起始信号或者终止信号冲突了)

 

/*******************************************************************                     起动总线函数               函数原型: void  Start_I2c();  功能:     启动I2C总线,即发送I2C起始条件.  ********************************************************************/void Start_I2c(){  SDA=1;         /*发送起始条件的数据信号*/  _Nop();  SCL=1;  _Nop();        /*起始条件建立时间大于4.7us,延时*/  _Nop();  _Nop();  _Nop();  _Nop();      SDA=0;         /*发送起始信号*/  _Nop();        /* 起始条件锁定时间大于4μs*/  _Nop();  _Nop();  _Nop();  _Nop();         SCL=0;       /*钳住I2C总线,准备发送或接收数据 */  _Nop();  _Nop();}

 

void Stop_I2c(){  SDA=0;      /*发送结束条件的数据信号*/  _Nop();       /*发送结束条件的时钟信号*/  SCL=1;      /*结束条件建立时间大于4μs*/  _Nop();  _Nop();  _Nop();  _Nop();  _Nop();  SDA=1;      /*发送I2C总线结束信号*/  _Nop();  _Nop();  _Nop();  _Nop();}

 

 

发送完起始信号就能传输数据了

下面是程序

void  SendByte(unsigned char  c){    unsigned char  BitCnt;    //SCL=0; 起始信号最后是SCL=0;所以不用写了    for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/    {      if((c<

现在说一下接收,,,假设上面发送完0xaa以后,从机就返回给我们数据(11001100, 0xcc),当然SCL为低电平的时候模块准备数据,,SCL为高电平的时候,从机就把数据放在了SDA上,这样循环8次,一个8位数据就过来了

 整体上应该是

Start_I2c();起始信号程序

SendByte(0xaa);

判断下ack是不是等于1,应答了(是继续执行还是停止看自己了)

Data = RcvByte();//接收数据

Ack_I2c(1);//发送非应答,就是SDA=1;,这个程序在下面

Stop_I2c();发送停止信号

 接收程序如下

unsigned char   RcvByte(){  unsigned char  retc;  unsigned char  BitCnt;    retc=0;   SDA=1;                     /*置数据线为输入方式*/  for(BitCnt=0;BitCnt<8;BitCnt++)    {        _Nop();                   SCL=0;                  /*置时钟线为低,准备接收数据位*/        _Nop();        _Nop();                 /*时钟低电平周期大于4.7μs*/        _Nop();        _Nop();        _Nop();        SCL=1;                  /*置时钟线为高使数据线上数据有效*/        _Nop();        _Nop();        retc=retc<<1;        if(SDA==1)retc=retc+1;  /*读数据位,接收的数据位放入retc中 */        _Nop();        _Nop();     }  SCL=0;      _Nop();  _Nop();  return(retc);}

 

 应答或者非应答程序如下

 

/********************************************************************                     应答子函数函数原型:  void Ack_I2c(bit a);功能:      主控器进行应答信号(可以是应答0或非应答1信号,由位参数a决定)********************************************************************/void Ack_I2c(bit a){  if(a==0)SDA=0;              /*在此发出应答或非应答信号 */  else SDA=1;  _Nop();  _Nop();  _Nop();        SCL=1;  _Nop();  _Nop();                    /*时钟低电平周期大于4μs*/  _Nop();  _Nop();  _Nop();    SCL=0;                     /*清时钟线,钳住I2C总线以便继续接收*/  _Nop();  _Nop();    }

IIC其实就这样了,主要看支持IIC通信的芯片的资料了,写好这些就是IIC通用的了

资料链接

现在看芯片资料如何写进去一个字节

关于器件的地址

写就是0xa0;;;;读就是0xa1

所以写函数就是

 

/*** @brief  向24C02写数据* @param  Data--数据* @param  Address--地址* @param  None* @retval None* @example **/unsigned char WriteData(unsigned char Data,unsigned char Address){    Start_I2c();    SendByte(0xa0);//最后一位为0写入    if(ack==0)return(0);        SendByte(Address);              //发送地址    if(ack==0)return(0);        SendByte(Data);              //发送数据    if(ack==0)return(0);        Stop_I2c();               //结束总线    return(1);}

关于应答哈我的SendByte(unsigned char  c)函数里面发送完8位数据后就写了应答,然后把应答标志给ack,,后面直接判断的ack

现在想想为什么叫应答...直接说判断从机正没正确接收到数据就完了呗,就是把SDA拉高,然后把SCL拉高,等一会然后判断SDA引脚有没有被从机拉低,拉低了就说明好了......没拉低从机可能接收的数据不正确

 _Nop();

 _Nop();
 SDA=1;                /*8位发送完后释放数据线,准备接收应答位*/
 _Nop();
 _Nop();  
 SCL=1;
 _Nop();
 _Nop();
 _Nop();
 if(SDA==1)/*判断是否接收到应答信号*/
  ack=0;//没有接收到应答信号    
 else
  ack=1;//接收到应答信号       
 SCL=0;
 _Nop();
 _Nop();
}

 

再看从任意地址读一个数据

注意哈第一个发送的器件地址是0xa0,后面的是0xa1

所以程序如下

 

/*** @brief  从24C02读出数据* @param  None* @param  Address--地址* @param  None* @retval 读到的数据* @example **/unsigned char ReadData(unsigned char Address){    unsigned char Data =0;        Start_I2c();    SendByte(0xa0);//最后一位为0    if(ack==0)return(0);        SendByte(Address);              //发送地址    if(ack==0)return(0);        Start_I2c();        SendByte(0xa1);//最后一位为1    if(ack==0)return(0);        Data  = RcvByte();    Ack_I2c(1);           //发送非就答位    Stop_I2c();          //结束总线    return(Data);}

现在看页写

把程序先放上,对了写的时候的开始地址最好是0,8,16,24,32,40,68,,,,8的倍数,要不然数据可能有错误,当然我用的芯片页写最多一次能写入8个字节.....感觉有点少哈......可以在现在的基础上再做一个函数实现哈,,或者用写单字节的for循环下....

 

/*** @brief  向24C02写数据----页写,,,最多一次写入8个字节,多了会覆盖前面的* @param  Data--数据* @param  StartAddress--开始的地址--最大255* @param  None* @retval None* @example **/unsigned char PageWrite(unsigned char *Data,unsigned char Address,unsigned char cnt){    Start_I2c();    SendByte(0xa0);//最后一位为0写入    if(ack==0)return(0);        SendByte(Address);            //发送地址    if(ack==0)return(0);        while(cnt--)    {        SendByte(*Data++);          //发送数据        if(ack==0)return(0);         DelayMs(10);    }    Stop_I2c();               //结束总线    return(1);}

现在看页读

看程序

/*** @brief  从24C02读出数据----页读* @param  Data--数据指针* @param  StartAddress--开始的地址--最大255* @param  None* @retval None* @example **/unsigned char PageRead(unsigned char *Data,unsigned char Address,unsigned char cnt){    Start_I2c();    SendByte(0xa0);//最后一位为0    if(ack==0)return(0);        SendByte(Address);              //发送要读的地址    if(ack==0)return(0);        Start_I2c();        SendByte(0xa1);//最后一位为1    if(ack==0)return(0);        while(cnt--)    {        *Data  = RcvByte();        Data ++;        Ack_I2c(0);         //发送应答位        DelayMs(10);  }        Ack_I2c(1);           //发送非应答位    Stop_I2c();           //结束总线    return(1);}

 

说一下读的时候最好开始读取的地址是8的倍数,读取的数据个数也是8的倍数,,,我测试的如果不是这样有时候,第二次页读的时候就会读错........

这芯片和8干上了............

还有一个立即读,,,看明白就行,就是立即返回当前读地址加1后的那个数据

源码链接

链接:密码:r9ov

 

转载地址:http://crkyo.baihongyu.com/

你可能感兴趣的文章
关于C语言中单双引号的问题
查看>>
I00003 贝尔三角形
查看>>
HDU1200 POJ2039 ZOJ2208 UVALive3084 To and Fro【密码】
查看>>
CCF201403-1 相反数(100分)
查看>>
表单通过连接数据库数据进行验证
查看>>
redis hash操作 list列表操作
查看>>
利用Hibernate 框架,实现对数据库的增删改查
查看>>
mysql开启远程连接权限
查看>>
关于商米D1S,USB默认权限在关机后丢失的FAQ
查看>>
css3 text-transform变形动画
查看>>
scikit-learn中文api
查看>>
一个完整的大作业--广州市社会保障(市民)卡服务网
查看>>
迭代器和生成器
查看>>
STM32 内存管理实验
查看>>
python注释、脚本参数、字节码
查看>>
Vue 组件之间传值
查看>>
使用pupperlabs yum repo
查看>>
指向方法之委托(一)
查看>>
2013 Multi-University Training Contest 3 部分解题报告
查看>>
Linux 网桥配置命令:brctl
查看>>