PIC单片机的I2C 24LC02 C读写程序

pic单片机的i2c 24lc02 c读写程序
1 i2c总线特点
i2c总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此i2c总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10kbps的最大传输速率支持40个组件。i2c总线的另一个优点是,它支持多主控(multimastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。
2 i2c总线工作原理
i2c总线上的数据稳定规则,scl为高电平时sda上的数据保持稳定,scl为低电平时允许sda变化。如果scl处于高电平时,sda上产生下降沿,则认为是起始位,sda上的上升沿认为是停止位。通信速率分为常规模式(时钟频率100khz)和快速模式(时钟频率400khz)。同一总线上可以连接多个带有i2c接口的器件,每个器件都有一个唯一的地址,既可以是单接收的器件,也可以是能够接收发送的器件。
每次数据传输都是以一个起始位开始,而以停止位结束。传输的字节数没有限制。最高有效位将首先被传输,接收方收到第8位数据后会发出应答位。数据传输通常分为两种:主设备发送从设备接收和从设备发送主设备接收。这两种模式都需要主机发送起始位和停止位,应答位由接收方产生。从设备地址一般是1或2个字节,用于区分连接在同一i2c上的不同器件。
i2c总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。
开始信号:scl为高电平时,sda由高电平向低电平跳变,开始传送数据。
结束信号:scl为高电平时,sda由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的ic在接收到8bit数据后,向发送数据的ic发出特定的低电平脉冲,表示已收到数据。cpu向受控单元发出一个信号后,等待受控单元发出一个应答信号,cpu接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。
在i2c总线中只有主发送和主接收两种操作方式。在系统初始化时,由指令控制cpu送出相关的数据,经接口送到i2c寄存器内。通过初始化这些寄存器,可以实现i2c总线的主模式控制,以及实现i2c总线上的从设备读写。
当主设备和其中的一个从设备交换数据时,主设备首先发出一个启动start信号,这个信号被所有的从设备接收。即从设备准备接收cpu的信号,然后主设备再发出它要通信的从设备地址。接下来,所有的从设备将收到的这个地址和它们自己的地址进行比较。
如果收到的地址和它们自己的地址不同,则什么都不做,只是等待主设备发出停止stop信号;如果收到的地址和它自己的地址相同,它就发出一个信号给主设备,这个信号称为应答acknowledge信号。当主设备收到应答信号后,它就开始向从设备发送数据或者从从设备接收数据。当所有操作都进行完毕时,主设备发出一个stop信号,通信完毕,释放i2c总线;然后所有的从设备都等待下一次start信号的到来。
3 总线基本操作
i2c规程运用主/从双向通讯。器件发送数据到总线上,则定义为发送器,器件接收数据则定义为接收器。主器件和从器件都可以工作于接收和发送状态。 总线必须由主器件(通常为微控制器)控制,主器件产生串行时钟(scl)控制总线的传输方向,并产生起始和停止条件。sda线上的数据状态仅在scl为低电平的期间才能改变,scl为高电平的期间,sda状态的改变被用来表示起始和停止条件。
3.1 控制字节
在起始条件之后,必须是器件的控制字节,其中高四位为器件类型识别符(不同的芯片类型有不同的定义,eeprom一般应为1010),接着三位为片选,最后一位为读写位,当为1时为读操作,为0时为写操作。
1.写过程
(1)上电后等待一个延时(1ms)。
(2)器件寻址,给一个起始信号(scl为高电平时sda给一个下降沿)。发送从器件地址,高5位为10110,然后根据a1/a0(如果和器件的地址相同则那个器件会应答)进行读/写控制(o为读)。
(3)应答,器件在scl的第9个周期时sda给出一个低电平,作为应答信号。
(4)开始写有两种模式:字节写模式和页写模式。
·字节模式:给出a15~a8应答,给出a7~a0应答;然后给出data和停止信号 (scl为高电平时,sda给出一个上升沿),接着要等待一个擦写时间。
·页写模式:给出地址以后连续给出64个数据。如果多于64个数据,则地址计数器自动翻转。(如果少于64昵,估计是没有问题的,但是需要实验验证。)
(5)判断擦写操作是否完毕的一个方法(应答查询),如果器件还处于擦写状态,则不会应答器件寻址;如果有应答,则说明擦写完毕。
2.读过程
(1)上电以后等待一个延时(lms)。
(2)器件寻址。
(3)应答。
(4)开始读有三种模式:立即当前地址读、选择/随机读、连续读。
·立即当前地址读:如果上次读/写的操作地址为n,则现在是n+1。不需要ack,但是需要stop信号。
·选择/随机读:先伪写(用于给出一个地址),然后再次启动,读取数据。
·连续读:读取一个以后给一个应答,这样器件会再给出下一个地址的数据内容。
(5)开始数据传输start后、停止数据传输stop前,scl高电平期间,sda上为有效数据。
/***********************************************************
一、程序说明:
1, 24lc02器件地址是1010000r/w.
2, 数组写入24lc02采取页写方式.
3, 数组code从24lc02读出时采取自由读方式.
4, 采用4.00m晶体。
5,采用软件i2c。
二、硬件连接:
1, sda------->23 pin.(当然你可以任意选择脚位)
2, scl------->18 pin.(当然你可以任意选择脚位)
3, portd----->外接8个led,显示读出的数据,在这里,读出的刚好是一个闪动的流水灯状态。
**************************************************************/
#i nclude pic.h
#define uchar unsigned char
#define nop() asm(nop
#define scl trisc3
#define sda trisc4
void start_i2c();
void stop_i2c();
void send_byte(uchar c);
uchar receive_byte();
void i_send_str(uchar sla,uchar suba,uchar *s,uchar no);
void delay_250ms();
void i2c_error ();
uchar code[]={0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
uchar no,ack,c,data;
void main(void)
{
uchar i;
trisc=0xff; //c口设为输入 rc3为scl线,rc4为sda线。
portc=0x00;
trisd=0x00; //d口为输出,显示ic24lc02中读出的内容
portd=0x00; //初始显示全亮
i_send_str(0xa0,0x00,code,9); //页写入code数组到24lc02,器件地址为0xa0,子地址为0x00,共9个数。
delay_250ms();
///////////开始读出到d口进行显示,根据random read时序图。
while (1)
{
for (i=0x00;i<0x09;i++)
{
start_i2c();
send_byte(0xa0); //发送器件地址,即device address。
if (ack==0) i2c_error(); //如果24lc02无应答。则进入i2c error错误指示。
send_byte(i); //发送字地址,即word address。d口显示数组。
if (ack==0) i2c_error();
start_i2c(); //重新启动总线。
send_byte(0xa1); //发送读命令和器件地址device address。
if (ack==0) i2c_error();
data=receive_byte();
stop_i2c();
portd=data;
delay_250ms();
}
}
}
/*************************************************************
起动总线函数
函数原型: void start_i2c();
function: start on the i2c bus
*************************************************************/
void start_i2c()
{
sda=1; //发送启始条件的数据信号
nop();
scl=1;
nop();nop();nop();nop();nop(); //24lc02要求建立时间大于4,7s
sda=0; //发送起始信号
nop();nop();nop();nop();nop();
scl=0; //钳住i2c总线,准备发送数据或接收数据
nop();nop();
}
/*************************************************************
停止总线函数
函数原型: void stop_i2c();
function: stop the i2c bus
**************************************************************/
void stop_i2c()
{
sda=0; //发送结束条件的数据信号
nop();
scl=1;
nop();nop();nop();nop();nop();
sda=1;
nop();nop();nop();nop();
}
/*====================================================
字节数据传送函数
函数原型: void send_byte(uchar c);
function: 将数据c发送出去,可以是地址,也可以是数据,发完后等待回应,并对此状态
位进行操作(不应答或非应答都使ack=0 ),发送数据正常,ack=1;ack=0
表示被控器无应答或损坏。
====================================================*/
void send_byte(uchar c)
{
uchar bit_count;
for (bit_count=0;bit_count<8;bit_count++)
{
if ((c<else {sda=0;}
nop();
scl=1;
nop();nop();nop();nop();nop();
scl=0;
}
nop();nop();
sda=1;
nop();nop();
scl=1;
nop();nop();nop();
if (rc4==1) ack=0;
else ack=1; //用ask=1为有应答信号
scl=0;
nop();nop();
}
/*================================================
字节数据接收函数
函数原型:uchar receive_byte();
function: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数。
====================================================*/
uchar receive_byte()
{
uchar retc,bit_count;
retc=0;
sda=1;
for (bit_count=0;bit_count<8;bit_count++)
{
nop();
scl=0;
nop();nop();nop();nop();nop();
scl=1;
nop();nop();
retc=retc<<1;
if (rc4==1) retc=retc+1;
nop();nop();
}
scl=0;
nop();nop();
return (retc);
}
/*=================================================
向有子地址器件发送多字节数据函数
函数原型: bit i_send_str(uchar sla,uchar suba,uchar *s,uchar no);
function: 从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla。如果
返回1表示操作成功,否则操作有误。
================================================*/
void i_send_str(uchar sla,uchar suba,uchar *s,uchar no)
{
uchar i;
start_i2c();
send_byte(sla);
if (ack==0) i2c_error();
send_byte(suba);
if (ack==0) i2c_error();
for (i=0;i{
send_byte(*s);
if (ack==0) i2c_error();
s++;
}
stop_i2c();
// return(1);
}
/*****************************************************************
延时函数
函数原型: void delay_250ms();
function: 延明250ms
*****************************************************************/
void delay_250ms()
{
unsigned int d=24999;
while (--d);
}
/*****************************************************************
总线错误函数
函数原型: void i2c_error();
function: 通过rd7闪动8次表示总线操作失败一次报警。
*****************************************************************/
void i2c_error ()
{
uchar i;
for (i=0;i<8;i++)
{
rd7=0;
delay_250ms();
rd7=1;
delay_250ms();
}
}
/**********end**************/

针对MOS管寄生参数振荡损坏电路仿真模拟方案
Android 11 DP2证实附近文件分享功能 与AirDrop竞争
白色LED的恒流驱动
深入推动国家人工智能发展战略在北京落实落地
指导分享高密度光纤配线架安装方法
PIC单片机的I2C 24LC02 C读写程序
减少杂波干扰的可控硅调速电路设计
轻松为医疗传感器和耗材添加内存、安全性、监控和控制
微软可调节滤光镜专利曝光,多个液晶层可进行模式切换
百度释出新AI算法 可提升肿瘤辨识效率与正确性
北京联通联合华为成功完成全球首个5G 承载随流检测方案iFIT试点
E-axle新型高功率密度驱动电机系统介绍
发光二极管的主要分类及应用领域
江苏交通抢抓政策“风口”,车联网领域率先示范试点
随着激光电视的出现 屏幕尺寸增大趋势正将迎来加速期
混合动力汽车在前期设计阶段整改案例
如何理解比特币的真正用途
台积电预计2019年2季度快速增长 贸易战对IC封测产业的影响如何?
“走位”独特的多功能卫星——海洋二号C星成功送入预定轨道
又一显示半导体关键项目落地合肥新站高新区