51单片机 I2C 24c02的单个数据读写
根据郭天祥的教程边的,但是不能运行。然后将respons改成现在的就能正确运行。求解释。/*........*/里面的是郭天祥的程序。#include<reg52.h>#...
根据郭天祥的教程边的,但是不能运行。然后将respons改成现在的就能正确运行。求解释。/*........*/里面的是郭天祥的程序。
#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit WP=P1^0;
sbit SCL=P1^1;
sbit SDA=P1^2;
void delay()
{ ;;
}
void start()
{
SCL=1;
SDA=1;
delay();
SDA=0;
delay();
}
void stop()
{
SCL=1;
SDA=0;
delay();
SDA=1;
delay();
}
void respons()
{
/* uchar i; 这是郭天祥的应答程序,不能正确运行
SCL=1;
delay();
while((SDA==1)&&(i<250))i++;
SCL=0;
delay(); */
SDA=0; 修改后的
delay();
SCL=1;
delay();
SCL=0;
delay();
}
void write_byte(uchar date)
{
uchar i,temp;
temp=date;
SDA=1;
delay();
for(i=0;i<8;i++)
{
temp=temp<<1;
SCL=0;
delay();
SDA=CY;
delay();
SCL=1;
delay();
}
SCL=0;
delay();
SDA=1;
delay();
}
uchar read_byte()
{
uchar j,k;
SDA=1;
delay();
SCL=0;
for(j=0;j<8;j++)
{
SCL=0;
delay();
SCL=1;
delay();
k=(k<<1)|SDA;
delay();
}
SCL=0;
SDA=1;
delay();
return k;
}
void init()
{
WP=0;
SCL=1;
SDA=1;
}
void write_add(uchar add, uchar date)
{
start();
write_byte(0xae);
respons();
write_byte(add);
respons();
write_byte(date);
respons();
stop();
}
uchar read_add(uchar add)
{
uchar ad;
start();
write_byte(0xae);
respons();
write_byte(add);
respons();
start();
write_byte(0xaf);
respons();
ad=read_byte();
stop();
return ad;
}
void delay1(uchar x)
{
uchar a,b;
for(a=x;a>0;a--)
for(b=100;b>0;b--);
}
void main()
{
init();
write_add(33,0x42);
delay1(100);
P0=read_add(33); 将读取的数显示在发光二极管上
while(1);
} 展开
#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit WP=P1^0;
sbit SCL=P1^1;
sbit SDA=P1^2;
void delay()
{ ;;
}
void start()
{
SCL=1;
SDA=1;
delay();
SDA=0;
delay();
}
void stop()
{
SCL=1;
SDA=0;
delay();
SDA=1;
delay();
}
void respons()
{
/* uchar i; 这是郭天祥的应答程序,不能正确运行
SCL=1;
delay();
while((SDA==1)&&(i<250))i++;
SCL=0;
delay(); */
SDA=0; 修改后的
delay();
SCL=1;
delay();
SCL=0;
delay();
}
void write_byte(uchar date)
{
uchar i,temp;
temp=date;
SDA=1;
delay();
for(i=0;i<8;i++)
{
temp=temp<<1;
SCL=0;
delay();
SDA=CY;
delay();
SCL=1;
delay();
}
SCL=0;
delay();
SDA=1;
delay();
}
uchar read_byte()
{
uchar j,k;
SDA=1;
delay();
SCL=0;
for(j=0;j<8;j++)
{
SCL=0;
delay();
SCL=1;
delay();
k=(k<<1)|SDA;
delay();
}
SCL=0;
SDA=1;
delay();
return k;
}
void init()
{
WP=0;
SCL=1;
SDA=1;
}
void write_add(uchar add, uchar date)
{
start();
write_byte(0xae);
respons();
write_byte(add);
respons();
write_byte(date);
respons();
stop();
}
uchar read_add(uchar add)
{
uchar ad;
start();
write_byte(0xae);
respons();
write_byte(add);
respons();
start();
write_byte(0xaf);
respons();
ad=read_byte();
stop();
return ad;
}
void delay1(uchar x)
{
uchar a,b;
for(a=x;a>0;a--)
for(b=100;b>0;b--);
}
void main()
{
init();
write_add(33,0x42);
delay1(100);
P0=read_add(33); 将读取的数显示在发光二极管上
while(1);
} 展开
3个回答
展开全部
写程序的时候,多注意一下芯片的资料。24C01的资料里面写的很清楚。读写必须按要求的波形来处理。我发一段我用在ST芯片的程序给你。由于IIC接口采用模拟的方式。所以,与什么芯片没有关系。你把这段程序看一下。相信你可以看懂。使用这段程序的产品已经出货几十万套产品。不会有问题。
ST芯片的端口输入输出设定比较麻烦。所以有单独的子程序来处理。
单片机IIC的SDA端口在向EEPROM(24C01)发数据时,设为输出
在读取EEPROM数据的时候则设为输入。
//-------------------------------------------
//-程序名称: Eestart
//-入口参数:无
//-出口参数:无
//-功能说明: IIC的START信号生成
//-------------------------------------------
void Eestart(void) //启动I2C总线//
{
SETSDA;
DelayNOP(STARTNOP);
SETSCL;
DelayNOP(STARTNOP);
CLRSDA;
DelayNOP(STARTNOP);
CLRSCL; ;--注意此处,很重要。总线只有SCL为低时,才允许SDA变化。
DelayNOP(STARTNOP);
}
//-------------------------------------------
//-程序名称: Eestop
//-入口参数:无
//-出口参数:无
//-功能说明: IIC的STOP信号生成
//-------------------------------------------
void Eestop(void )/*停止I2C总线*/
{
i2csdaoutput();
CLRSCL;
DelayNOP(STARTNOP);
CLRSDA;
DelayNOP(STARTNOP);
SETSCL;
DelayNOP(STARTNOP);
SETSDA;
}
//-------------------------------------------
//-程序名称: read_byte_eeprom
//-入口参数:ackstate
//-出口参数:返回值(读取到的数据)
//-功能说明: 读取1byte的EEPROM数据
//-------------------------------------------
UI08 read_byte_eeprom(UI08 ackstate) //-read
{
UI08 j,data;
i2csdainput(); //-SDA端口设为输入状态
data = 0; //-将接收缓冲清空
//DelayNOP(NOP1US); //-2011-7-21 新增延时
for(j=0;j<8;j++)
{
//-
data <<= 1; //-将接收缓冲左移,保证高位先发
SETSCL;
DelayNOP(NOP2US); //-延时
if(p_eepsdain != 0) //-此处的p_eepsdain 就是SDA端口,ST芯片输入输出端口不是同一名字
{
//-检测到数据为1时,将接收缓冲0BIT置1
data++;
}
CLRSCL;
DelayNOP(NOP1P5US);
}
if(ackstate == ACKREAD)
{
//-有要求发送ACK信号的则发送ACK信号
i2csdaoutput(); //-将SDA端口设为输出
CLRSDA;
DelayNOP(NOP2US);
SETSCL;
DelayNOP(NOP2US);
CLRSCL;
}
return(data);
}
//-------------------------------------------
//-程序名称: write_byte_eeprom
//-入口参数:wrdata
//-出口参数:返回值,FALSE(写入失败),TRUE(写入成功)
//-功能说明: 将wrdata写入EEPROM
//-------------------------------------------
bool write_byte_eeprom(UI08 wrdata)
{
bool j=FALSE; //-返回值,默认为失败
UI08 i;
//DelayNOP(NOP1US); //-2011-7-21 新增延时
for(i=0; i<8; i++)
{
//-总共移位8次
if((0x80 & wrdata) != 0)
{
//-最高位为1时,SDA置1
SETSDA;
}
else
{
//-最高位为0时,SDA置0
CLRSDA;
}
wrdata <<= 1; //-将发送数据左移,实现高位先发
//DelayNOP(NOP1US); //-2011-7-21 新增延时
SETSCL;
DelayNOP(NOP2US);
CLRSCL;
DelayNOP(NOP1P5US);
}
//--read ACK signal--{
i2csdainput(); //-将SDA设为输入状态
DelayNOP(NOP1US);
SETSCL;
if(p_eepsdain == 0)
{
//-读取到正确的ACK信号,则返回写入成功
j = TRUE;
}
DelayNOP(NOP1P5US);
CLRSCL;
i2csdaoutput(); //-将SDA端口设为输出
//--read ACK signal--}
return(j);
}
//-------------------------------------------
//-程序名称: DelayNOP
//-入口参数:cntnop
//-出口参数:无
//-功能说明: 进行cntnop个延时
//-------------------------------------------
void DelayNOP(UI08 cntnop)
{
UI08 i;
for(i=0; i<cntnop; i++);
}
//-------------------------------------------
//-程序名称: i2csdainput
//-入口参数:无
//-出口参数:无
//-功能说明: 将SDA端口设为输入
//-------------------------------------------
void i2csdainput(void)
{
/*
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
*/
}
//-------------------------------------------
//-程序名称: i2csdaoutput
//-入口参数:无
//-出口参数:无
//-功能说明: 将SDA端口设为输出
//-------------------------------------------
void i2csdaoutput(void)
{
/*
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
*/
}
ST芯片的端口输入输出设定比较麻烦。所以有单独的子程序来处理。
单片机IIC的SDA端口在向EEPROM(24C01)发数据时,设为输出
在读取EEPROM数据的时候则设为输入。
//-------------------------------------------
//-程序名称: Eestart
//-入口参数:无
//-出口参数:无
//-功能说明: IIC的START信号生成
//-------------------------------------------
void Eestart(void) //启动I2C总线//
{
SETSDA;
DelayNOP(STARTNOP);
SETSCL;
DelayNOP(STARTNOP);
CLRSDA;
DelayNOP(STARTNOP);
CLRSCL; ;--注意此处,很重要。总线只有SCL为低时,才允许SDA变化。
DelayNOP(STARTNOP);
}
//-------------------------------------------
//-程序名称: Eestop
//-入口参数:无
//-出口参数:无
//-功能说明: IIC的STOP信号生成
//-------------------------------------------
void Eestop(void )/*停止I2C总线*/
{
i2csdaoutput();
CLRSCL;
DelayNOP(STARTNOP);
CLRSDA;
DelayNOP(STARTNOP);
SETSCL;
DelayNOP(STARTNOP);
SETSDA;
}
//-------------------------------------------
//-程序名称: read_byte_eeprom
//-入口参数:ackstate
//-出口参数:返回值(读取到的数据)
//-功能说明: 读取1byte的EEPROM数据
//-------------------------------------------
UI08 read_byte_eeprom(UI08 ackstate) //-read
{
UI08 j,data;
i2csdainput(); //-SDA端口设为输入状态
data = 0; //-将接收缓冲清空
//DelayNOP(NOP1US); //-2011-7-21 新增延时
for(j=0;j<8;j++)
{
//-
data <<= 1; //-将接收缓冲左移,保证高位先发
SETSCL;
DelayNOP(NOP2US); //-延时
if(p_eepsdain != 0) //-此处的p_eepsdain 就是SDA端口,ST芯片输入输出端口不是同一名字
{
//-检测到数据为1时,将接收缓冲0BIT置1
data++;
}
CLRSCL;
DelayNOP(NOP1P5US);
}
if(ackstate == ACKREAD)
{
//-有要求发送ACK信号的则发送ACK信号
i2csdaoutput(); //-将SDA端口设为输出
CLRSDA;
DelayNOP(NOP2US);
SETSCL;
DelayNOP(NOP2US);
CLRSCL;
}
return(data);
}
//-------------------------------------------
//-程序名称: write_byte_eeprom
//-入口参数:wrdata
//-出口参数:返回值,FALSE(写入失败),TRUE(写入成功)
//-功能说明: 将wrdata写入EEPROM
//-------------------------------------------
bool write_byte_eeprom(UI08 wrdata)
{
bool j=FALSE; //-返回值,默认为失败
UI08 i;
//DelayNOP(NOP1US); //-2011-7-21 新增延时
for(i=0; i<8; i++)
{
//-总共移位8次
if((0x80 & wrdata) != 0)
{
//-最高位为1时,SDA置1
SETSDA;
}
else
{
//-最高位为0时,SDA置0
CLRSDA;
}
wrdata <<= 1; //-将发送数据左移,实现高位先发
//DelayNOP(NOP1US); //-2011-7-21 新增延时
SETSCL;
DelayNOP(NOP2US);
CLRSCL;
DelayNOP(NOP1P5US);
}
//--read ACK signal--{
i2csdainput(); //-将SDA设为输入状态
DelayNOP(NOP1US);
SETSCL;
if(p_eepsdain == 0)
{
//-读取到正确的ACK信号,则返回写入成功
j = TRUE;
}
DelayNOP(NOP1P5US);
CLRSCL;
i2csdaoutput(); //-将SDA端口设为输出
//--read ACK signal--}
return(j);
}
//-------------------------------------------
//-程序名称: DelayNOP
//-入口参数:cntnop
//-出口参数:无
//-功能说明: 进行cntnop个延时
//-------------------------------------------
void DelayNOP(UI08 cntnop)
{
UI08 i;
for(i=0; i<cntnop; i++);
}
//-------------------------------------------
//-程序名称: i2csdainput
//-入口参数:无
//-出口参数:无
//-功能说明: 将SDA端口设为输入
//-------------------------------------------
void i2csdainput(void)
{
/*
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
*/
}
//-------------------------------------------
//-程序名称: i2csdaoutput
//-入口参数:无
//-出口参数:无
//-功能说明: 将SDA端口设为输出
//-------------------------------------------
void i2csdaoutput(void)
{
/*
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
*/
}
展开全部
我感觉你的应答程序有问题,如果有应答的话,SDA才被拉低,你直接使SDA拉低,所以不管实际上是否有应答你自己强制使其应答了,我是这样认为的,其实我也不太懂
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
我也是开始自学单片机,虽然困难但是很有意思。这是我自己做的程序,已经测试可用,但是是周立功公司的DP-51仿真实验板,上面芯片用的p89c52,数码管是4位8段共阳极的。
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define SomeNop(); {_nop_();_nop_();_nop_();_nop_();_nop_();}
void AckI2C(bit a);
bit SendStr(uchar slave,uchar add,uchar* source,uchar num);
bit RecStr(uchar slave,uchar add,uchar* source,uchar num);
bit ack;
sbit SDA=P1^0;
sbit CLK=P1^1;
sbit sda=P3^4;
sbit scl=P3^5;
uchar code led[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar DATAS[2];
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void send(uchar a)
{
uchar i;
for(i=0;i<8;i++)
{
if(_crol_(a,i)&0x80)
SDA=1;
else
SDA=0;
CLK=0;
CLK=1;
}
}
void display(uchar num1,num2)
{
while(1)
{
uchar temp=0xbf;
uchar j,k,m,n;
P1=temp;
j=led[num1/10];
send(j);
delay(1);
temp=_cror_(temp,1);
P1=temp;
k=led[num1%10];
send(k);
delay(1);
temp=_cror_(temp,1);
P1=temp;
m=led[num2/10];
send(m);
delay(1);
temp=_cror_(temp,1);
P1=temp;
n=led[num2%10];
send(n);
delay(1);
}
}
void main()
{
uchar num1,num2;
uchar DATA[2]={0x12,0x0a};
SendStr(0xa0,0x00,DATA,2);
delay(250);
RecStr(0xa0,0x00,DATAS,2);
num1=DATAS[0];
num2=DATAS[1];
display(num1,num2);
}
void start()
{
sda = 1;
scl = 1;
SomeNop();
sda = 0;
SomeNop();
scl = 0;
_nop_();
_nop_();
}
void stop()
{
sda = 0;
scl = 1;
SomeNop();
sda = 1;
SomeNop();
}
void AckI2C(bit a)
{
if(a==1)
sda = 1;
else
sda = 0;
_nop_();
_nop_();
scl = 1;
SomeNop();
scl = 0;
_nop_();
_nop_();
}
void SendByte(uchar b)
{
uchar i = 8;
uchar errtime = 255;
while(i--)
{
b <<= 1;
sda = CY;
scl = 1;
SomeNop();
scl = 0;
}
_nop_();
sda = 1;
_nop_();
_nop_();
scl = 1;
_nop_();
_nop_();
if(sda)
{
while(sda && errtime)
errtime--;
if(errtime)
ack = 1;
else
ack = 0;
}
else
ack = 1;
scl = 0;
_nop_();
_nop_();
}
uchar RecByte()
{
uchar i = 8;
uchar temp;
sda = 1;
while(i--)
{
_nop_();
scl = 0;
SomeNop();
scl = 1;
_nop_();
temp = (temp<<1) | sda;
_nop_();
}
scl = 0;
_nop_();
_nop_();
return temp;
}
bit SendStr(uchar slave,uchar add,uchar* source,uchar num)
{
start();
SendByte(slave);
if(!ack) return 0;
SendByte(add);
if(!ack) return 0;
while(num--)
{
SendByte(*source);
if(!ack) return 0;
source++;
}
stop();
return 1;
}
bit RecStr(uchar slave,uchar add,uchar* source,uchar num)
{
start();
SendByte(slave);
if(!ack) return 0;
SendByte(add);
if(!ack) return 0;
start();
SendByte(slave+1);
if(!ack) return 0;
num--;
while(num--)
{
*source = RecByte();
AckI2C(0);
source++;
}
*source = RecByte();
stop();
return 1;
}
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define SomeNop(); {_nop_();_nop_();_nop_();_nop_();_nop_();}
void AckI2C(bit a);
bit SendStr(uchar slave,uchar add,uchar* source,uchar num);
bit RecStr(uchar slave,uchar add,uchar* source,uchar num);
bit ack;
sbit SDA=P1^0;
sbit CLK=P1^1;
sbit sda=P3^4;
sbit scl=P3^5;
uchar code led[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar DATAS[2];
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void send(uchar a)
{
uchar i;
for(i=0;i<8;i++)
{
if(_crol_(a,i)&0x80)
SDA=1;
else
SDA=0;
CLK=0;
CLK=1;
}
}
void display(uchar num1,num2)
{
while(1)
{
uchar temp=0xbf;
uchar j,k,m,n;
P1=temp;
j=led[num1/10];
send(j);
delay(1);
temp=_cror_(temp,1);
P1=temp;
k=led[num1%10];
send(k);
delay(1);
temp=_cror_(temp,1);
P1=temp;
m=led[num2/10];
send(m);
delay(1);
temp=_cror_(temp,1);
P1=temp;
n=led[num2%10];
send(n);
delay(1);
}
}
void main()
{
uchar num1,num2;
uchar DATA[2]={0x12,0x0a};
SendStr(0xa0,0x00,DATA,2);
delay(250);
RecStr(0xa0,0x00,DATAS,2);
num1=DATAS[0];
num2=DATAS[1];
display(num1,num2);
}
void start()
{
sda = 1;
scl = 1;
SomeNop();
sda = 0;
SomeNop();
scl = 0;
_nop_();
_nop_();
}
void stop()
{
sda = 0;
scl = 1;
SomeNop();
sda = 1;
SomeNop();
}
void AckI2C(bit a)
{
if(a==1)
sda = 1;
else
sda = 0;
_nop_();
_nop_();
scl = 1;
SomeNop();
scl = 0;
_nop_();
_nop_();
}
void SendByte(uchar b)
{
uchar i = 8;
uchar errtime = 255;
while(i--)
{
b <<= 1;
sda = CY;
scl = 1;
SomeNop();
scl = 0;
}
_nop_();
sda = 1;
_nop_();
_nop_();
scl = 1;
_nop_();
_nop_();
if(sda)
{
while(sda && errtime)
errtime--;
if(errtime)
ack = 1;
else
ack = 0;
}
else
ack = 1;
scl = 0;
_nop_();
_nop_();
}
uchar RecByte()
{
uchar i = 8;
uchar temp;
sda = 1;
while(i--)
{
_nop_();
scl = 0;
SomeNop();
scl = 1;
_nop_();
temp = (temp<<1) | sda;
_nop_();
}
scl = 0;
_nop_();
_nop_();
return temp;
}
bit SendStr(uchar slave,uchar add,uchar* source,uchar num)
{
start();
SendByte(slave);
if(!ack) return 0;
SendByte(add);
if(!ack) return 0;
while(num--)
{
SendByte(*source);
if(!ack) return 0;
source++;
}
stop();
return 1;
}
bit RecStr(uchar slave,uchar add,uchar* source,uchar num)
{
start();
SendByte(slave);
if(!ack) return 0;
SendByte(add);
if(!ack) return 0;
start();
SendByte(slave+1);
if(!ack) return 0;
num--;
while(num--)
{
*source = RecByte();
AckI2C(0);
source++;
}
*source = RecByte();
stop();
return 1;
}
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询