3个回答
展开全部
发送和接收差不多,
这里是个例子,有问题欢迎一起讨论
/*****************************************************
/* 文件名 : I2C.h
/* 描述 : I2C.c的头文件
/* 编写环境 : Keil uVision 3 V3.51
/* 作者 : XX
/* 学校 : 广东XX大学
/* Email : lanhaospider@163.com
/* 版本 : V1.0
/* 编写日期 : 2008-3-30
/* 仅供学习参考
/* 芯片 : MCS-51 AT89S52
/* 晶振 : 11.0592MHz
/* 功能描述 : 模拟I2C总线的接口程序库,主机的程序
/* 应用 : 发送n个字节: 起始位->发送控制字节(类型标识符4位->
片选3位->读写位最后1位)->应答位->数据->应答...........应答->终止位
高位先到达,低位后到达
/****************************************************/
#include "reg51.h" /*根据不同主控芯片型号改写该套入*/
#include "intrins.h"
sbit SCL = P1^6; /*定义SCL线所在口,根据实践需要改写该定义*/
sbit SDA = P1^7; /*定义SDA线所在口,根据实践需要改写该定义*/
unsigned char idata error; /*错误提示,全局变量*/
extern void Start_I2C(void);
extern void Stop_I2C(void);
extern void Ack_I2C(void);
extern void Send_Ack(void);
extern void Send_Not_Ack(void);
extern void Send_I2C(unsigned char send_byte);
extern unsigned char Receive_I2C(void);
/*****************************************************/
/* 文件名 : I2C.c
/* 描述 : I2C通信程序
/* 编写环境 : Keil uVision 3 V3.51
/* 作者 : XX
/* 学校 : 广东XX大学
/* Email : lanhaospider@163.com
/* 版本 : V1.0
/* 编写日期 : 2008-3-30
/* 仅供学习参考
/* 芯片 : MCS-51 AT89S52
/* 晶振 : 11.0592MHz
/* 功能描述 : 模拟I2C总线的接口程序库,为主机的程序
/*****************************************************/
#include "I2C.h"
/**************************************************
调用方式 : void Start_I2C(void)
函数说明: 启动I2C总线
**************************************************/
void Start_I2C(void)
{
EA = 0; /*关总中断*/
SDA = 1; /*发送启动总线的数据信号*/
SCL = 1; /*发送启动总线的时钟信号*/
_nop_(); /*保持数据线高,延时*/
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 0; /*发送起始信号*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0; /*时钟线高低跳变一次,I2C通信开始*/
}
/**************************************************
调用方式 : void Stop_I2C(void)
函数说明: 关闭I2C总线
**************************************************/
void Stop_I2C(void)
{
SCL = 0; /*发送关闭总线的时钟信号*/
SDA = 0; /*发送关闭总线的数据信号*/
_nop_();
_nop_();
_nop_(); /*保持数据线低,延时*/
_nop_();
_nop_();
SCL = 1; /*时钟线一次低高跳变,I2C通信停止*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 1; /*发送I2C总线停止数据信号*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
EA = 1; /*开总中断*/
}
/**************************************************
调用方式 : void Ask_I2C(void)
函数说明: 主控程序等待从器件接收方式应答
**************************************************/
void Ack_I2C(void)
{
unsigned char errtimes = 0xFF;
SDA = 1;
SCL = 1;
error = 0x10;
while(SDA)
{
errtimes--;
if(!errtimes)
{
Stop_I2C();
error = 0x11;
return;
}
}
SCL = 0;
}
/**************************************************
调用方式 : void Send_Ask(void)
函数说明: 主控程序为接收方,从器件为发送方时,从
器件等待主器件应答
**************************************************/
void Send_Ack(void)
{
SDA = 0; /*保持数据线低,时钟线发生一次高低跳变 发送一个应答信号*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 1; /*时钟线保持低电平*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0;
}
/**************************************************
调用方式 : void Send_Not_Ask(void)
函数说明: 主控程序为接收方,从器件为发送方时,非应答信号
**************************************************/
void Send_Not_Ack(void)
{
SDA = 1; /*保持数据线高,时钟线发生一次高低跳变 没有应答*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 1; /*时钟线保持高电平*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0;
}
/**************************************************
调用方式 : void Send_I2C(unsigned char send_byte)
函数说明: 总线发送一个字节
**************************************************/
void Send_I2C(unsigned char send_byte)
{
unsigned char send_bit;
for(send_bit = 8;send_bit <= 0;send_bit--)
{
SCL = 0;
_nop_();
SDA = (send_byte & 0x80);
send_byte<<=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
SCL = 0;
}
/**************************************************
调用方式 : unsigned char Receive_I2C(void)
函数说明: 从I2C总线上接收一个字节
**************************************************/
unsigned char Receive_I2C(void)
{
unsigned char receive_bit , receive_byte = 0;
for(receive_bit = 8;receive_bit <= 0;receive_bit--)
{
SCL = 0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
receive_byte <<=1;
receive_byte |= SDA;
}
SCL = 0;
return receive_byte;
}
这里是个例子,有问题欢迎一起讨论
/*****************************************************
/* 文件名 : I2C.h
/* 描述 : I2C.c的头文件
/* 编写环境 : Keil uVision 3 V3.51
/* 作者 : XX
/* 学校 : 广东XX大学
/* Email : lanhaospider@163.com
/* 版本 : V1.0
/* 编写日期 : 2008-3-30
/* 仅供学习参考
/* 芯片 : MCS-51 AT89S52
/* 晶振 : 11.0592MHz
/* 功能描述 : 模拟I2C总线的接口程序库,主机的程序
/* 应用 : 发送n个字节: 起始位->发送控制字节(类型标识符4位->
片选3位->读写位最后1位)->应答位->数据->应答...........应答->终止位
高位先到达,低位后到达
/****************************************************/
#include "reg51.h" /*根据不同主控芯片型号改写该套入*/
#include "intrins.h"
sbit SCL = P1^6; /*定义SCL线所在口,根据实践需要改写该定义*/
sbit SDA = P1^7; /*定义SDA线所在口,根据实践需要改写该定义*/
unsigned char idata error; /*错误提示,全局变量*/
extern void Start_I2C(void);
extern void Stop_I2C(void);
extern void Ack_I2C(void);
extern void Send_Ack(void);
extern void Send_Not_Ack(void);
extern void Send_I2C(unsigned char send_byte);
extern unsigned char Receive_I2C(void);
/*****************************************************/
/* 文件名 : I2C.c
/* 描述 : I2C通信程序
/* 编写环境 : Keil uVision 3 V3.51
/* 作者 : XX
/* 学校 : 广东XX大学
/* Email : lanhaospider@163.com
/* 版本 : V1.0
/* 编写日期 : 2008-3-30
/* 仅供学习参考
/* 芯片 : MCS-51 AT89S52
/* 晶振 : 11.0592MHz
/* 功能描述 : 模拟I2C总线的接口程序库,为主机的程序
/*****************************************************/
#include "I2C.h"
/**************************************************
调用方式 : void Start_I2C(void)
函数说明: 启动I2C总线
**************************************************/
void Start_I2C(void)
{
EA = 0; /*关总中断*/
SDA = 1; /*发送启动总线的数据信号*/
SCL = 1; /*发送启动总线的时钟信号*/
_nop_(); /*保持数据线高,延时*/
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 0; /*发送起始信号*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0; /*时钟线高低跳变一次,I2C通信开始*/
}
/**************************************************
调用方式 : void Stop_I2C(void)
函数说明: 关闭I2C总线
**************************************************/
void Stop_I2C(void)
{
SCL = 0; /*发送关闭总线的时钟信号*/
SDA = 0; /*发送关闭总线的数据信号*/
_nop_();
_nop_();
_nop_(); /*保持数据线低,延时*/
_nop_();
_nop_();
SCL = 1; /*时钟线一次低高跳变,I2C通信停止*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 1; /*发送I2C总线停止数据信号*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
EA = 1; /*开总中断*/
}
/**************************************************
调用方式 : void Ask_I2C(void)
函数说明: 主控程序等待从器件接收方式应答
**************************************************/
void Ack_I2C(void)
{
unsigned char errtimes = 0xFF;
SDA = 1;
SCL = 1;
error = 0x10;
while(SDA)
{
errtimes--;
if(!errtimes)
{
Stop_I2C();
error = 0x11;
return;
}
}
SCL = 0;
}
/**************************************************
调用方式 : void Send_Ask(void)
函数说明: 主控程序为接收方,从器件为发送方时,从
器件等待主器件应答
**************************************************/
void Send_Ack(void)
{
SDA = 0; /*保持数据线低,时钟线发生一次高低跳变 发送一个应答信号*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 1; /*时钟线保持低电平*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0;
}
/**************************************************
调用方式 : void Send_Not_Ask(void)
函数说明: 主控程序为接收方,从器件为发送方时,非应答信号
**************************************************/
void Send_Not_Ack(void)
{
SDA = 1; /*保持数据线高,时钟线发生一次高低跳变 没有应答*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 1; /*时钟线保持高电平*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0;
}
/**************************************************
调用方式 : void Send_I2C(unsigned char send_byte)
函数说明: 总线发送一个字节
**************************************************/
void Send_I2C(unsigned char send_byte)
{
unsigned char send_bit;
for(send_bit = 8;send_bit <= 0;send_bit--)
{
SCL = 0;
_nop_();
SDA = (send_byte & 0x80);
send_byte<<=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
SCL = 0;
}
/**************************************************
调用方式 : unsigned char Receive_I2C(void)
函数说明: 从I2C总线上接收一个字节
**************************************************/
unsigned char Receive_I2C(void)
{
unsigned char receive_bit , receive_byte = 0;
for(receive_bit = 8;receive_bit <= 0;receive_bit--)
{
SCL = 0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
receive_byte <<=1;
receive_byte |= SDA;
}
SCL = 0;
return receive_byte;
}
展开全部
作为接收方的MCU如果仅使用仿真方式会遭遇很大麻烦,每隔5微妙左右就要抽样一下SCL和SDA,个人推荐采用带I2C的MCU,酱紫当发生I2C中断时,你根据I2C状态码就可以判定发生的情况,并据此转向对应的处理程序段。
BTW:我有类似的87C552程序
BTW:我有类似的87C552程序
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit DS=P2^2; //define interface
uint temp; // variable of temperature
uchar flag1; // sign of the result positive or negative
sbit dula=P2^6;
sbit wela=P2^7;
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
0x87,0xff,0xef};
void delay(uint count) //delay
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
///////功能:串口初始化,波特率9600,方式1///////
void Init_Com(void)
{
TMOD = 0x20;
PCON = 0x00;
SCON = 0x50;
TH1 = 0xFd;
TL1 = 0xFd;
TR1 = 1;
}
void dsreset(void) //send reset and initialization command
{
uint i;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}
bit tmpreadbit(void) //read a bit
{
uint i;
bit dat;
DS=0;i++; //i++ for delay
DS=1;i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
uchar tmpread(void) //read a byte date
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat);
}
void tmpwritebyte(uchar dat) //write a byte to ds18b20
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //write 1
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{
DS=0; //write 0
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //DS18B20 begin change
{
dsreset();
delay(1);
tmpwritebyte(0xcc); // address all drivers on bus
tmpwritebyte(0x44); // initiates a single temperature conversion
}
uint tmp() //get the temperature
{
float tt;
uchar a,b;
dsreset();
delay(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe);
a=tmpread();
b=tmpread();
temp=b;
temp<<=8; //two byte compose a int variable
temp=temp|a;
tt=temp*0.0625;
temp=tt*10+0.5;
return temp;
}
void readrom() //read the serial
{
uchar sn1,sn2;
dsreset();
delay(1);
tmpwritebyte(0x33);
sn1=tmpread();
sn2=tmpread();
}
void delay10ms() //delay
{
uchar a,b;
for(a=10;a>0;a--)
for(b=60;b>0;b--);
}
void display(uint temp) //显示程序
{
uchar A1,A2,A2t,A3,ser;
ser=temp/10;
SBUF=ser;
A1=temp/100;
A2t=temp%100;
A2=A2t/10;
A3=A2t%10;
dula=0;
P0=table[A1]; //显示百位
dula=1;
dula=0;
wela=0;
P0=0x7e;
wela=1;
wela=0;
delay(1);
dula=0;
P0=table1[A2]; //显示十位
dula=1;
dula=0;
wela=0;
P0=0x7d;
wela=1;
wela=0;
delay(1);
P0=table[A3]; //显示个位
dula=1;
dula=0;
P0=0x7b;
wela=1;
wela=0;
delay(1);
}
void main()
{
uchar a;
// Init_Com();
do
{
tmpchange();
// delay(200);
for(a=10;a>0;a--)
{ display(tmp());
}
} while(1);
}
参照一下。但注意你的开发板的接线情况,sbit dula=P2^6;
sbit wela=P2^7;是控制数码管锁存。
#define uchar unsigned char
#define uint unsigned int
sbit DS=P2^2; //define interface
uint temp; // variable of temperature
uchar flag1; // sign of the result positive or negative
sbit dula=P2^6;
sbit wela=P2^7;
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
0x87,0xff,0xef};
void delay(uint count) //delay
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
///////功能:串口初始化,波特率9600,方式1///////
void Init_Com(void)
{
TMOD = 0x20;
PCON = 0x00;
SCON = 0x50;
TH1 = 0xFd;
TL1 = 0xFd;
TR1 = 1;
}
void dsreset(void) //send reset and initialization command
{
uint i;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}
bit tmpreadbit(void) //read a bit
{
uint i;
bit dat;
DS=0;i++; //i++ for delay
DS=1;i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
uchar tmpread(void) //read a byte date
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat);
}
void tmpwritebyte(uchar dat) //write a byte to ds18b20
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //write 1
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{
DS=0; //write 0
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //DS18B20 begin change
{
dsreset();
delay(1);
tmpwritebyte(0xcc); // address all drivers on bus
tmpwritebyte(0x44); // initiates a single temperature conversion
}
uint tmp() //get the temperature
{
float tt;
uchar a,b;
dsreset();
delay(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe);
a=tmpread();
b=tmpread();
temp=b;
temp<<=8; //two byte compose a int variable
temp=temp|a;
tt=temp*0.0625;
temp=tt*10+0.5;
return temp;
}
void readrom() //read the serial
{
uchar sn1,sn2;
dsreset();
delay(1);
tmpwritebyte(0x33);
sn1=tmpread();
sn2=tmpread();
}
void delay10ms() //delay
{
uchar a,b;
for(a=10;a>0;a--)
for(b=60;b>0;b--);
}
void display(uint temp) //显示程序
{
uchar A1,A2,A2t,A3,ser;
ser=temp/10;
SBUF=ser;
A1=temp/100;
A2t=temp%100;
A2=A2t/10;
A3=A2t%10;
dula=0;
P0=table[A1]; //显示百位
dula=1;
dula=0;
wela=0;
P0=0x7e;
wela=1;
wela=0;
delay(1);
dula=0;
P0=table1[A2]; //显示十位
dula=1;
dula=0;
wela=0;
P0=0x7d;
wela=1;
wela=0;
delay(1);
P0=table[A3]; //显示个位
dula=1;
dula=0;
P0=0x7b;
wela=1;
wela=0;
delay(1);
}
void main()
{
uchar a;
// Init_Com();
do
{
tmpchange();
// delay(200);
for(a=10;a>0;a--)
{ display(tmp());
}
} while(1);
}
参照一下。但注意你的开发板的接线情况,sbit dula=P2^6;
sbit wela=P2^7;是控制数码管锁存。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询