例如写操作时的一个语句,if (ack==0)return(0);这里的return(0)是什么意思?此外,整个写函数结束后,会以return(1)结尾,这里的rerun(1)又是什么作用???求高手指点,感激不尽
#ifndef __AT24C02_H__
#define __AT24C02_H__
#include<stc89.h> //包含单片机寄存器的头文件
#include<intrins.h> //包含NOP空指令的头文件
#define uchar unsigned char
#define uint unsigned int
/*宏定义器件地址*/ //AT24C器件ID 1 0 1 0 A2 A1 A0 RW
#define AT24_ID0 0XA0 //AT24C器件ID 1 0 1 0 0 0 0 RW
#define AT24_ID1 0XA2 //AT24C器件ID 1 0 1 0 0 0 1 RW
#define AT24_ID2 0XA4 //AT24C器件ID 1 0 1 0 0 1 0 RW
#define AT24_ID3 0XA6 //AT24C器件ID 1 0 1 0 0 1 1 RW
#define AT24_ID4 0XA8 //AT24C器件ID 1 0 1 0 1 0 0 RW
#define AT24_ID5 0XAA //AT24C器件ID 1 0 1 0 1 0 1 RW
#define AT24_ID6 0XAE //AT24C器件ID 1 0 1 0 1 1 1 RW
/*其他参数*/
#define AT24_INQ 255 //器件应答最大检测次数 超过此数量 无应答也会退出循环 以避免程序死循环
/*I2C总线驱动IO口*/
sbit I2C_SCL=P1^5;//串行时钟输入。SCL同步数据传输,上升沿数据写入,下降沿数据读出
sbit I2C_SDA=P3^6;//穿行地址和数据输入/输出。SDA是双向串行数据传输引脚,漏极开路,需外接上拉电阻到VCC(典型值10K)
/*最终使用的函数*/
void at24cxx_weite(uchar I2C_IDRW,I2C_ADDRESS,I2C_DATA);//写入AT24 I2C_IDRW器件地址 I2C_ADDRESS数据地址 I2C_DATA数据
uchar at24cxx_read(uchar I2C_IDRW,I2C_ADDRESS) ; //带地址的读取AT24 I2C_IDRW器件地址 I2C_ADDRESS数据地址
/*被调用的子函数*/
uchar at24cxx_rd(I2C_IDRD); //当前地址读取AT24 由 读取函数调用 I2C_IDRD 为器件地址
void at24cxx_com(uchar I2C_DATA); //AT24写公用函数 由写入读取函数调用 I2C_DATA 为要写入的变量(器件ID,数据地址,数据)
void at24cxx_start(); //AT24起始信号 由写入读取函数调用
void at24cxx_stop(); //AT24停止信号 由写入读取函数调用
void at24cxx_inquires(uchar I2C_IDRW);//AT24应答检测 由写入读取函数调用
void at24cxx_response(); //I2C总线应答检测 由写入读取函数调用
void at24cxx_ricom(); //器件应答与总线应答检测 公用函数 由器件应答和总线应答函数调用
/*字节写操作 起始条件 器件地址 写 字地址 数据停止条件*/
void at24cxx_weite(uchar I2C_IDRW,I2C_ADDRESS,I2C_DATA)//写入AT24I2C_IDRW器件地址 I2C_ADDRESS数据地址 I2C_DATA数据
{
//at24cxx_start(); //起始条件 开始写入数据
//at24cxx_com(I2C_IDRW&0xfe); //写入芯片ID及读写选择位 0
//at24cxx_response(); //总线应答
at24cxx_inquires(I2C_IDRW&0xfe);//器件应答检测 并写入器件ID以及读写选项 内部有起始条件
at24cxx_com(I2C_ADDRESS); //写入数据地址
at24cxx_response(); //总线应答
at24cxx_com(I2C_DATA); //写入数据
at24cxx_response(); //总线应答
at24cxx_stop(); //结束条件 终止写入数据
}
/*函数流程 起始条件 器件地址 写 字地址 起始条件 器件地址 读 读数据 停止条件*/
uchar at24cxx_read(uchar I2C_IDRW,I2C_ADDRESS) //带地址的读取AT24 I2C_IDRW器件地址 I2C_ADDRESS数据地址
{ uchar I2C_DATA; //最终读取的数据
//at24cxx_start(); //起始条件 开始写入数据
//at24cxx_com(I2C_IDRW&0xfe); //写入芯片ID及读写选择位 0
//at24cxx_response(); //总线应答
at24cxx_inquires(I2C_IDRW&0xfe); //器件应答检测 并写入器件ID以及读写选项 内部有起始条件
at24cxx_com(I2C_ADDRESS); //写入数据地址
at24cxx_response(); //总线应答
I2C_DATA=at24cxx_rd(I2C_IDRW|0x01);//写入芯片ID及读写选择位 1 程序内部有起始停止功能
return(I2C_DATA); //返回数据
}
/*起始条件 器件地址 读 数据 停止条件*/
/*当前地址读 起始条件 器件地址 读 数据 停止条件*/
/*接收器件地址(读/写选择为为1)、EEPROM应答ACK后,当前地址的数据就随时钟送出主器件无需应答0,但需要发送停止条件*/
uchar at24cxx_rd(I2C_IDRD) //当前地址读取AT24 I2C_IDRD为器件地址
{ uchar I2C_NUM,I2C_DAT; //定义8位变量用来做循环移位读取数据
at24cxx_start(); //起始条件
at24cxx_com(I2C_IDRD|0x01); //写入芯片ID及读写选择位 1
at24cxx_response(); //总线应答
for(I2C_NUM=0;I2C_NUM<8;I2C_NUM++)
{ I2C_DAT=I2C_DAT<<1; //数据左移位
I2C_SCL=1; //拉高时钟线得到 要读的数据
_nop_(); //一个机器周期指令
if(I2C_SDA==1) //判断数据为1
{I2C_DAT=I2C_DAT|0X01;} //将数据变量赋值
I2C_SCL=0; //拉低时钟线 以获得新数据
nop_(); //一个机器周期指令
}
at24cxx_stop(); //结束条件 终止接收数据
return(I2C_DAT); //返回数据
}
/*由读写函数调用 目的:节省空间*/
void at24cxx_com(uchar I2C_DATA) //AT24写公用函数
{ uchar I2C_NUM,I2C_DAT; //定义8位变量用来做循环写入位
for(I2C_NUM=0;I2C_NUM<8;I2C_NUM++)
{
I2C_DAT=(I2C_DATA>>7);//获得数据最高位
I2C_DAT=I2C_DAT&0X01; //取数据的最高位数据
I2C_SCL=0; //拉低时钟线数据传输开始
_nop_(); //一个机器周期指令
I2C_SDA=I2C_DAT; //I2C数据线赋值
_nop_(); //一个机器周期指令
I2C_SCL=1; //拉高时钟线数据存储
_nop_(); //一个机器周期指令
I2C_DATA=I2C_DATA<<1; //数据移位
}
}
/*当SCL为高电平时SDA的下降沿(高到低)叫做起始条件(START)起始条件保持时间 最小值1.8V 0.6US:5V 0.25US 起始条件建立时间1.8V 0.6US:5V 0.25US */
void at24cxx_start()//AT24起始信号
{
I2C_SCL=1; //空闲总线
_nop_(); //一个机器周期指令
I2C_SDA=1; //空闲总线
_nop_(); //一个机器周期指令
I2C_SDA=0; //拉低数据线 发起起始信号
_nop_(); //一个机器周期指令
}
/*SDA的上升沿(低到高)叫做停止条件(STOP) 停止条件建立时间 最小值1.8V 0.6US:5V 0.25US */
void at24cxx_stop() //AT24停止信号
{
I2C_SDA=0; //拉低数据线 以便形成上升沿
_nop_(); //一个机器周期指令
I2C_SCL=1; //
_nop_(); //一个机器周期指令
I2C_SDA=1; //老高数据线 发起停止信号
_nop_(); //一个机器周期指令
}
/*一旦内部写周期启动,EEPROM输入无效,此时即可启动应答查询:发送起始条件和器件地址(读/写位为期望的操作)。
只有内部写周期完成EEPROM才会应答“0”。之后可继续读/写操作
应答查询流程:1.发送写命令 2.发送停止条件启动写周期 3.发送起始条件 4.发送控制字节R/W=0 5.器件是否应答(ACK=0)? 是 5.下一操作 否 重复2-4操作
*/
void at24cxx_inquires(uchar I2C_IDRW)//AT24应答查询
{ uchar AT24_NUM; //定义变量用来跳出循环应答检测
AT24_NUM=AT24_INQ; //赋值应答最大检测次数 避免无应答时程序死循环
while(AT24_NUM--) //循环判断应答
{ at24cxx_start(); //发送起始条件
at24cxx_com(I2C_IDRW); //写入芯片ID及读写选择位
at24cxx_ricom(); //调用应答公用检测函数
if(I2C_SDA==0) //应答成功
{break;} //退出循环
}
I2C_SCL=0; //应答结束拉低时钟线
_nop_(); //一个机器周期指令
I2C_SDA=1; //应答结束把数据线重新拉高
_nop_(); //一个机器周期指令
}
/*接收器拉低SDA线表示应答,应在应答脉冲器件保持稳定的低电平。当主器件做接收器时,必须发出数据传输结束的信号给发送器,
即它在最后一个字节之后的应答脉冲期间不会产生应噶信号(不拉低SDA)。这种情况下,发送器必须释放SDA线为高以便主器件产生停止条件*/
void at24cxx_response()//总线应答
{
at24cxx_ricom(); //调用应答公用检测函数
I2C_SCL=0; //应答结束拉低时钟线
_nop_(); //一个机器周期指令
I2C_SDA=1; //应答结束把数据线重新拉高
_nop_(); //一个机器周期指令
}
/*器件应答与总线应答公用函数 由于这部分代码相同 所以写成一个函数 以节省空间*/
void at24cxx_ricom() //器件应答与总线应答检测 公用函数
{
uchar AT24_NUM; //定义变量 用来无应答时跳出循环判断应答
I2C_SCL=0; //总线应答额外脉冲
_nop_(); //一个机器周期指令
I2C_SDA=1; //拉高数据线 以检测应答
_nop_(); //一个机器周期指令
I2C_SCL=1; //应答时钟脉冲
_nop_(); //一个机器周期指令
while(I2C_SDA) //判断应答
{
if(AT24_NUM<255)//判断累加 总线应答检测最大时间(次数) 避免无应答时程序死循环
{AT24_NUM++;} //没有到则自+
else //否则
{break;} //退出循环判断应答
}
}
#define __AT24C02_H__
#include<stc89.h> //包含单片机寄存器的头文件
#include<intrins.h> //包含NOP空指令的头文件
#define uchar unsigned char
#define uint unsigned int
/*宏定义器件地址*/ //AT24C器件ID 1 0 1 0 A2 A1 A0 RW
#define AT24_ID0 0XA0 //AT24C器件ID 1 0 1 0 0 0 0 RW
#define AT24_ID1 0XA2 //AT24C器件ID 1 0 1 0 0 0 1 RW
#define AT24_ID2 0XA4 //AT24C器件ID 1 0 1 0 0 1 0 RW
#define AT24_ID3 0XA6 //AT24C器件ID 1 0 1 0 0 1 1 RW
#define AT24_ID4 0XA8 //AT24C器件ID 1 0 1 0 1 0 0 RW
#define AT24_ID5 0XAA //AT24C器件ID 1 0 1 0 1 0 1 RW
#define AT24_ID6 0XAE //AT24C器件ID 1 0 1 0 1 1 1 RW
/*其他参数*/
#define AT24_INQ 255 //器件应答最大检测次数 超过此数量 无应答也会退出循环 以避免程序死循环
/*I2C总线驱动IO口*/
sbit I2C_SCL=P1^5;//串行时钟输入。SCL同步数据传输,上升沿数据写入,下降沿数据读出
sbit I2C_SDA=P3^6;//穿行地址和数据输入/输出。SDA是双向串行数据传输引脚,漏极开路,需外接上拉电阻到VCC(典型值10K)
/*最终使用的函数*/
void at24cxx_weite(uchar I2C_IDRW,I2C_ADDRESS,I2C_DATA);//写入AT24 I2C_IDRW器件地址 I2C_ADDRESS数据地址 I2C_DATA数据
uchar at24cxx_read(uchar I2C_IDRW,I2C_ADDRESS) ; //带地址的读取AT24 I2C_IDRW器件地址 I2C_ADDRESS数据地址
/*被调用的子函数*/
uchar at24cxx_rd(I2C_IDRD); //当前地址读取AT24 由 读取函数调用 I2C_IDRD 为器件地址
void at24cxx_com(uchar I2C_DATA); //AT24写公用函数 由写入读取函数调用 I2C_DATA 为要写入的变量(器件ID,数据地址,数据)
void at24cxx_start(); //AT24起始信号 由写入读取函数调用
void at24cxx_stop(); //AT24停止信号 由写入读取函数调用
void at24cxx_inquires(uchar I2C_IDRW);//AT24应答检测 由写入读取函数调用
void at24cxx_response(); //I2C总线应答检测 由写入读取函数调用
void at24cxx_ricom(); //器件应答与总线应答检测 公用函数 由器件应答和总线应答函数调用
/*字节写操作 起始条件 器件地址 写 字地址 数据停止条件*/
void at24cxx_weite(uchar I2C_IDRW,I2C_ADDRESS,I2C_DATA)//写入AT24I2C_IDRW器件地址 I2C_ADDRESS数据地址 I2C_DATA数据
{
//at24cxx_start(); //起始条件 开始写入数据
//at24cxx_com(I2C_IDRW&0xfe); //写入芯片ID及读写选择位 0
//at24cxx_response(); //总线应答
at24cxx_inquires(I2C_IDRW&0xfe);//器件应答检测 并写入器件ID以及读写选项 内部有起始条件
at24cxx_com(I2C_ADDRESS); //写入数据地址
at24cxx_response(); //总线应答
at24cxx_com(I2C_DATA); //写入数据
at24cxx_response(); //总线应答
at24cxx_stop(); //结束条件 终止写入数据
}
/*函数流程 起始条件 器件地址 写 字地址 起始条件 器件地址 读 读数据 停止条件*/
uchar at24cxx_read(uchar I2C_IDRW,I2C_ADDRESS) //带地址的读取AT24 I2C_IDRW器件地址 I2C_ADDRESS数据地址
{ uchar I2C_DATA; //最终读取的数据
//at24cxx_start(); //起始条件 开始写入数据
//at24cxx_com(I2C_IDRW&0xfe); //写入芯片ID及读写选择位 0
//at24cxx_response(); //总线应答
at24cxx_inquires(I2C_IDRW&0xfe); //器件应答检测 并写入器件ID以及读写选项 内部有起始条件
at24cxx_com(I2C_ADDRESS); //写入数据地址
at24cxx_response(); //总线应答
I2C_DATA=at24cxx_rd(I2C_IDRW|0x01);//写入芯片ID及读写选择位 1 程序内部有起始停止功能
return(I2C_DATA); //返回数据
}
/*起始条件 器件地址 读 数据 停止条件*/
/*当前地址读 起始条件 器件地址 读 数据 停止条件*/
/*接收器件地址(读/写选择为为1)、EEPROM应答ACK后,当前地址的数据就随时钟送出主器件无需应答0,但需要发送停止条件*/
uchar at24cxx_rd(I2C_IDRD) //当前地址读取AT24 I2C_IDRD为器件地址
{ uchar I2C_NUM,I2C_DAT; //定义8位变量用来做循环移位读取数据
at24cxx_start(); //起始条件
at24cxx_com(I2C_IDRD|0x01); //写入芯片ID及读写选择位 1
at24cxx_response(); //总线应答
for(I2C_NUM=0;I2C_NUM<8;I2C_NUM++)
{ I2C_DAT=I2C_DAT<<1; //数据左移位
I2C_SCL=1; //拉高时钟线得到 要读的数据
_nop_(); //一个机器周期指令
if(I2C_SDA==1) //判断数据为1
{I2C_DAT=I2C_DAT|0X01;} //将数据变量赋值
I2C_SCL=0; //拉低时钟线 以获得新数据
nop_(); //一个机器周期指令
}
at24cxx_stop(); //结束条件 终止接收数据
return(I2C_DAT); //返回数据
}
/*由读写函数调用 目的:节省空间*/
void at24cxx_com(uchar I2C_DATA) //AT24写公用函数
{ uchar I2C_NUM,I2C_DAT; //定义8位变量用来做循环写入位
for(I2C_NUM=0;I2C_NUM<8;I2C_NUM++)
{
I2C_DAT=(I2C_DATA>>7);//获得数据最高位
I2C_DAT=I2C_DAT&0X01; //取数据的最高位数据
I2C_SCL=0; //拉低时钟线数据传输开始
_nop_(); //一个机器周期指令
I2C_SDA=I2C_DAT; //I2C数据线赋值
_nop_(); //一个机器周期指令
I2C_SCL=1; //拉高时钟线数据存储
_nop_(); //一个机器周期指令
I2C_DATA=I2C_DATA<<1; //数据移位
}
}
/*当SCL为高电平时SDA的下降沿(高到低)叫做起始条件(START)起始条件保持时间 最小值1.8V 0.6US:5V 0.25US 起始条件建立时间1.8V 0.6US:5V 0.25US */
void at24cxx_start()//AT24起始信号
{
I2C_SCL=1; //空闲总线
_nop_(); //一个机器周期指令
I2C_SDA=1; //空闲总线
_nop_(); //一个机器周期指令
I2C_SDA=0; //拉低数据线 发起起始信号
_nop_(); //一个机器周期指令
}
/*SDA的上升沿(低到高)叫做停止条件(STOP) 停止条件建立时间 最小值1.8V 0.6US:5V 0.25US */
void at24cxx_stop() //AT24停止信号
{
I2C_SDA=0; //拉低数据线 以便形成上升沿
_nop_(); //一个机器周期指令
I2C_SCL=1; //
_nop_(); //一个机器周期指令
I2C_SDA=1; //老高数据线 发起停止信号
_nop_(); //一个机器周期指令
}
/*一旦内部写周期启动,EEPROM输入无效,此时即可启动应答查询:发送起始条件和器件地址(读/写位为期望的操作)。
只有内部写周期完成EEPROM才会应答“0”。之后可继续读/写操作
应答查询流程:1.发送写命令 2.发送停止条件启动写周期 3.发送起始条件 4.发送控制字节R/W=0 5.器件是否应答(ACK=0)? 是 5.下一操作 否 重复2-4操作
*/
void at24cxx_inquires(uchar I2C_IDRW)//AT24应答查询
{ uchar AT24_NUM; //定义变量用来跳出循环应答检测
AT24_NUM=AT24_INQ; //赋值应答最大检测次数 避免无应答时程序死循环
while(AT24_NUM--) //循环判断应答
{ at24cxx_start(); //发送起始条件
at24cxx_com(I2C_IDRW); //写入芯片ID及读写选择位
at24cxx_ricom(); //调用应答公用检测函数
if(I2C_SDA==0) //应答成功
{break;} //退出循环
}
I2C_SCL=0; //应答结束拉低时钟线
_nop_(); //一个机器周期指令
I2C_SDA=1; //应答结束把数据线重新拉高
_nop_(); //一个机器周期指令
}
/*接收器拉低SDA线表示应答,应在应答脉冲器件保持稳定的低电平。当主器件做接收器时,必须发出数据传输结束的信号给发送器,
即它在最后一个字节之后的应答脉冲期间不会产生应噶信号(不拉低SDA)。这种情况下,发送器必须释放SDA线为高以便主器件产生停止条件*/
void at24cxx_response()//总线应答
{
at24cxx_ricom(); //调用应答公用检测函数
I2C_SCL=0; //应答结束拉低时钟线
_nop_(); //一个机器周期指令
I2C_SDA=1; //应答结束把数据线重新拉高
_nop_(); //一个机器周期指令
}
/*器件应答与总线应答公用函数 由于这部分代码相同 所以写成一个函数 以节省空间*/
void at24cxx_ricom() //器件应答与总线应答检测 公用函数
{
uchar AT24_NUM; //定义变量 用来无应答时跳出循环判断应答
I2C_SCL=0; //总线应答额外脉冲
_nop_(); //一个机器周期指令
I2C_SDA=1; //拉高数据线 以检测应答
_nop_(); //一个机器周期指令
I2C_SCL=1; //应答时钟脉冲
_nop_(); //一个机器周期指令
while(I2C_SDA) //判断应答
{
if(AT24_NUM<255)//判断累加 总线应答检测最大时间(次数) 避免无应答时程序死循环
{AT24_NUM++;} //没有到则自+
else //否则
{break;} //退出循环判断应答
}
}
温馨提示:答案为网友推荐,仅供参考
第1个回答 2012-07-22
子函数,用 return 语句,向主函数,分别返回0或1。
返回的值,在主函数里面,进行判断,再分别处理。
又是什么作用???
具体作用,要看主函数中的代码。
返回的值,在主函数里面,进行判断,再分别处理。
又是什么作用???
具体作用,要看主函数中的代码。
第2个回答 2012-07-21
return(0)返回的意思是假 return(1)返回的意思是真
第3个回答 2012-07-21
函数值