您需要 登录 才可以下载或查看,没有账号?注册
收藏0 举报
ayb_ice 发表于 2018-11-19 08:40 最简单的方法,高低电平各延时2US,读取数据时延时1US
c834706901 发表于 2018-11-19 10:45 你是怎么判断延时这么长时间的呢
c834706901 发表于 2018-11-18 23:17 有人教教我吗,教会我50元红包 加Q直接发
ayb_ice 发表于 2018-11-19 11:39 上面不是写的 SCL高电平时间吗,最小0.6,可以大于这个时间,不可以小于这个时间,所以2US是合适的。。。 ...
c834706901 发表于 2018-11-19 12:15 下面的sda保持时间和有效时间是什么意思是,有什么作用吗
玄德 发表于 2018-11-20 21:18 启动或者读写数据的时候延时多少 这句话是什么意思? 你究竟想知道什么参数?
c834706901 发表于 2018-11-23 09:07 我就是想知道delay(4) delay(2)这些延时是怎么得出来的
#include "stc15f2k60s2.h" #include <intrins.h> #include "Delay.h" #include "I2C.h" void Start_I2c(void); void Stop_I2c(void); unsigned char I2c_wait_ack(void); void Ack_I2c(void); void Nack_I2c(void); void SendByte(unsigned char ); unsigned char RcvByte(); //起动总线函数 //Start_I2c(); //功能:启动I2C总线,即发送I2C起始条件. void Start_I2c() { SCL=1; Delay5us(); //tSU:STA SDA=0; //发送起始信号 Delay5us(); //tHD:STA SCL=0; //条件保持SCL处于0状态才能进行写入 } //结束总线函数 //Stop_I2c(); //功能:结束I2C总线,即发送I2C结束条件. void Stop_I2c() { SCL=0; SDA=0; Delay5us(); //tSU:STO SCL=1; //结束条件建立时间大于4μs Delay5us(); //tBUF总线空闲时间大于4.7us SDA=1; //发送I2C总线结束信号 } //等待应答信号到来 //返回值:1,接收应答失败 // 0,接收应答成功 u8 I2c_wait_ack(void) { u8 Time=0; SCL=0; SDA=1; //准备接收应答位 Delay5us(); //tAA tLOW SCL=1; Delay5us(); //tHIGH while(SDA) { Time++; if(Time>250) { Stop_I2c(); return 1; //超时检测无应答返回1 } } SCL=0; //时钟输出0 return 0; //有应答返回0 } 复制<blockquote> //字节数据发送函数 //SendByte(u8 DAT); //功能: 将数据DAT发送出去,可以是地址,也可以是数据 void SendByte(u8 DAT) { u8 i=0; SCL=0; for(i=0;i<8;i++) //要传送的数据长度为8位 { if((DAT<<i)&0x80) { SDA=1; //判断发送位 发送是由高位开始发送 } else { SDA=0; } Delay5us(); SCL=1; //置时钟线为高,通知被控器开始接收数据位 Delay5us(); SCL=0; //出函数保持SLC=0 _nop_(); //tHD 数据输出保持时间0ns } } //功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号), //发完后请用应答函数应答从机。 u8 RcvByte() { u8 Dat=0; u8 i=0; for(i=0;i<8;i++) { SCL=0; //置时钟线为低,准备接收数据位 _nop_(); //tDH从器件数据输出保持时间100ns SDA=1; //释放总线准备接收数据位 Delay5us(); SCL=1; //置时钟线为高使数据线上数据有效 Dat<<=1; //最后一位不需要移位,所以移位放在此处 if(SDA==1) { Dat|=0x01; //读数据位,接收的数据位放入Dat中 } Delay5us(); } SCL=0; //出函数保持SLC=0 _nop_(); //tDH从器件数据输出保持时间100ns return Dat; } //应答子函数 //主机应答 void Ack_I2c(void) { SCL=0; SDA=0; Delay5us(); SCL=1; Delay5us(); SCL=0; //清时钟线,钳住I2C总线以便继续接收 } //主机不应答 void Nack_I2c(void) { SCL=0; SDA=1; Delay5us(); SCL=1; Delay5us(); SCL=0; } 复制 /*************************此部分为AT2402的驱动程序使用I2C总线连接*************************************/ #include "stc15f2k60s2.h" #include "Delay.h" #include "24C04.h" #include "I2C.h" //24c 默认的硬件地址都是 0xa0 即 1010 然后A2 A1 A0 最后一位 为读写位 1读 0写 //24c02 256x8 bit //24c04 512x8 bit //而子地址 只是8位的 即最大也就256个字节 那么24c04 就要占用2个256个字节 //这里24c04硬件上采用的是 分页方法 即有24c02里有A2 A1 A0 当是24c04时 A0做为分页位 //当A0为0 表示第一页 写入第一页256字节 //当A0为1 表示第二页 写入第二页256字节 //在AT24CXX指定地址读出一个数据 //Addr:开始读数的地址 //返回值 :读到的数据 u8 AT24C_Rcvone(u8 Addr) { u8 temp=0; Start_I2c(); //启动总线 SendByte(0xa0); //发送器件I2C地址,写模式 I2c_wait_ack(); //等待应答 SendByte(Addr); //发送器件存储地址 I2c_wait_ack(); //等待应答 Start_I2c(); //重新启动总线 SendByte(0xa1); //设置为读操作 I2c_wait_ack(); //等待应答; temp=RcvByte(); //读字节 Nack_I2c(); //非应答 Stop_I2c(); //结束总线 return temp; } //在AT24CXX指定地址写入一个数据 此函数只限于 c02-c16 //Addr:写入数据的目的地址 //Data:要写入的数据 void AT24C_Sendone(u8 Addr,u8 Data) { Start_I2c(); //启动总线 SendByte(0xa0); //发送写命令 I2c_wait_ack(); //等待应答 SendByte(Addr); //发送地址 I2c_wait_ack(); //等待应答 SendByte(Data); //发送字节数据 I2c_wait_ack(); //等待应答 Stop_I2c(); //结束总线 Delay10ms(); //tWR 周期,等待I2C器件写完毕 } 楼主搞定了没,你对着我严格按datasheet写24C04的100K SCL程序,注意红色的标注的地方,不同器件参数不太一样,要全部通用的话可以统一延迟为1us, 那么就可以对应上你的器件上的最大900ns
<blockquote> //字节数据发送函数 //SendByte(u8 DAT); //功能: 将数据DAT发送出去,可以是地址,也可以是数据 void SendByte(u8 DAT) { u8 i=0; SCL=0; for(i=0;i<8;i++) //要传送的数据长度为8位 { if((DAT<<i)&0x80) { SDA=1; //判断发送位 发送是由高位开始发送 } else { SDA=0; } Delay5us(); SCL=1; //置时钟线为高,通知被控器开始接收数据位 Delay5us(); SCL=0; //出函数保持SLC=0 _nop_(); //tHD 数据输出保持时间0ns } } //功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号), //发完后请用应答函数应答从机。 u8 RcvByte() { u8 Dat=0; u8 i=0; for(i=0;i<8;i++) { SCL=0; //置时钟线为低,准备接收数据位 _nop_(); //tDH从器件数据输出保持时间100ns SDA=1; //释放总线准备接收数据位 Delay5us(); SCL=1; //置时钟线为高使数据线上数据有效 Dat<<=1; //最后一位不需要移位,所以移位放在此处 if(SDA==1) { Dat|=0x01; //读数据位,接收的数据位放入Dat中 } Delay5us(); } SCL=0; //出函数保持SLC=0 _nop_(); //tDH从器件数据输出保持时间100ns return Dat; } //应答子函数 //主机应答 void Ack_I2c(void) { SCL=0; SDA=0; Delay5us(); SCL=1; Delay5us(); SCL=0; //清时钟线,钳住I2C总线以便继续接收 } //主机不应答 void Nack_I2c(void) { SCL=0; SDA=1; Delay5us(); SCL=1; Delay5us(); SCL=0; } 复制 /*************************此部分为AT2402的驱动程序使用I2C总线连接*************************************/ #include "stc15f2k60s2.h" #include "Delay.h" #include "24C04.h" #include "I2C.h" //24c 默认的硬件地址都是 0xa0 即 1010 然后A2 A1 A0 最后一位 为读写位 1读 0写 //24c02 256x8 bit //24c04 512x8 bit //而子地址 只是8位的 即最大也就256个字节 那么24c04 就要占用2个256个字节 //这里24c04硬件上采用的是 分页方法 即有24c02里有A2 A1 A0 当是24c04时 A0做为分页位 //当A0为0 表示第一页 写入第一页256字节 //当A0为1 表示第二页 写入第二页256字节 //在AT24CXX指定地址读出一个数据 //Addr:开始读数的地址 //返回值 :读到的数据 u8 AT24C_Rcvone(u8 Addr) { u8 temp=0; Start_I2c(); //启动总线 SendByte(0xa0); //发送器件I2C地址,写模式 I2c_wait_ack(); //等待应答 SendByte(Addr); //发送器件存储地址 I2c_wait_ack(); //等待应答 Start_I2c(); //重新启动总线 SendByte(0xa1); //设置为读操作 I2c_wait_ack(); //等待应答; temp=RcvByte(); //读字节 Nack_I2c(); //非应答 Stop_I2c(); //结束总线 return temp; } //在AT24CXX指定地址写入一个数据 此函数只限于 c02-c16 //Addr:写入数据的目的地址 //Data:要写入的数据 void AT24C_Sendone(u8 Addr,u8 Data) { Start_I2c(); //启动总线 SendByte(0xa0); //发送写命令 I2c_wait_ack(); //等待应答 SendByte(Addr); //发送地址 I2c_wait_ack(); //等待应答 SendByte(Data); //发送字节数据 I2c_wait_ack(); //等待应答 Stop_I2c(); //结束总线 Delay10ms(); //tWR 周期,等待I2C器件写完毕 } 楼主搞定了没,你对着我严格按datasheet写24C04的100K SCL程序,注意红色的标注的地方,不同器件参数不太一样,要全部通用的话可以统一延迟为1us, 那么就可以对应上你的器件上的最大900ns
/*************************此部分为AT2402的驱动程序使用I2C总线连接*************************************/ #include "stc15f2k60s2.h" #include "Delay.h" #include "24C04.h" #include "I2C.h" //24c 默认的硬件地址都是 0xa0 即 1010 然后A2 A1 A0 最后一位 为读写位 1读 0写 //24c02 256x8 bit //24c04 512x8 bit //而子地址 只是8位的 即最大也就256个字节 那么24c04 就要占用2个256个字节 //这里24c04硬件上采用的是 分页方法 即有24c02里有A2 A1 A0 当是24c04时 A0做为分页位 //当A0为0 表示第一页 写入第一页256字节 //当A0为1 表示第二页 写入第二页256字节 //在AT24CXX指定地址读出一个数据 //Addr:开始读数的地址 //返回值 :读到的数据 u8 AT24C_Rcvone(u8 Addr) { u8 temp=0; Start_I2c(); //启动总线 SendByte(0xa0); //发送器件I2C地址,写模式 I2c_wait_ack(); //等待应答 SendByte(Addr); //发送器件存储地址 I2c_wait_ack(); //等待应答 Start_I2c(); //重新启动总线 SendByte(0xa1); //设置为读操作 I2c_wait_ack(); //等待应答; temp=RcvByte(); //读字节 Nack_I2c(); //非应答 Stop_I2c(); //结束总线 return temp; } //在AT24CXX指定地址写入一个数据 此函数只限于 c02-c16 //Addr:写入数据的目的地址 //Data:要写入的数据 void AT24C_Sendone(u8 Addr,u8 Data) { Start_I2c(); //启动总线 SendByte(0xa0); //发送写命令 I2c_wait_ack(); //等待应答 SendByte(Addr); //发送地址 I2c_wait_ack(); //等待应答 SendByte(Data); //发送字节数据 I2c_wait_ack(); //等待应答 Stop_I2c(); //结束总线 Delay10ms(); //tWR 周期,等待I2C器件写完毕 } 楼主搞定了没,你对着我严格按datasheet写24C04的100K SCL程序,注意红色的标注的地方,不同器件参数不太一样,要全部通用的话可以统一延迟为1us, 那么就可以对应上你的器件上的最大900ns
本版积分规则 发表回复 回帖并转播 回帖后跳转到最后一页
等级类勋章
发帖类勋章
时间类勋章
人才类勋章
13
29
1
扫码关注 21ic 官方微信
扫码关注嵌入式微处理器
扫码关注电源系统设计
扫码关注21ic项目外包
扫码浏览21ic手机版
本站介绍 | 申请友情链接 | 欢迎投稿 | 隐私声明 | 广告业务 | 网站地图 | 联系我们 | 诚聘英才
京公网安备 11010802024343号