标题:
单片机模拟I2C总线通信Proteus仿真源程序
[打印本页]
作者:
wuchx12
时间:
2020-3-6 14:45
标题:
单片机模拟I2C总线通信Proteus仿真源程序
书上关于89c52连接24C02,利用I2C总线通信实现秒表断电或复位后从新开机仍能将上次数据读取出来继续计时,书上关于I2C总线通信部分的代码用proteus模拟无法成功,我从网上找到的一个I2C_51.C和.H文件进行了改写,实现了Proteus模拟。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei图片20200306143811.png
(92.35 KB, 下载次数: 63)
下载附件
2020-3-6 14:39 上传
单片机源程序如下:
/*************************************
单片机模拟I2C总线C语言代码
*************************************/
//#include<string.h>
#include<reg52.h>
#include "I2C_51.h"
/********** Function Definition 函数定义 ***************/
void delay(uint t) /*延时函数*/
{
while(t!=0)
t--;
}
/*初始化I2C总线*****************************************/
void i2c_init()
{
scl=1;
delay(DELAY_TIME);
sda=1;
delay(DELAY_TIME);
}
/*启动I2C总线的函数,当scl为高电平时使sda产生一个负跳变*/
void i2c_start()
{
sda=1;
scl=1;
delay(DELAY_TIME);
sda=0;
delay(DELAY_TIME);
scl=0;
delay(DELAY_TIME);
}
/*终止I2C总线,当scl为高电平时使sda产生一个正跳变******/
void i2c_stop()
{
scl=0;
sda=0;
scl=1;
delay(DELAY_TIME);
sda=1;
delay(DELAY_TIME);
scl=0;
delay(DELAY_TIME);
}
/*发送0,在scl为高电平时使sda信号为低*****************/
void send_0() /* SEND ACK */
{
sda=0;
scl=1;
delay(DELAY_TIME);
scl=0;
delay(DELAY_TIME);
}
/*发送1,在scl为高电平时使sda信号为高****************/
void send_1()
{
sda=1;
scl=1;
delay(DELAY_TIME);
scl=0;
delay(DELAY_TIME);
}
/*发送完一个字节后检验设备的应答信号****************/
bit check_acknowledge()
{
sda=1;
scl=1;
delay(DELAY_TIME/2);
F0=sda;
delay(DELAY_TIME/2);
scl=0;
delay(DELAY_TIME);
if(F0==1)
return FALSE;
return TRUE;
}
/*向I2C总线写一个字节*******************************/
void write_i2c_byte(char b)
{
char i;
for(i=8;i!=0;i--){ //for(i=0;i<8;i++)
if(b&0x80)
send_1();
else
send_0();
b<<=1;
/*if((b<<i)&0x80) //原来写法
SEND_1();
else
SEND_0();*/
}
}
/*从I2C总线读一个字节******************************/
char read_i2c_byte()
{
char b=0,i;
for(i=0;i<8;i++)
{
sda=1; /*释放总线*/
scl=1; /*接受数据*/
delay(10);
F0=sda;
delay(10);
scl=0;
if(F0==1)
{
b=b<<1;
b=b|0x01;
}
else
b=b<<1;
}
return b;
}
/***************write one byte***********************************************************
功能:将ch写到地址add处 *
输入:地址add,待写字节数据ch *
输出:无 *
****************************************************************************************/
void write_byte(uchar add, uchar ch)
{
i2c_start(); //start
write_i2c_byte(0xa0); //control byte:1010+A2+A1+A0+1(write)/0(read)
while(!check_acknowledge());
write_i2c_byte(add); //address
while(!check_acknowledge());
write_i2c_byte(ch); //data
while(!check_acknowledge());
i2c_stop(); //stop
}
/***************Read one byte************************************************************
功能:从地址ch处读取一字节数据 *
输入:地址add *
输出:从地址add处读得的一字节数据 *
****************************************************************************************/
char read_byte(uchar add)
{
char b;
i2c_start(); //start
write_i2c_byte(0xa0); //control byte
while(!check_acknowledge());
write_i2c_byte(add); //address
while(!check_acknowledge());
i2c_start(); //start
write_i2c_byte(0xa1); //data
while(!check_acknowledge());
b=read_i2c_byte(); //N0 Acknowledge
// i2c_stop(); //stop 有该停止信号proteus要报错
return b;
}
/***************write string***************************************************************
功能:以add为起始地址连续写入字符串p *
输入:地址,待写字符串 *
输出:无 *
注意:字符串p的长度不需小于一页数据(24c02c的一页为16byte)。 *
数据字节临时存储在片内页缓冲器中。在主器件发送停止条件之后,这些数据将被写入存储器。*
每接收一个字,内部地址计数器加一。如果在停止条件产生前,主器件有超出一页的数据要发送,
地址计数器将会翻转,先前写入的数据将被覆盖。 *
******************************************************************************************/
/*void write_string(uchar add, uchar *p)
{
/*224C02C(2kbit),strlen(p)should<=16bit*/
/*uchar i;
i2c_start();
write_i2c_byte(0xa0);
while(!check_acknowledge());
write_i2c_byte(add);
while(!check_acknowledge());
for(i=strlen(p);i!=0;i--)
{
write_i2c_byte(*p);
while(!check_acknowledge());
p++;
}
i2c_stop();
}*/
/***************read string*************************************************************************
功能:以add为起始地址连续读len长字节数据,并通过*P返回 *
输入:地址add,读取长度len *
输出:字符串*p *
说明:连续读操作的起动过程和随机读操作相同,只是在 24XX发送完第一个数据字节后,主器件发出确认信号,*
而在随机读操作中发送的是停止条件。确认信号指示 24XX 器件发送下一个连续地址的数据字节(图 8-4)。
在24器件向主器件发送完最后一个字节后,主器件不会 产生确认信号,而是产生停止条件。 *
***************************************************************************************************/
/*void read_string(uchar add, uchar *p, uchar len)
{
i2c_start(); //start
write_i2c_byte(0xa0);
while(!check_acknowledge()); //control byte,
write_i2c_byte(add);
while(!check_acknowledge()); //address
i2c_start(); //start
write_i2c_byte(0xa1);
while(!check_acknowledge()); //data
while(len--)
{
*p=read_i2c_byte();
sda=0; //MCU发确认信号,使器件发送下一个连续地址的数据字节
scl=1;
delay(DELAY_TIME);
scl=0;
delay(DELAY_TIME);
p++;
} //读完最后一个字节不确认,停止结束
i2c_stop(); //stop
}*/
复制代码
所有资料51hei提供下载:
新建文件夹.rar
(301.46 KB, 下载次数: 48)
2020-3-6 14:45 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1