历史上的今天
返回首页

历史上的今天

今天是:2024年12月24日(星期二)

正在发生

2021年12月24日 | 51单片机实验2——I2C通信——24C01扩展实验

2021-12-24 来源:eefocus

一、实验原理:


I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。


主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件。在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;如果主机要接收从器件的数据,首先由主器件寻址从器件。然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下,主机负责产生定时时钟和终止数据传送。


二、实验电路图

三、代码详解:

“i2c.h”


#ifndef _I2C_H_

#define _I2C_H_


#include    

#include


/*定义关键字*/

#ifndef uchar      

#define uchar unsigned char 

#endif 


#ifndef uint      

#define uint unsigned int 

#endif 


sbit SCL = P3^0; 

sbit SDA = P3^1; 

sbit WP = P3^4;


/*声明函数*/

void IIC_Start(void);                   // 起始信号  

void IIC_Stop(void);                    // 停止信号  

void IIC_Asked(void);               // 应答信号  

bit IIC_WaitAsk(void);              // 等待应答  

void IIC_NonAsked(void);                // 非应答信号  

void IIC_SendByte(unsigned char Data);          // 发送一个字节  

unsigned char IIC_ReceiveByte(void);                // 接收一个字节  

void WriteToEE(unsigned char Addr,unsigned char Data);      // 写入EEPROM,24C01-08使用  

unsigned char ReadFromEE(unsigned char Addr);           // 从EEPROM读出,24C01-08使用 


#endif  


“i2c.c”


#include "i2c.h"


#define RdAddr 0xA1 // 从地址读出 AT24C01:1010A2A1A01(1010-000-1)  

#define WrAddr 0xA0 // 写入从地址 AT24C01:1010A2A1A00(1010-000-0)

unsigned char SystemError;      // I2C系统错误字


/*开始I2C相关设置 */

void Delay_us(unsigned int m) {// 延时m (us)  

  while(m > 0) {  

    _nop_();  

    m--;  

  }  

}  


void IIC_Start(void) {// 起始信号  

  EA = 0;  

  SDA = 1;  

  SCL = 1;  

  Delay_us(10);  

  SDA = 0;  

  Delay_us(10);  

  SCL = 0;  


void IIC_Stop(void) {// 停止信号  

  SCL = 0;  

  SDA = 0;  

  Delay_us(10);  

  SCL = 1;  

  Delay_us(10);  

  SDA = 1;  

  EA = 1;  


void IIC_Asked(void) {// 应答信号  

  SDA = 0;   

  Delay_us(10);  

  SCL = 1;  

  Delay_us(10);  

  SCL = 0;  


bit IIC_WaitAsk(void) {// 等待应答  

  unsigned char ErrTime = 255;// 检测次数255  

  SDA = 1;  

  Delay_us(10);  

  SCL = 1;  

  Delay_us(10);  

  while(SDA) {// 如果非应答  

    ErrTime--;// 次数减1  

    if(!ErrTime) {// 如果次数到0  

      IIC_Stop();// 停止信号  

      SystemError = 0x11;// 置系统错误字=0x11  

      return 0;// 返回0  

    }  

  }  

  SCL = 0;  

  return 1;// 如果应答,返回1  

}  


void IIC_NonAsked(void) {// 非应答  

  SDA = 1;  

  Delay_us(10);  

  SCL = 1;  

  Delay_us(10);  

  SCL = 0;  


void IIC_SendByte(unsigned char Data) {// 发送一个字节  

  unsigned char tData,i;  

  tData = Data;  

  i = 8;  

  while(i > 0) {  

    SCL = 0;  

    _nop_();  

    if((tData & 0x80) == 0x80) { SDA = 1; }  

    else    { SDA = 0; }  

    tData <<= 1;  

    Delay_us(10);  

    SCL = 1;  

    Delay_us(10);  

    i--;  

  }  

  SCL = 0;  


unsigned char IIC_ReceiveByte(void) {// 接收一个字节  

  unsigned char Data,i;  

  i = 8;  

  Data = 0x00;  

  SDA = 1;  

  while(i > 0) {  

    Data <<= 1;  

    SCL = 0;  

    Delay_us(10);  

    SCL = 1;  

    Delay_us(10);  

    if(SDA == 1) { Data |= 0x01; }  

    i--;  

  }  

  SCL = 0;  

  return Data;  


// ******* 写入EEPROM *******   

// ******* 输入:Addr 地址;Data 数据 *******   

void WriteToEE(unsigned char Addr,unsigned char Data) {  

  IIC_Start();              // 发起始信号  

  IIC_SendByte(WrAddr);     // 发写入控制字  

  IIC_WaitAsk();            // 等待应答  

  IIC_SendByte(Addr);       // 发送地址  

  IIC_WaitAsk();            // 等待应答  

  IIC_SendByte(Data);       // 发送数据  

  IIC_WaitAsk();            // 等待应答  

  IIC_Stop();               // 发停止信号  


// ******* 从EEPROM读出 *******   

// ******* 输入:Addr 地址;返回数据 *******   

unsigned char ReadFromEE(unsigned char Addr) {  

  unsigned char Data;  

  IIC_Start();              // 发起始信号  

  IIC_SendByte(WrAddr);     // 发写入控制字  

  IIC_WaitAsk();            // 等待应答  

  IIC_SendByte(Addr);       // 发送地址  

  IIC_WaitAsk();            // 等待应答  

  IIC_Start();              // 发重复起始信号  

  IIC_SendByte(RdAddr);     // 发读出控制字  

  IIC_WaitAsk();            // 等待应答  

  Data = IIC_ReceiveByte(); // 接收一个字节到Data  

  IIC_NonAsked();           // 非应答信号  

  IIC_Stop();               // 发停止信号  

  return Data;              // 返回Data  

}   


**注意:**这个工程项目中去掉应答信号函数void IIC_Asked(void)也行,因为没用上。写的目的是提供大家以后参考使用。

也因为多余了这个应答函数,因此编译时,编译器会报一个warning: SEGMENT: ?PR?IIC_ASKED?I2C。意思是有个函数声明了却未使用。但不影响实验结果。


“main.c”


#include

#include "i2c.h"


unsigned char code seg[16]=

{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

unsigned char code pos[4]=

{0xfe,0xfd,0xfb,0xf7}; 

unsigned char disbuf[4]={0,0,0,0};


unsigned char counter = 0;//定时器中断计数器

unsigned char index = 0;//地址索引 


void delay(unsigned int x) {

    unsigned char i;

    while(x--) {

        for(i=0;i<125;i++)  ;

    }

}

void display(void){

    unsigned char i; 

    for(i=0;i<4;i++){ 

        P0 = seg[disbuf[i]];   //段码

        P1 = pos[i];                //位选码

        delay(2);   

        P1=0xff;                   //消隐 

    } 


void  main(void){  

 TMOD=0x01;  

    TH0=(65536-10000)/256;

    TL0=(65536-10000)%256;

    EA=1;  

    ET0=1;  

    TR0=1;  

 WP=0;

    for(index=0;index<=0x1f;index++){// 连续写入24C01   

     WriteToEE(index,index);// index地址写入index   

     delay(9);//必须等待写周期结束 

    }

 index=0;  

 WP=1;

    while(1){ display(); } 


void timer0() interrupt 1{

 unsigned char Data=0;  

    TH0=(65536-10000)/256;

    TL0=(65536-10000)%256;

    counter++;

    if (counter==100){

        counter=0;

        Data= ReadFromEE(index);// 读出index地址数据 

     disbuf[3]=index/0x10;  //地址、数据写入显示缓冲器

     disbuf[2]=index%0x10;  

     disbuf[1]=Data/0x10; 

     disbuf[0]=Data%0x10;     

        index++; 

  if(index==0x2f){index=0;}

  }    


仿真结果:

实验结果:单片机成功将0到15这十六个数写入AT24C01的存储区中,并通过I2C总线的读取方式,将存放在AT24C01存储区的这十六个数依次读取出来并在数码管上显示出来。


上图为单片机成功写入16个数进入AT24C01存储区并依次读取数据并在数码管上显示的图片。

推荐阅读

史海拾趣

高博(GBG)公司的发展小趣事

在巩固功率MOSFET市场地位的同时,谷峰公司还积极拓展其他应用领域。公司的半导体产品广泛应用于PD快充、机器人、电动工具、LED照明、5G基站、充电桩等多个领域,满足了不同客户的多样化需求。此外,谷峰还紧跟行业发展趋势,不断推出新产品和技术解决方案,以应对市场的快速变化。这种多元化的发展策略不仅为公司带来了新的增长点,还增强了其抵御市场风险的能力。

Gem Asia Enterprise Co Ltd公司的发展小趣事

Gem Asia Enterprise最初是一家专注于电子元件生产的小型制造商。面对激烈的市场竞争,公司决定加大研发投入,专注于开发新型半导体材料。经过数年努力,Gem Asia成功研发出一种高效能、低功耗的半导体材料,并成功应用于智能手机和可穿戴设备中。这一创新不仅显著提升了产品的市场竞争力,还吸引了多家国际知名电子品牌的合作,使Gem Asia迅速在电子行业中崭露头角。

Good Will Instrument Co., Ltd.公司的发展小趣事

随着导热材料技术的不断进步,其应用领域也在不断扩展。Bergquist Company紧跟市场需求,将导热产品应用于汽车、家用电器、电脑、散热器、电源供应器及电马达控制等多个领域。这些产品的广泛应用不仅提升了人们的生活品质,还为公司的持续发展注入了强大动力。

Atlanta Micro公司的发展小趣事

作为一家技术驱动的公司,Atlanta Micro始终重视研发实力的提升。公司不断加大研发投入,引进了一批高素质的研发人才,并建立了完善的研发体系。这些举措使得公司的研发能力得到了显著提升,不断推出具有市场竞争力的新产品,为公司的发展提供了源源不断的动力。

Crameda Intersys公司的发展小趣事

随着公司业务的不断发展,Crameda Intersys公司开始寻求与行业内其他企业的战略合作。公司通过与多家知名企业建立紧密的合作关系,共同研发和推广新技术产品,成功将业务扩展到全球市场。这些战略合作不仅拓宽了公司的市场渠道,也提升了公司的品牌影响力和市场竞争力。同时,通过与合作伙伴的深入交流和学习,公司不断吸收新的技术和理念,为自身的创新和发展注入了新的活力。

和芯润德(CoreChips)公司的发展小趣事

随着技术的不断进步,和芯润德并未满足于现状。公司持续加大研发投入,积极探索新的技术领域。通过与世界领先的EDA工具提供商合作,和芯润德建立了完整的集成电路设计链,并成功研发出多款高性能、低功耗的集成电路芯片产品。这些产品在市场上获得了广泛好评,使和芯润德成为了技术创新的引领者。

问答坊 | AI 解惑

CANopen主节点的设计方案

CANopen主节点的设计方案 - 基于IXXAT公司 CANopen Master API for Windows CANopen主节点除具备CANopen设备的基本条件外,还需具备NMT Master的功能,即对CANopen网络进行管理。对CANopen主节点的实现提出三种方案: ?? 方案1:在CANopen-Chip ...…

查看全部问答>

你的第一部手机是什么型号的?

先说说我的: NOKIA 3310 像板砖一样的家伙 呵呵  不过在01年的时候也算稀罕物。 经过多次高空坠落试验,都完好无损, 后来从一个酒瓶高的容器上坠落,液晶屏里的蓝色液体流出,彻底退休了。当时在工资还不高的情况下,流的不是液晶, ...…

查看全部问答>

MAX485通信同步问题?求解???

       初次搞485的多机通信(一主多从),现在遇到的问题令我很困惑。        我的通信思路是,从机逐个与主机通信,即主机发送一帧数据(8字节,包含数据信息),呼叫从 ...…

查看全部问答>

新手提问:学习单片机需要有多少电气知识?

我大学里是学软件的,对C#之类的比较熟,C/C++也还行,汇编了解一些,电气电路和硬件几乎一点不懂。 现在有个工作是从事激光仪器里的单片机开发,请问需要学习多少电气知识?线路应该有人设计好的,我写程序要看懂电路吗?有哪里方面是要与设计电 ...…

查看全部问答>

对话框最小化就不见了。

ce5.0 evc4.2. 我要在对话框中加个最小化按钮,用ShowWindow(SW_MINIMIZE)来实现,但对话框最小化就不见了.而在xp系统中就行。 感觉是任务栏没有显示,造成最小化后程序不能回到任务栏,所以不见了。 …

查看全部问答>

一个简短程序放在AT89C55WD中好象不工作了,是否与程序有关?

问题1: 全部程序如下: #include sbit Fscx = P3^4; sbit CW   = P3^5; void main() {    int i;    CW = 0;    while(1)    {        Fscx = 1;   ...…

查看全部问答>

CE5.0大内存支持问题

CE里默认为64M,IMGRAM128=1设置后对128M支持没有问题,但是设置IMGRAM256=1之后,就不能进入系统了 所以想问一下CE里怎么添加对256M的支持,多谢!…

查看全部问答>

PCB板前期定位注意

  上周周一(6月13号)开始为一块电路板做定位工作,由于自己没有详细考虑PCB设计时的显示位置与实际模具的接口的位置关系,导致周二、三、四的布局布线工作全都白做了,实在是悲惨,只能怪自己前期考虑的不周,这也算是一次学习的机会吧 ...…

查看全部问答>

欢迎下载德仪2012年电源管理指南

这套电源管理方案指南中提供了线电源和移动设备电源的全套解决方案,而且设计目前TI最新的产品系列,对于电源方案的制定非常有参考意义。 [ 本帖最后由 wstt 于 2012-6-16 00:43 编辑 ]…

查看全部问答>

【Nucleo+BLUENRG心得】—— 验身

   今天早上刚到公司打卡看到EEWORLD寄来的快递 估计就是蓝牙板  迫不及待拆开看一下 比想象中小不少 这样可能看不出来 这样就能感觉出mini了吧 简单上个电 看下功耗 2.367mA 应该主要是有源晶振的功耗 晚 ...…

查看全部问答>