关于I2C程序

关于I2C程序,第1张

AT的没有具体去看他的daatsheep

一般的 24都是允许一次性全部读出的只要你的时序没有问题

另外ack信号迟一点发送 不会影响读写的

你可以仔细看一下 at的 daatsheep看有没有256字节的限制.

普通的24是01-128字节 02=256字节...16=2047字节..

超过部分..器件会自动回到0地址处理,

/////////////////////////////////////////////

看了一下你,后面添加的程序.

如果你这样写.那么read_all那边就不需要用参数了.

因为如果读取,一般都是从0开始读取的..

另外x24c08_read如果是单字节读写函数.而且是正确的话

那么用

for (ii=0ii<4ii++)

{

for (iii=0iii<256iii++)

{

c=x24c08_read(ii,(uchar)iii)

SBUF=c

while (!TI)

这种方式的读取一定是没有问题.

有问题就是你的代码..或者你的eep本身坏了.

如果你感觉时许地上对的话..不妨看一下.

//////////////////////////////////

发送和接收差不多,

这里是个例子,有问题欢迎一起讨论

/*****************************************************

/* 文件名: 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 = 8send_bit <= 0send_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 = 8receive_bit <= 0receive_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

}

//给你一个简单的可断电保存的计时程序,用的是24C08

#include <reg52.h> // 包含51单片机寄存器定义的头文件

#include <intrins.h> //包含_nop_()函数定义的头文件

#define OP_READ 0xa1 // 器件地址以及读取 *** 作,0xa1即为1010 0001B

#define OP_WRITE 0xa0 // 器件地址以及写入 *** 作,0xa1即为1010 0000B

sbit SCL=P3^4//将串行时钟总线SCL位定义在为P3.4引脚

sbit SDA=P3^5 //将串行数据总线SDA位定义在为P3.5引脚

unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}//定义共阳数码管显示字型码

unsigned char sec=0//定义计数值,每过1秒,sec加1

unsigned int count//定时中断次数

bit write=0//写24C08的标志

sbit shiwei=P2^6//十位选通定义

sbit gewei=P2^7//个位选通定义

sbit K5=P3^2 //清0按键

/*****************************************************

函数功能:延时1ms

***************************************************/

void delay1ms()

{

unsigned char i,j

for(i=0i<10i++)

for(j=0j<33j++)

}

/*****************************************************

函数功能:延时若干毫秒

入口参数:n

***************************************************/

void delaynms(unsigned char n)

{

unsigned char i

for(i=0i<ni++)

delay1ms()

}

/***************************************************

函数功能:开始数据传送

***************************************************/

void start()

// 开始位

{

SDA = 1 //SDA初始化为高电平“1”

SCL = 1 //开始数据传送时,要求SCL为高电平“1”

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

SDA = 0 //SDA的下降沿被认为是开始信号

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

SCL = 0 //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)

}

/***************************************************

函数功能:结束数据传送

***************************************************/

void stop()// 停止位

{

SDA = 0//SDA初始化为低电平“0” _n

SCL = 1//结束数据传送时,要求SCL为高电平“1”

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

SDA = 1 //SDA的上升沿被认为是结束信号

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

_nop_()//等待一个机器周期

SDA=0

SCL=0

}

/***************************************************

函数功能:检测应答位

***************************************************/

bit Ask() //检测应答

{

bit ack_bit //储存应答位

SDA = 1 // 发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)释放SDA线,

//以让SDA线转由接收设备(AT24Cxx)控制

_nop_() //等待一个机器周期

_nop_() //等待一个机器周期

SCL = 1 //根据上述规定,SCL应为高电平

_nop_() //等待一个机器周期

_nop_() //等待一个机器周期

_nop_() //等待一个机器周期

_nop_() //等待一个机器周期

_nop_() //等待一个机器周期

ack_bit = SDA//接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个字节

//若送高电平,表示没有接收到,传送异常 结束发送

SCL = 0 //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)

return ack_bit // 返回AT24Cxx应答位

}

/***************************************************

函数功能:从AT24Cxx读取数据

出口参数:x

***************************************************/

unsigned char ReadData()

// 从AT24Cxx移入数据到MCU

{

unsigned char i

unsigned char x //储存从AT24Cxx中读出的数据

for(i = 0i <8i++)

{

SCL = 1 //SCL置为高电平

x<<=1 //将x中的各二进位向左移一位

x|=(unsigned char)SDA //将SDA上的数据通过按位“或“运算存入x中

SCL = 0 //在SCL的下降沿读出数据

}

return(x) //将读取的数据返回

}

/***************************************************

函数功能:向AT24Cxx的当前地址写入数据

入口参数:y (储存待写入的数据)

***************************************************/

//在调用此数据写入函数前需首先调用开始函数start(),所以SCL=0

void WriteCurrent(unsigned char y)

{

unsigned char i

for(i = 0i <8i++) // 循环移入8个位

{

SDA = (bit)(y&0x80) //通过按位“与”运算将最高位数据送到S

//因为传送时高位在前,低位在后

_nop_() //等待一个机器周期

SCL = 1 //在SCL的上升沿将数据写入AT24Cxx

_nop_() //等待一个机器周期

_nop_()//等待一个机器周期

SCL = 0 //将SCL重新置为低电平,以在SCL线形成传送数据所需的8个脉冲

y <<= 1 //将y中的各二进位向左移一位

}

}

/***************************************************

函数功能:向AT24Cxx中的指定地址写入数据

入口参数:add (储存指定的地址);dat(储存待写入的数据)

***************************************************/

void WriteSet(unsigned char add, unsigned char dat)

// 在指定地址addr处写入数据WriteCurrent

{

start() //开始数据传递

WriteCurrent(OP_WRITE) //选择要 *** 作的AT24Cxx芯片,并告知要对其写入数据

Ask()

WriteCurrent(add) //写入指定地址

Ask()

WriteCurrent(dat) //向当前地址(上面指定的地址)写入数据

Ask()

stop() //停止数据传递

delaynms(4) //1个字节的写入周期为1ms, 最好延时1ms以上

}

/***************************************************

函数功能:从AT24Cxx中的当前地址读取数据

出口参数:x (储存读出的数据)

***************************************************/

unsigned char ReadCurrent()

{

unsigned char x

start() //开始数据传递

WriteCurrent(OP_READ) //选择要 *** 作的AT24Cxx芯片,并告知要读其数据

Ask()

x=ReadData()//将读取的数据存入x

stop() //停止数据传递

return x //返回读取的数据

}

/***************************************************

函数功能:从AT24Cxx中的指定地址读取数据

入口参数:set_addr

出口参数:x

***************************************************/

unsigned char ReadSet(unsigned char set_addr)

// 在指定地址读取

{

start() //开始数据传递

WriteCurrent(OP_WRITE) //选择要 *** 作的AT24Cxx芯片,并告知要对其写入数据

Ask()

WriteCurrent(set_addr) //写入指定地址

Ask()

return(ReadCurrent()) //从指定地址读出数据并返回

}

/***********************************************************/

void LEDshow() //LED显示函数

{

P0=table[sec/10]

shiwei=0

delaynms(2)

shiwei=1

P0=table[sec%10]

gewei=0

delaynms(2)

gewei=1

}

/***********************************************************/

/***************************************************

函数功能:主函数

***************************************************/

void main(void)

{

TMOD=0x01//定时器0工作在方式1

ET0=1

EA=1

TH0=(65536-50000)/256//对TH0 TL0赋值

TL0=(65536-50000)%256//使定时器0.05秒中断一次

SDA = 1 // SDA=1,SCL=1,使主从设备处于空闲状态

SCL = 1

sec=ReadSet(2)//读出保存的数据赋于sec

TR0=1//开始计时

while(1)

{

LEDshow()

if(write==1) //判断计时器是否计时一秒

{

write=0//清零

WriteSet(2,sec)//在24c08的地址2中写入数据sec

}

if(K5==0){

delaynms(10)

if(K5==0){

sec=0

}

}

}

}

/**************************************************************/

void t0(void) interrupt 1 using 0 //定时中断服务函数

{

TH0=(65536-50000)/256//对TH0 TL0赋值

TL0=(65536-50000)%256//重装计数初值

count++//每过50ms tcnt加一

if(count==20) //计满20次(1秒)时

{

count=0//重新再计

sec++

write=1//1秒写一次24C08

if(sec==100) //定时100秒,在从零开始计时

{sec=0}

}

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11122319.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-13
下一篇 2023-05-13

发表评论

登录后才能评论

评论列表(0条)

保存