52单片机iic读写c语言,如何52单片机的I2C读写24C08程序问题排查修改

37adf77e240b913c367f6d447d41c09b.gif ------波形在一楼

isoimg2130老师提供在单片机正常运行的程序:

#include "reg52.h"

#include  "intrins.h"

typedef unsigned char u8;

sbit SCL=P2^1;                                             //I2C  时钟

sbit SDA=P2^2;                                             //I2C  数据

void delay()                                                   //4微秒延时函数

{

_nop_();

_nop_();

_nop_();

_nop_();

}

void yanshi(unsigned int hm)                  //延时毫秒

{

unsigned int i;

do

{

i = 12000000 / 97560;

while(--i)        ;

}

while(--hm);

}

void Start_I2c()

{

SDA=1;                                                 //发送起始条件的数据信号

SCL=1;

delay();

SDA=0;                                                 //发送起始信号

delay();

SCL=0;                                               //钳住I2C总线,准备发送或接收数据

}

void Stop_I2c()

{

SCL=0;

SDA=0;                                              //发送结束条件的数据信号

delay();

SCL=1;                                              //结束条件建立时间大于4μs

SDA=1;                                                      //发送I2C总线结束信号

delay();

}

u8 I2c_wait_ack(void)                                  //等待应答信号到来         1,接收应答失败 0,接收应答成功

{

u8 Time=0;

SDA=1;                                        //准备接收应答位

_nop_();

SCL=1;

_nop_();

while(SDA)

{

Time++;

if(Time>250)

{

Stop_I2c();

return 1;                                 //无应答返回1

}

}

SCL=0;                                                        //时钟输出0

return 0;                                                   //有应答返回0

}

void  SendByte(u8  c)                                //字节数据发送函数

{

u8  BitCnt;                                                   //条件 一定要开启总线 保持SCL处于0状态 才能进行写入

for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位

{

SDA=c<

_nop_();

SCL=1;                               //置时钟线为高,通知被控器开始接收数据位

_nop_();

SCL=0;

_nop_();

}

}

void I2C_Ack(void)                                          //产生ACK应答

{

SCL=0;

delay();

SDA=1;

delay();

SDA=0;

delay();

SCL=1;

delay();

SCL=0;

delay();

SDA=1;

delay();

}

void I2C_NAck(void)                                           //不产生ACK应答

{

SCL=0;

delay();

SDA=1;

delay();

SCL=1;

delay();

SCL=0;

delay();

SDA=0;

delay();

}

u8 RcvByte(u8 ack)                                        //字节数据接收函数

{                                                                         //ack  1 发送应答  0 不发送应答

u8 retc=0,i;

SDA=1;

delay();

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

{

SCL=0;                          //置时钟线为低,准备接收数据位

delay();

SCL=1;                          //置时钟线为高使数据线上数据有效

_nop_();

retc<<=1;

if(SDA)retc++;                      //读数据位,接收的数据位放入retc中

_nop_();

}

if (!ack)

I2C_NAck();                                                //发送nACK

else

I2C_Ack();                                                 //发送ACK

return retc;

}

u8 AT24C_Rcvone(u8 Addr)                           //在AT24CXX指定地址读出一个数据

{

u8 temp=0;

Start_I2c();                                //启动总线

SendByte(0xa0);                             //发送写命令

I2c_wait_ack();                                           //等待应答

SendByte(Addr);                             //发送地址

I2c_wait_ack();                                           //等待应答

Start_I2c();                                //重新启动总线

SendByte(0xa1);                                       //设置为读操作

I2c_wait_ack();                                           //等待应答;

temp=RcvByte(0);                                           //读字节        非应答

Stop_I2c();                                 //结束总线

return temp;

}

void AT24C_Sendone(u8 Addr,u8 Data)        //在AT24CXX指定地址写入一个数据         此函数只限于 c02-c16

{

Start_I2c();                               //启动总线

SendByte(0xa0);                            //发送写命令

I2c_wait_ack();                                          //等待应答

SendByte(Addr);                            //发送地址

I2c_wait_ack();                                          //等待应答

SendByte(Data);                                          //发送字节数据

I2c_wait_ack();                                          //等待应答

Stop_I2c();                                //结束总线

yanshi(10);                                                  //如果是连续发送字节的时候这个延时很重要 否则将回传错

}

void main()

{

AT24C_Sendone(10,0xaa);

P1=AT24C_Rcvone(10);

while(1);

}

下面是书本示例运行没有读出数据led灯不亮:

I2C.H

#ifndef __I2C_H__   //文件名全部都大写,首尾各添加2个下划线”__”

#define __I2C_H__

#include

#define uchar unsigned char

sbit SDA=P2^0;  //24C02芯片SDA引脚位定义

sbit SCL=P2^2;         //24C02芯片SCL引脚位定义

void delay();              //分别对各函数声明

void start();

void stop();

void ack();

void nack();

void write_byte(uchar date);

uchar read_byte();

void write_at24c02(uchar address ,uchar date);

uchar read_at24c02(uchar address);

#endif

I2C.c

#include "i2c.h"  //包含i2c.h头文件,注意自建的头文件是用双引号

void delay()   //微秒级延时函数

{

;;  //用两个空语句实现短时间延时,当晶振为11.0592MHz时,约4~5微秒

}

void start() //起始信号

{

SDA=1;

SCL=1;

delay();

SDA=0;

delay();

}

void stop()        //终止信号

{

SDA=0;

SCL=1;

delay();

SDA=1;

delay();

}

void ack()        //应答信号

{

uchar i;

SCL=1;

delay();

while((SDA==1)&&i<250)i++;

SCL=0;

delay();

}

void nack()          //无应答信号

{

SCL=1;

delay();

SDA=1;

SCL=0;

delay();

}

void  write_byte(uchar date) //写入一个字节到I2C总线

{

uchar i,temp;

temp=date;

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

{

temp=temp<<1;

SCL=0;

delay();

SDA=CY;

delay();

SCL=1;

}

SCL=0;

delay();

SDA=1;

delay();

}

uchar read_byte() //从I2C读一个字节

{

uchar i,j,k;

SCL=0;

delay();

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

{

SCL=1;

delay();

j=SDA;

k=(k<<1)|j;

SCL=0;

delay();

}

return k;

}

void wrte_at2402(uchar address,uchar date)//at24c02按字节写入函数

{

start();

write_byte(0xa0);

ack();

write_byte(address);

ack();

write_byte(date);

ack();

stop();

}

uchar read_dat24c02(uchar address)        //对at24c02随机读函数

{

uchar date;

start();

write_byte(0xa0);

ack();

write_byte(address);

ack();

start();

write_byte(0xa1);

ack();

date=read_byte();

nack();

stop();

return date;

}

main.c

#include

#include"I2C.h"

#include

void delay_10ms()

{

uchar a,b;

for(a=50;a>0;a--)

for(b=200;b>0;b--) ;

}

void main()

{

start();

write_at24c02(10,0xaa);

delay_10ms();

P1=read_at24c02(10);

while(1);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值