基于AT24C02的多机通信

2023-12-30 21:40:50

//单片机U3对AT24C02的读取程序
#include <reg51.h> ? ? ? ? // ?包含51单片机寄存器定义的头文件
#include <intrins.h> ? ? ? //包含_nop_()函数定义的头文件
#define?? ?OP_READ?? ?0xa1?? ??? ?// 器件1地址以及读取操作,0xa1即为1010 0001B
#define?? ?OP_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_(); ? ? //等待一个机器周期
}
/***************************************************
函数功能:从AT24Cxx读取数据
出口参数:x
***************************************************/
unsigned char ReadData()
// 从AT24Cxx移入数据到MCU
{
?? ?unsigned char i;
?? ?unsigned char x; ? ? ? ? ? //储存从AT24Cxx中读出的数据
?? ?for(i = 0; i < 8; i++)
?? ?{
?? ??? ?SCL = 1; ? ? ? ? ? ? ? ?//SCL置为高电平
?? ??? ?x<<=1; ? ? ? ? ? ? ? ? ?//将x中的各二进位向左移一位
?? ??? ?x|=(unsigned char)SDA; ?//将SDA上的数据通过按位“或“运算存入x中
?? ??? ?SCL = 0; ? ? ? ? ? ? ? //在SCL的下降沿读出数据
?? ?}
?? ?return(x); ? ? ? ? ? ? ? ?//将读取的数据返回
}
/***************************************************
函数功能:向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中的当前地址读取数据
出口参数:x (储存读出的数据)?
***************************************************/
unsigned char ReadCurrent()
{
?? ?unsigned char x;
?? ?start(); ? ? ? ? ? ? ? ? ? //开始数据传递
?? ?WriteCurrent(OP_READ); ? //选择要操作的AT24Cxx芯片,并告知要读其数据
?? ?x=ReadData(); ? ? ? ? ? ? //将读取的数据存入x
?? ?stop(); ? ? ? ? ? ? ? ? ? //停止数据传递
?? ?return x; ? ? ? ? ? ? ? ? //返回读取的数据
}

/***************************************************
函数功能:从AT24Cxx中的指定地址读取数据
入口参数:set_addr
出口参数:x?
***************************************************/
unsigned char ReadSet(unsigned char set_addr)
// 在指定地址读取
{
?? ?start(); ? ? ? ? ? ? ? ? ? ? ?//开始数据传递
?? ?WriteCurrent(OP_WRITE); ? ? ? //选择要操作的AT24Cxx芯片,并告知要对其写入数据
?? ?WriteCurrent(set_addr); ? ? ? //写入指定地址
?? ?return(ReadCurrent()); ? ? ? ?//从第一个AT24Cxx芯片指定地址读出数据并返回
}
/***************************************************
函数功能:主函数
***************************************************/
main(void)
{
? SDA = 1; ? ? ? ? ? // SDA=1,SCL=1,使主从设备处于空闲状态
? SCL = 1; ?
? while(1)
?? ?{
? ? ? while(flag==1)
?? ? ? ? ? ;
?? ? ?P1=ReadSet(0x36); ? ? ? //从第二个AT24C02中的指定地址"0x36"读出数据
?? ??? ?delaynms(90);
??? ?} ??
}
?


//单片机U1对AT24C02的写入程序
#include <reg51.h> ? ? ? ? // ?包含51单片机寄存器定义的头文件
#include <intrins.h> ? ? ? //包含_nop_()函数定义的头文件
#define?? ?OP_READ?? ?0xa1?? ??? ?// 器件1地址以及读取操作,0xa1即为1010 0001B
#define?? ?OP_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;
}
?

文章来源:https://blog.csdn.net/qq_46065313/article/details/135309441
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。