Facebook移动用户访问时长超过PC,或有利于IPO计划
06-17
我们知道,打电话的时候,当拨打电话时,接听方在拿起电话时肯定会回应“你好”。
这是告诉打电话的人有人在这里。
同理,第九个ACK其实也起到了这样的作用。
当我们发送了 7 位地址和 1 位方向后,如果发送的地址确实存在,那么该地址的设备应该响应一个 ACK??(将 SDA 拉低以输出“0”)。
如果不存在,就不会有“人”对ACK的响应(SDA会保持高电平或者“1”)。
那么我们来写一个简单的程序来访问我们板上EEPROM的地址,写入一个不存在的地址,看看是否可以返回ACK来了解并确认这个问题。
我们板上的EEPROM器件型号是24C02,可以在24C02数据表的3.6节中找到。
24C02的位地址,高4位固定为0b,而低3位地址则根据具体地址而定,电路的设计由A2、A1、A0这三个引脚的实际电平决定。
看一下我们的24C02的电路图,和24C01的原理图一模一样,如图 图24C02原理图 从图中可以看出。
,我们的A2、A1、A0都连接到了GND,也就是说都是0,所以24C02的7位地址实际上是二进制的0b,也就是我们用I2C协议来寻址0x50。
地址不存在的地址 0x62。

寻址完成后,返回的ACK会显示在我们的LCD上,以供比较。
/********************************Lcd.c文件程序源码************ *** *****************/ #include #define LCD_DB P0 sbit LCD_RS = P1^0; sbit LCD_RW = P1 ^1; sbit LCD_E = P1^5; /*等待LCD就绪*/ void LcdWaitReady(){ unsigned char sta; LCD_DB = 0xFF; LCD_RS = 0; LCD_RW = 1; do { LCD_E = 1; sta = LCD_DB; //读取状态字 LCD_E = 0; while (sta & 0x80); //bit7等于1,说明LCD忙,重复检测,直到等于0 } /*向LCD液晶写入一字节命令,cmd-命令为写入值*/ void LcdWriteCmd(unsigned char cmd){ LcdWaitReady(); LCD_RS = 0; LCD_RW = 0; LCD_DB = cmd; LCD_E = 1; LCD_E = 0; } /*向LCD液晶写入一字节数据,dat-要写入的数据值*/ void LcdWriteDat(unsigned char dat){ LcdWaitReady( ); LCD_RS = 1; LCD_RW = 0; LCD_DB = 数据;起始地址,即光标位置,(x,y)——对应屏幕上的字符坐标 */ void LcdSetCursor(unsigned char x, unsigned char y){ unsigned char addr; if (y == 0){ //根据输入的屏幕坐标计算显示RAM的地址 addr = 0x00 + x; //第一行字符地址从0x00开始 }else{ addr = 0x40 + x; //第二行字符地址从0x40 } LcdWriteCmd(addr | 0x80); //设置RAM地址 } /*在LCD上显示字符串,(x ,y)-对应屏幕上的起始坐标,str-字符串指针*/ void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str){ LcdSetCursor(x, y);//设置起始地址 while (*str != '\0'){ //连续写入字符串数据直到检测到结束字符 LcdWriteDat(*str++); } } /*初始化LCD*/ void InitLcd(){ LcdWriteCmd(0x38); //16*2显示,5*7点阵,8位数据接口 LcdWriteCmd(0x0C); //显示屏亮,光标灭 LcdWriteCmd(0x06); //文字不动,地址自动为 LcdWriteCmd(0x01); //清屏 } /**************************** **main.c文件程序源码** ****************************/ #include #include #define I2CDelay() {_nop_( );_nop_();_nop_();_nop_();} sbit I2C_SCL = P3^7; sbit I2C_SDA = P3^6; bit I2CAddressing(unsigned char addr); extern void InitLcd(); extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str); void main(){ 位确认; unsigned char str[10]; InitLcd(); //初始化LCD ack = I2CAddressing(0x50); //查询地址为0x50 str[0] = '5'的设备; //将地址和响应值转换为字符串 str[1] = '0'; str[2] = ':'; str[3] = (unsigned char)ack + '0' ; str[4] = '\0'; LcdShowStr(0, 0, str); //在LCD上显示 ack = I2CAddressing(0x62); //查询地址 对于0x62设备 str[0] = '6'; //将地址和响应值转换为字符串 str[1] = '2'; str[2] = ':' ; str[3] = (unsigned char)ack + '0' ; str[4] = '\0'; LcdShowStr(8, 0, str); //LCD上显示 while (1); } /*产生总线启动信号*/ void I2CStart(){ I2C_SDA = 1; //首先确保SDA和SCL均为高电平 I2C_SCL = 1; I2CDelay(); I2C_SDA = 0; //先将SDA拉低 I2CDelay(); I2C_SCL = 0; //再次拉低SCL } /*产生公交车站信号*/ void I2CStop(){ I2C_SCL = 0; //首先保证SDA和SCL均为低电平 I2C_SDA = 0; I2CDelay() ; I2C_SCL = 1; //先将SCL拉高 I2CDelay(); I2C_SDA = 1; //再次将SDA拉高 I2CDelay(); } /* I2C总线写操作,dat-要写入的字节,返回值-从机响应位的值*/ 位 I2CWrite(unsigned char dat){ 位 ack; // 用于临时存储响应位 Value unsigned char mask; //掩码变量,用于检测字节中的某个位值 for (mask=0x80; mask!=0; mask>>=1){ //从高位到低位依次处理 if ((mask&dat) == 0){ //该位的值输出到SDA I2C_SDA = 0; }else{ I2C_SDA = 1; } I2CDelay (); } I2C_SCL = 1; //将SCL拉高 I2CDelay(); I2C_SCL = 0; //再次将SCL拉低,完成一位周期 //此时读取SDA值,即为从机的响应值 I2CDelay(); I2C_SCL = 0; //再次将SCL拉低完成响应位,并保持总线 返回ack; //返回从机响应值 } /* I2C 寻址函数,即检查地址为 addr 的设备是否存在,返回值 - 从设备响应值 */ bit I2CAddressing(unsigned char addr){ bit ack; I2CStart() ; //生成起始位,即开始总线操作 //设备地址需要左移一位,因为寻址命令的最低位 //是读写位,用于指示后续操作是读还是写 ack = I2CWrite(addr<<1); I2CStop(); //不需要进行后续的读写,而是直接停止本次总线操作 return ack; } 我们在KST-51开发板上运行这个程序后,就会显示我们期望的结果在液晶显示屏上。
主机发送现有从机地址,从机返回响应位,即响应位为0;如果主机发送了不存在的从机地址,则不会有从机响应,即响应位为1。
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
标签:
相关文章
06-17
06-18
06-17
06-18
06-17
06-06
06-17
06-17
最新文章
使用电子管有哪些注意事项?如何检查电子管之间是否短路?
博通支付1200万美元和解SEC财务欺诈指控
八名运营商高管确认加入虚拟运营商
内蒙古农牧区雷电灾害成因分析及防雷对策
北京联通将5G应用于世园会远程医疗急救
TD-SCDMA最后一轮冲刺测试启动,产业前景更加光明
专访阿里云总裁王健:云计算服务平台梦想成真
USB2.0控制器CY7C68013的接口设计与实现