技术文档

at24c02 单片机 51单片机学习30-AT24C02

小编 2024-11-24 技术文档 23 0

51单片机学习30-AT24C02

这篇讲AT24C02

实现的功能是 每次关机在开机 数码管显示的数字加1 从0到9 这样循环。实现了AT24C02存储功能。

仿真图用的是我自己做的一个51单片机开发板 图纸比较大,截图可能看不清,需要的话可以私信联系我。

/*单片机模拟I2C总线通信时,需要以下几个关键部分的程序

1.总线初始化

2.启动信号

3.应答信号

4.停止信号

5.写一个字节

6.读一个字节

7.封装一个写程序

8.封装一个读程序*/

程序:

源代码:

#include<reg52.h>

#include<intrins.h>

#define uint unsigned int

#define uchar unsigned char

sbit SCL=P2^0;

sbit SDA=P2^1;

uchar code smg_dm[]={ //数码管显示编码

0x3f,0x06,0x5b,0x4f,

0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71};

//////延时函数声明//////////

void delay_50us(uint);

void delay_10us();

/////i2c操作相关函数声明///////////

void i2c_init();

void i2c_start();

void i2c_respond();

void i2c_no_respond();

void i2c_stop();

void i2c_write_Byte(uchar dat);

uchar i2c_read_Byte();

void write_Byte(uchar add,uchar dat);

uchar read_Byte(uchar add);

//////////////////////////////////

void main()

{

uchar k;

k=read_Byte(3);

k=k%10;

P1=smg_dm[k];

k++;

write_Byte(3,k); //关机开机后数码管自加一

while(1);

}

void delay_50us(uint z) //延时子程序

{

uchar y;

for(;z>0;z--)

for(y=19;y>0;y--);

}

void delay_10us() //NOP执行一句1us 调用延时函数2us,结束调用2us一共10us

{

_nop_();_nop_(); _nop_();

_nop_(); _nop_(); _nop_();

}

void i2c_init()//总线初始化

{

SCL=1;

delay_10us();

SDA=1;

delay_10us();

}

void i2c_start()//启动信号

{

SCL=1;

delay_10us();

SDA=1;

delay_10us();

SDA=0;

delay_10us();

}

void i2c_respond()//应答信号

{

uchar i;

SCL=1;

delay_10us();

//while((SDA==1)&&(i<255));

while((SDA==1)&&(i<255))i++;//实际程序不能一直等着 当SDA变低电平或者i++超过255时

//表示没有收到从机的应答信号,而主机默认已经收到数据而不再等待

SCL=0;

delay_10us();

}

void i2c_no_respond()//非应答信号

{

SDA=1;

delay_10us();

SCL=1;

delay_10us();

SCL=0;

delay_10us();

}

void i2c_stop()//停止信号

{

SDA=0;

delay_10us();

SCL=1;

delay_10us();

//SDA=0; //原先这两句在这里程序不会执行加一,与停止信号的时序不符

//delay_10us();

SDA=1;

delay_10us();

}

void i2c_write_Byte(uchar dat)//写一个字节

{

uchar i;

SCL=0;//在时钟信号低电平期间,数据线上高地电平状态才允许变化

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

{

if(dat&0x80)//判断高位是0还是1 &单一位与运算 &&按位与 dat&&0x80 相当于dat&10000000

//传送数据高位在前 判断dat&0x80相当于dat&1 真执行if后面的语句 否则执行else后面语句

{SDA=1;} ////////////////////////////////

else ////////////////////////////////

{SDA=0;} ////////////////////////////////

dat=dat<<1;//高位在前,往左移

delay_10us();

SCL=1; //芯片会来读数据

delay_10us();

SCL=0;

delay_10us();

}

SDA=1;//释放数据线

delay_10us();

}

uchar i2c_read_Byte()//读一个字节

{

uchar i;

uchar dat;

SCL=0;//在时钟信号低电平期间,数据线上高地电平状态才允许变化

delay_10us();

SDA=1;//释放数据线

delay_10us();

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

{

SCL=1;//准备读数据

delay_10us();

dat=dat<<1;//判断8次移位7次

if(SDA)//判断SDA的电平

{ dat++; } //个位加1

SCL=0;//时钟线拉低

delay_10us();

}

return dat;

}

仿真结果:

仿真停止后,再次运行仿真

数据加1 实现了要求的功能

单片机 基于AT24C02的多机通信 写入程序

#include <reg51.h> // 包含51单片机寄存器定义的头文件

#include <intrins.h> //包含_nop_()函数定义的头文件

#defineOP_READ0xa1// 器件1地址以及读取操作,0xa1即为1010 0001B

#defineOP_WRITE 0xa0// 器件1地址以及写入操作,0xa1即为1010 0000B

sbit SDA=P3^4; //将串行数据总线SDA位定义在为P3.4引脚

sbit SCL=P3^3; //将串行时钟总线SDA位定义在为P3.3引脚

sbit flag=P3^0;

/*****************************************************

函数功能:延时1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒

***************************************************/

void delay1ms()

{

unsigned char i,j;

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

for(j=0;j<33;j++)

;

}

/*****************************************************

函数功能:延时若干毫秒

入口参数:n

***************************************************/

void delaynms(unsigned char n)

{

unsigned char i;

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

delay1ms();

}

/***************************************************

函数功能:开始数据传送

***************************************************/

void start()

// 开始位

{

SDA = 1; //SDA初始化为高电平“1”

SCL = 1; //开始数据传送时,要求SCL为高电平“1”

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

SDA = 0; //SDA的下降沿被认为是开始信号

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

SCL = 0; //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)

_nop_(); //等待一个机器周期

}

/***************************************************

函数功能:结束数据传送

***************************************************/

void stop()

// 停止位

{

SDA = 0; //SDA初始化为低电平“0”

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

SCL = 1; //结束数据传送时,要求SCL为高电平“1”

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

SDA = 1; //SDA的上升沿被认为是结束信号

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

}

/***************************************************

函数功能:向AT24Cxx的当前地址写入数据

入口参数:y (储存待写入的数据)

***************************************************/

//在调用此数据写入函数前需首先调用开始函数start(),所以SCL=0

bit WriteCurrent(unsigned char y)

{

unsigned char i;

bit ack_bit; //储存应答位

for(i = 0; i < 8; i++)// 循环移入8个位

{

SDA = (bit)(y&0x80); //通过按位“与”运算将最高位数据送到S

//因为传送时高位在前,低位在后

_nop_(); //等待一个机器周期

SCL = 1; //在SCL的上升沿将数据写入AT24Cxx

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

SCL = 0; //将SCL重新置为低电平,以在SCL线形成传送数据所需的8个脉冲

y <<= 1; //将y中的各二进位向左移一位

}

SDA = 1; // 发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)释放SDA线,

//以让SDA线转由接收设备(AT24Cxx)控制

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

SCL = 1; //根据上述规定,SCL应为高电平

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

_nop_(); //等待一个机器周期

ack_bit = SDA; //接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个字节

//若送高电平,表示没有接收到,传送异常

SCL = 0; //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)

return ack_bit;// 返回AT24Cxx应答位

}

/***************************************************

函数功能:向AT24Cxx中的指定地址写入数据

入口参数:add (储存指定的地址);dat(储存待写入的数据)

***************************************************/

void WriteSet(unsigned char add, unsigned char dat)

// 在指定地址addr处写入数据WriteCurrent

{

start(); //开始数据传递

WriteCurrent(OP_WRITE); //选择要操作的第一个AT24Cxx芯片,并告知要对其写入数据

WriteCurrent(add); //写入指定地址

WriteCurrent(dat); //向当前地址(上面指定的地址)写入数据

stop(); //停止数据传递

delaynms(4); //1个字节的写入周期为1ms, 最好延时1ms以上

}

/***************************************************

函数功能:主函数

***************************************************/

main(void)

{

TMOD=0x01;

TH0=(65536-46083)/256;

TL0=(65536-46083)%256;

EA=1;

ET0=1;

TR0=1;

flag=1;

while(1)

{

while(flag==1)

{

WriteSet(0x36,0xf0); //将数据"0xf0"写入第一个AT24C02的指定地址"0x36"

delaynms(50); //延时50ms

}

while(flag==0)

;

}

}

/***************************************************

函数功能:定时器T0的中断函数,使P3.0引脚输出100ms方波

***************************************************/

void Time0(void) interrupt 1 using 1

{

TH0=(65536-46083)/256;

TL0=(65536-46083)%256;

flag=!flag;

}

相关问答

24C02 是什么集成块-ZOL问答

24C02是一款常见的EEPROM芯片,使用I²C接口,容量为256Byte。AT24c02的SDA,SCL分别上拉5.1k电阻与单片机IO口连接EESDAEESCL接单片机的引脚。EEVC...

24c02 n芯片引脚定义?

24C02与单片机的接口非常简单E0,E1,E2为器件地址线,WP为写保护引脚,SCL,SDA为二线串行接口,符合I2C总线协议。在一般单片机系统中,24C02数据受到干扰的...

请问 24C02 是什么芯片-ZOL问答

贴片24c02有问题《,线路有问题,或程序本来就还没调试好24C01,24C04,24C08,除了容量不同,其他的一样,可以上网找一下驱动程序。EESDAEESCL接单片机的引脚。...

AT 89 C 51 单片机 主要功能有哪些啊?

AT89C51是一种带4K字节闪存可编程可擦除只读存储器(FPEROM—FlashProgrammableandErasableReadOnlyMemory)的低电压、高性能CMOS8位...

存储器EEPROM通俗叫法是什么?-ZOL问答

现在的单片机,ROM一般就是指的FlashROM,从来保存程序的,即程序存储器。EEPROM专指“可以进行字节擦除和编程”的存储器,比如28C64、24C02这样的存储器。还有...

89 c 51真的过时了吗?

89C51单片机是一款8位单片机,最常用的是艾特梅尔产的AT89C51,我在上学时是用的最多的一款单片机芯片,现在来说它早已停产多年了。我认为尽管这样,作为一种性...8...

rom ram eeprom分别肿么读-ZOL问答

现在的单片机,ROM一般就是指的FlashROM,从来保存程序的,即程序存储器。EEPROM专指“可以进行字节擦除和编程”的存储器,比如28C64、24C02这样的存储器。还有...

单片机 仿真软件中如何设置数码管与 24C 04?

这个题目看着东西多,实际上没有太大的难度。需要知道单片机如何控制数码管显示即可,其他题目中更多的是一些业务逻辑,你需要设置一个交互逻辑即可,比如通过按...

单片机 如何通过ADC模块采集模拟信号?

朋友们好,我是电子及工控技术,我来回答这个问题。众所周知单片机是一种超大规模的集成电路,它只能“读懂”并处理数字信号,对于连续量的模拟信号则无能为力。...

51 单片机 开发板有什么用,对初学 单片机 有什么帮助?

51单片机开发板对初学单片机的帮助,就像学步车对于刚学走路的儿童一样,可以帮助它少摔跤,快速学会走路。一、单片机学习板的重要性单片机的学习,包含两大方...

猜你喜欢