#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
unsigned char flag,a,b[]={0,0,0,0,0},l,s[]={0,0},x[]={0},m,n;
sbit led1=P3^4;
sbit led2=P1^5;
sbit led3=P3^7;
sbit I2C_SCL = P2^1;
sbit I2C_SDA = P2^0;
/*******************************************************************************
* 函 数 名 : Delay1us()
* 函数功能 : 延时
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void I2C_Delay10us()
{
uchar a, b;
for(b=1; b>0; b--)
{
for(a=2; a>0; a--);
}
}
/*******************************************************************************
* 函 数 名 : I2C_Start()
* 函数功能 : 起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
* 输 入 : 无
* 输 出 : 无
* 备 注 : 起始之后I2C_SDA和I2C_SCL都为0
*******************************************************************************/
void I2C_Start()
{
I2C_SDA = 1;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间是I2C_SDA保持时间>4.7us
I2C_SDA = 0;
I2C_Delay10us();//保持时间是>4us
I2C_SCL = 0;
I2C_Delay10us();
}
/*******************************************************************************
* 函 数 名 : I2C_Stop()
* 函数功能 : 终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
* 输 入 : 无
* 输 出 : 无
* 备 注 : 结束之后保持I2C_SDA和I2C_SCL都为1;表示总线空闲
*******************************************************************************/
void I2C_Stop()
{
I2C_SDA = 0;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间大于4.7us
I2C_SDA = 1;
I2C_Delay10us();
}
/*******************************************************************************
* 函 数 名 : I2cSendByte(uchar num)
* 函数功能 : 通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间,
* * 保持发送信号I2C_SDA保持稳定
* 输 入 : num ,ack
* 输 出 : 0或1。发送成功返回1,发送失败返回0
* 备 注 : 发送完一个字节I2C_SCL=0, 需要应答则应答设置为1,否则为0
*******************************************************************************/
uchar I2C_SendByte(uchar dat, uchar ack)
{
uchar a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。
for(a=0; a<8; a++)//要发送8位,从最高位开始
{
I2C_SDA = dat >> 7; //起始信号之后I2C_SCL=0,所以可以直接改变I2C_SDA信号
dat = dat << 1;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间>4.7us
I2C_SCL = 0;
I2C_Delay10us();//时间大于4us
}
I2C_SDA = 1;
I2C_Delay10us();
I2C_SCL = 1;
while(I2C_SDA && (ack == 1))//等待应答,也就是等待从设备把I2C_SDA拉低
{
b++;
if(b > 200) //如果超过200us没有应答发送失败,或者为非应答,表示接收结束
{
I2C_SCL = 0;
I2C_Delay10us();
return 0;
}
}
I2C_SCL = 0;
I2C_Delay10us();
return 1;
}
/*******************************************************************************
* 函 数 名 : I2cReadByte()
* 函数功能 : 使用I2c读取一个字节
* 输 入 : 无
* 输 出 : dat
* 备 注 : 接收完一个字节I2C_SCL=0
*******************************************************************************/
uchar I2C_ReadByte()
{
uchar a = 0,dat = 0;
I2C_SDA = 1; //起始和发送一个字节之后I2C_SCL都是0
I2C_Delay10us();
for(a=0; a<8; a++)//接收8个字节
{
I2C_SCL = 1;
I2C_Delay10us();
dat <<= 1;
dat |= I2C_SDA;
I2C_Delay10us();
I2C_SCL = 0;
I2C_Delay10us();
}
return dat;
}
/*******************************************************************************
* 函 数 名 : Delay10ms
* 函数功能 : 延时函数,延时10ms
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Delay10ms(unsigned int c) //误差 0us
{
unsigned char a, b;
//--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--//
for (;c>0;c--)
{
for (b=38;b>0;b--)
{
for (a=130;a>0;a--);
}
}
}
/*******************************************************************************
* 函 数 名 : void At24c02Write(unsigned char addr,unsigned char dat)
* 函数功能 : 往24c02的一个地址写入一个数据
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void At24c02Write(unsigned char addr,unsigned char dat)
{
I2C_Start();
I2C_SendByte(0xa0, 1);//发送写器件地址
I2C_SendByte(addr, m);//发送要写入内存地址
I2C_SendByte(dat, 0); //发送数据
I2C_Stop();
}
/*******************************************************************************
* 函 数 名 : unsigned char At24c02Read(unsigned char addr)
* 函数功能 : 读取24c02的一个地址的一个数据
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
unsigned char At24c02Read(unsigned char addr)
{
unsigned char num;
I2C_Start();
I2C_SendByte(0xa0, 1); //发送写器件地址
I2C_SendByte(addr, 0x00); //发送要读取的地址
I2C_Start();
I2C_SendByte(0xa1, 1); //发送读器件地址
num=I2C_ReadByte(); //读取数据
I2C_Stop();
return num;
}
void init()
{
SCON=0x50;
PCON=0x80;
TMOD=0x20;
TH1=0xff;
TL1=0xff;
TR1=1;
EA=1;
ES=1;
}
void main ()
{
init();
while(1)
{
if(flag==1)
{
EA=0;
led1=0;
led2=0;
led3=0;
m=At24c02Read(2);
n=b[2];
At24c02Write(2,n);
flag=0;
l=0;
led1=1;
led3=1;
led2=1;
EA=1;
}
}
}
void ser()interrupt 4
{
if(RI)
{
if(l<5)
{
b[l]=SBUF;
l++;
}
RI=0;
if(l==5)
{
flag=1;
}
}
}
这是我的程序,读取24c02中 00H内容 然后把其内容当作地址 再把串口接受到的数据标b[2]写入到这个地址中。
下面为同学写的读取IIC 的一个子程序(非全部)。但是他每次读出来的和我写进去的不一样。因为他是汇编,我是C我俩都不知道哪里出了问题。
IIC_BUSY1 BIT P3.2 ; 1-- BUSY
IIC_BUSY2 BIT P3.3 ; 1-- BUSY
AZIMU_H EQU 37H ;已使用
AZIMU_L EQU 38H ;已使用
R2 EQU 39H ;
;**********************************
; READ1 READ2
;**********************************
RANDOM_READ1:
ACALL IIC_STA
MOV A,#0A0H
ACALL IIC_WRBYT
ACALL IIC_CACK
JB F0,RANDOM_READ1
ACALL IIC_STA
MOV A,#00H
ACALL IIC_WRBYT
ACALL IIC_CACK
JB F0,RANDOM_READ1
MOV AZIMU_H,A
ACALL IIC_WRBYT
ACALL IIC_CACK
JB F0,RANDOM_READ1
ACALL IIC_STOP
RET
;**********************************************
;******************IIC OPREATE*****************
;----------------------------------------------
IIC_STA:
SETB IIC_SDA
SETB IIC_SCK
NOP
NOP
CLR IIC_SDA
NOP
NOP
CLR IIC_SCK
RET
IIC_STOP:
CLR IIC_SDA
SETB IIC_SCK
NOP
NOP
SETB IIC_SDA
NOP
NOP
CLR IIC_SCK
RET
IIC_MACK:
CLR IIC_SDA
SETB IIC_SCK
NOP
NOP
CLR IIC_SCK
SETB IIC_SDA
RET
IIC_MNACK:
SETB IIC_SDA
SETB IIC_SCK
NOP
NOP
CLR IIC_SCK
CLR IIC_SDA
RET
IIC_CACK:
SETB IIC_SDA
SETB IIC_SCK
CLR F0
MOV C,IIC_SDA
JC CEND
SETB F0
CEND:
CLR IIC_SCK
NOP
RET
IIC_WRBYT:
MOV R0,#08H
WLP:
RLC A
JC WR1
SJMP WR0
WLP1:
DJNZ R0,WLP
SETB IIC_SDA
RET
WR1:
SETB IIC_SDA
SETB IIC_SCK
NOP
NOP
CLR IIC_SCK
CLR IIC_SDA
SJMP WLP1
WR0:
CLR IIC_SDA
SETB IIC_SCK
NOP
NOP
CLR IIC_SCK
SJMP WLP1
RET
IIC_RDBYT:
MOV R0, #08H
RLP:
SETB IIC_SDA
SETB IIC_SCK
MOV C,IIC_SDA
JC RD0
SJMP RD1
RLP1:
DJNZ R0,RLP
RET
RD0:
CLR C
MOV A,R2
RLC A
MOV R2,A
CLR IIC_SCK
SJMP RLP1
RD1:
SETB C
MOV A,R2
RLC A
MOV R2,A
CLR IIC_SCK
SJMP RLP1
RET
求解答。。。。。
|
|