3939|5

80

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

关于ii问题请教! [复制链接]

我按照“msp430系列16位超低功耗单片机实践和系统设计”上的iic程序写的,为什么读不出数据。请问一下,这个例程序是否正确!那问告诉?

最新回复

里面的delay() 是延时,比如 delay(5); 就是for(i=5;i>0;i--);  详情 回复 发表于 2005-6-16 13:48
 
点赞 关注

回复
举报

68

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
是否是和24C256?你用的是430哪个型号的?
 
 

回复

65

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
能否贴出程序?
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

4
 
msp430f1121和24lc01
程序是书上的程序如下:
/********************************************************
* 文件名称:
* IIC.c
* 文件说明:
* 使用口线模拟IIC
*********************************************************/



//p1.6 = scl ,p1.5 = sda;
/*********************************************************
* 数据定义
*********************************************************/
unsigned char read_Buf, //读缓冲区
write_Buf, //写缓冲区
ctrl_Buf, //用于存放控制指令等的中间缓冲区
addr_Buf, //高地址缓冲
ack_Flag; //应答标识
/************************************************
* 延迟
************************************************/

void iic_Delay(void)
{
_NOP();
_NOP();
_NOP();
}
/*********************************************************
* 启动IIC
*********************************************************/
void start_IIC(void)
{
P1OUT &= 0x9f ; //设置P1OUT
P1DIR &= 0xdf; //SDA = 1
iic_Delay();
P1DIR &= 0xbf; //SCL = 1
iic_Delay();
P1DIR |= 0x20; //SDA = 0
iic_Delay();
P1DIR |= 0x40; //SCL = 0
iic_Delay();

}
/*******************************************************
* 停止IIC
*******************************************************/
void stop_IIC(void)
{
P1DIR |= 0x20; //SDA = 0
iic_Delay();
P1DIR &= 0xbf; //SCL = 1
iic_Delay();
P1DIR &= 0xdf; //SDA = 1
iic_Delay();
P1DIR |= 0x20; //SDA = 0
iic_Delay();
P1DIR |= 0x40; //SCL = 0
}

/*******************************************************
* 发送 0
*******************************************************/
void send_Zero(void)
{
P1DIR |= 0x20; //SDA = 0
iic_Delay();
P1DIR &= 0xbf; //SCL = 1
iic_Delay();
P1DIR |= 0x40; //SCL = 0
iic_Delay();

}
/*******************************************************
* 发送 1
*******************************************************/
void send_One(void)
{
P1DIR &= 0xdf; //SDA = 1
iic_Delay();
P1DIR &= 0xbf; //SCL = 1
iic_Delay();
P1DIR |= 0x40; //SCL = 0
iic_Delay();
P1DIR |= 0x20; //SDA = 0
iic_Delay();
}
/*******************************************************
* 发送一个字节数据
*******************************************************/
void send_Char(void)
{
unsigned char cnt,tmp=0x80;
for(cnt=0;cnt<8;cnt++)
{
if((ctrl_Buf & tmp )> 0)
{
send_One(); // 发送1
}
else
{
send_Zero(); // 发送0
}
tmp /= 2; // tmp右移一位
}
}

/*******************************************************
* 读一个byte数据
*******************************************************/
void read_Char(void)
{
unsigned char cnt,tmp=0x80;
read_Buf = 0x00;
for(cnt=0;cnt<8;cnt++)
{
P1DIR &= 0xdf; //SDA = 1
iic_Delay();
P1DIR &= 0xbf; //SCL = 1
iic_Delay();
if((P1IN & 0x20) > 0x00)
{ // 收到 1
read_Buf |= tmp;
}
P1DIR |= 0x40; //SCL = 0
iic_Delay();
tmp = tmp/2;

}
}

/*************************************************
* 应答信号
*************************************************/
void iic_ACK(void)
{
ack_Flag = 0x00;
P1DIR &= 0xdf; //SDA = 1
iic_Delay();
P1DIR &= 0xbf; //SCL = 1

if ((P1IN & 0x20) == 0x20 )
{
ack_Flag = 0x01;
}
P1DIR |= 0x40; //SCL = 0
iic_Delay();

}
/***********************************************
* iic_NACK
************************************************/
void iic_NACK(void)
{
P1DIR &= 0xdf; //SDA = 1
iic_Delay();
P1DIR &= 0xbf; //SCL = 0
iic_Delay();

P1DIR |= 0x40; //SCL = 0
iic_Delay();
P1DIR |= 0x20; //SDA = 0
iic_Delay();
}

/************************************************
* 写一个数据到EEPROM
*************************************************/
void write_EEPROM(void)
{
unsigned char step_Flag=0x00;
while(step_Flag < 0x03)
{
if(step_Flag == 0x00)
{
start_IIC(); // 启动 I2c
ctrl_Buf = 0xA0; // 设置控制位
send_Char(); // 发送控制位
iic_ACK(); // 确认
if (ack_Flag == 0) step_Flag += 1;
}
else if (step_Flag==1)
{
ctrl_Buf = addr_Buf; // 设置地址
send_Char(); // 发送地址
iic_ACK(); // 读 确认
if (ack_Flag == 0)
{ // 检测是否地址发送成功
step_Flag += 1;
}
else
{
step_Flag = 0;
}
}
else{
ctrl_Buf = write_Buf; // 设置写内容
send_Char(); // 写
iic_ACK(); // 读响应信息
if (ack_Flag == 0)
{ // 检测是否写成功
step_Flag += 1;
}
else
{
step_Flag = 0;
}
}
}

stop_IIC(); // 停止 IIC

}
/*************************************************
* 从EEPROM读数据
*************************************************/
void read_EEPROM()
{
unsigned char step_Flag=0;
while(step_Flag < 0x03)
{
if(step_Flag == 0x00)
{
start_IIC(); //启动 I2c
ctrl_Buf = 0xa0; //设置控制位
send_Char(); //发送控制位
iic_ACK(); //读取应答
if (ack_Flag == 0) step_Flag += 1;
}else if (step_Flag==1){ // 如果控制位发送成功
ctrl_Buf = addr_Buf; // 设置读地址
send_Char(); // 发送地址
iic_ACK(); // 读响应
if (ack_Flag == 0)
{ // 是否地址已经发送
step_Flag += 1;
}else{
step_Flag = 0;
}
}else{
start_IIC(); // 启动 IIC
ctrl_Buf = 0xa1; // 设置读模式
send_Char(); // 发送控制位
iic_ACK(); // 获取响应
if (ack_Flag == 0)
{ // 是否发送成功
step_Flag += 1;
read_Char(); // 读字符
iic_NACK(); // 发响应
}else{
step_Flag = 0;
}
}
}
stop_IIC(); // 停止 IIC
}
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

5
 
下面是24LC256 的程序,我自己的项目里的,绝对可用。
/*-----------------------
*函数名称:vid Init(void)
*函数说明:IIC器件的初始化
*----------------------*/
void Init(void)
{
SCL_1;
delay(5);
SDA_1;
delay(5);
}
/*-------------------------------------
*函数名称:void Start(void)
*函数说明:提供I2C总线工作时序中的起始位
*------------------------------------*/
void Start(void)
{
SDA_1;
delay(5);
SCL_1;
delay(5);
SDA_0;
delay(5);
SCL_0;
delay(5);
}
/*--------------------------------------
*函数名称:void Stop(void)
*函数说明:提供I2C总线工作时序中的停止位
*-------------------------------------*/
void Stop(void)
{
SDA_0;
delay(5);
SCL_1;
delay(5);
SDA_1;
delay(5);
}

/*------------------------------------------------------------
*函数名称:IICAck(void)
*函数说明:对IIC总线产生应答,在连续读取时,每读取1字节后执行
*------------------------------------------------------------*/
void IICAck(void)
{
SDA_0;
SCL_1;
_NOP();
_NOP();
_NOP();
SCL_0;
_NOP();
SDA_1;
}


/*------------------------------------------------------
*函数名称:IICNoAck(void)
*函数说明: 不对IIC总线产生应答,在读取完最后1字节数据后执行
*-----------------------------------------------------*/
void IICNoAck(void)
{
SDA_1;
SCL_1;
_NOP();
_NOP();
_NOP();
SCL_0;
}
/*-----------------------------------------------------
*函数名称: ReceiveAck(void)
*函数说明: 检查返回应答位,在每写入1字节数据后都要执行
*----------------------------------------------------*/
unsigned char ReceiveAck(void)
{
unsigned char Ack=0; //存储应答位的字节
SDA_1 ;
delay(2);
SCL_1 ;
delay(2);
DIR_IN; // SDA 方向为输入
Ack = SDA_IN ; //SDA状态送Ack
SCL_0 ;
DIR_OUT; //SDA 方向重新还原为输出
delay(2);
return (Ack);
}



/*-----------------------------------------------------
*函数名称:Write_byte(unsigned char input)
*函数说明:向I2C总线发送8位数据, 高位在先
*----------------------------------------------------*/
void Write_byte(unsigned char input)
{
unsigned char i;
for(i=0;i<8;i++)
{
if((input&0x80)==0x80)
SDA_1;
else
SDA_0;
SCL_1;
SCL_0;
input=input<<1;
delay(3);
}
}





/*--------------------------------------
*函数名称:Read_byte(unsigned char input)
*函数说明:从I2C总线读取8位数据, 高位在先
*-------------------------------------*/

unsigned char Read_byte(void)
{
unsigned char i, output=0;
DIR_IN; //SDA方向设置为 输入
for(i=0;i<8;i++)
{
SCL_1;
output=output<<1;
if(SDA_IN==0x01)output=output|0x01;
SCL_0;
delay(3);
}
DIR_OUT; //SDA方向设置为 输出
return(output);
}

/*------------------------------------------------------------------------------
*函数名称:WR_24LC256(unsigned int RomAddress,unsigned char data)
*函数说明:写1字节数据到LC256(字节写模式),(先写器件地址,片内地址,再送数据)
*-----------------------------------------------------------------------------*/
void WR_24LC256(unsigned int RomAddress,unsigned char data)
{
unsigned char i;
unsigned char Ack;
Init(); //I2C总线初始化
for (i=0;i<10;i++) //每个要写入的数据最多允许写10次(在失败情况下)
{
Start();
Write_byte(0xa0); //24C的外部地址,0xa0
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)(RomAddress>>8)); //片内rom地址 高8位
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)RomAddress); //片内rom地址 低8位
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte(data);
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Stop();
if (Ack==0) break;//写入正确,1次即可,跳出for
}

delay(1000);
}
/*-----------------------------------------------------------------------------------------
*函数名称:void PWR_24LC256(unsigned int RomAddress,unsigned char number)
*函数说明:连续写模式,一次写入最多64字节数据,RomAddress为起始地址,number为要写入的数据字节数
*-----------------------------------------------------------------------------------------*/
void PWR_24LC256(unsigned int RomAddress,unsigned char number )
{
unsigned char i,k;
unsigned char Ack;
unsigned char errorflag;
Init(); //I2C总线初始化
for (i=0;i<10;i++) //每个要写入的数据最多允许写10次(在失败情况下)
{
Start();
Write_byte(0xa0); //24C的外部地址,0xa0
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)(RomAddress>>8)); //片内rom地址 高8位
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)RomAddress); //片内rom地址 低8位
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}

errorflag=0;
for(k=0;k<number;k++) //循环送数据
{
Write_byte(WR_RDtab[k]);
Ack= ReceiveAck();//
if(Ack==0x00) //写入正确
{ continue;}
errorflag=1;
break;
}
if(errorflag==1)
{continue;} //写入错误,重新写入控制字节,首地址,重新写所有数据
break;
}
Stop();

delay(1000);
}


/*----------------------------------------------------------------------------------
*函数名称:RD_24LC256(unsigned cahr addr1,unsigned int addr2)
*函数说明:读24LC256函数(字节模式),带二个参数,第一个参数为24C的外部地址和读写命令码
* 第二个参数为24C的内部存储地址,返回值为欲读出的值
*---------------------------------------------------------------------------------*/
unsigned char RD_24LC256(unsigned int RomAddress)
{
unsigned char Temp;
unsigned char i;
unsigned char Ack;
Init(); //I2C总线初始化
for(i=0;i<10;i++)
{
Start();
Write_byte(0xa0); //devices address(control byte) 写
Ack=ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)(RomAddress>>8)); //片内rom地址 高8位
Ack=ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)RomAddress); //片内rom地址 低8位
Ack=ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Start();
Write_byte(0xa1); //devices address(control byte) 读
Ack=ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Temp=Read_byte();
IICNoAck();
Stop();
if (Ack==0 ) break;//写入正确,1次即可,跳出for
}
return (Temp) ;
}

/*----------------------------------------------------------------------------
*函数名称:SRD_24LC256(unsigned int RomAddress,unsigned char number)
*函数说明:连续读模式,RomAddress为要读取数据的起始地址,number为要读取的字节数
*---------------------------------------------------------------------------*/
void SRD_24LC256(unsigned int RomAddress,unsigned char number)
{
unsigned char i,k;
unsigned char Ack;
Init(); //I2C总线初始化
for(i=0;i<10;i++)
{
Start();
Write_byte(0xa0); //devices address 写
Ack=ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)(RomAddress>>8)); //片内rom地址 高8位
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)RomAddress); //片内rom地址 低8位
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Start();
Write_byte(0xa1); //devices address 读
Ack=ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
for(k=0;k<number-1;k++) //循环读取数据
{
WR_RDtab[k]=Read_byte();
IICAck();
}
WR_RDtab[k]=Read_byte();//读取最后一个字节数据
IICNoAck();
break;
}
Stop();

}
 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

6
 
里面的delay()
是延时,比如 delay(5);
就是for(i=5;i>0;i--);
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表