iic.c
来自「基于PIC18F4520的CAT24C021带看门狗EEPROM的读写」· C语言 代码 · 共 232 行
C
232 行
//*一、程序说明:
//1, 24LC02器件地址是1010000R/W.
//2, 数组写入24LC02采取页写方式.
//3, 数组code从24LC02读出时采取自由读方式.
//4, 采用8.00M晶体。
//5,采用软件I2C。
//二、硬件连接:
//, SDA------->23 pin.(当然你可以任意选择脚位)
//2, SCL------->18 Pin.(当然你可以任意选择脚位)
//3, PORTD----->外接8个LED,显示读出的数据,在这里,读出的刚好是一个闪动的流水灯状态。
#include "p18f4520.h"
#define uchar unsigned char
#define SCL TRISCbits.TRISC3
#define SDA TRISCbits.TRISC4
void start_i2c(void);
void stop_i2c(void);
void send_byte(uchar c);
uchar receive_byte(void);
void I_send_str(uchar sla,uchar suba,uchar *s,uchar no);
void delay_250ms(void);
void i2c_error (void);
uchar code0[]={0x90,0x01,0x90,0x01,0x64,0x00,0x01,0x90,0x96,0x00,0x90,0x01,0x90,0x01,0x7C,0x01};
uchar code1[]={0x54,0x00};
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,code0,16); //页写入code数组到24LC02,器件地址为0Xa0,子地址为0X00,共9个数。
delay_250ms();
I_send_str(0xa0,0x10,code1,2);
delay_250ms();
///////////开始读出到D口进行显示,根据Random read时序图。
while (1)
{
/*
for (i=0x00;i<16;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();
}
*/
for (i=0x10;i<18;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(void)
{
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(void)
{
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<<bit_count)&0x80) {SDA=1;}
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 (PORTCbits.RC4==1) ack=0;
else ack=1; //用ASK=1为有应答信号
SCL=0;
Nop();Nop();
}
/*==================================================================
字节数据接收函数
函数原型:uchar receive_byte();
FUNCTION: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数。
===================================================================*/
uchar receive_byte(void)
{
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 (PORTCbits.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<no;i++)
{
send_byte(*s);
if (ack==0) i2c_error();
s++;
}
stop_i2c();
// return(1);
}
/*****************************************************************
延时函数
函数原型: void delay_250ms();
FUNCTION: 延明250ms
*****************************************************************/
void delay_250ms(void)
{
unsigned int d=24999;
while (--d);
}
/*****************************************************************
总线错误函数
函数原型: void i2c_error();
Function: 通过RD7闪动8次表示总线操作失败一次报警。
*****************************************************************/
void i2c_error (void)
{
uchar i;
for (i=0;i<8;i++)
{
PORTDbits.RD7=0;
delay_250ms();
PORTDbits.RD7=1;
delay_250ms();
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?