4270|9

72

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

i2c程序的困惑 [复制链接]

    我的i2c驱动程序没有问题,可以对eeprom进行读写,但是在读写g-sensor(加速度传感器,也是一款支持i2c总线的芯片,里面带有一些寄存器)时出现了问题,测试程序和读写eeprom的差不多,只是将slave address由0x50改成了0x1d,将原来读写eeprom存储空间改成了读写寄存器的值(不知道读eeprom里面的数据和读寄存器的值方法是不是一样?),现在就出现了read address error的错误,我检查了芯片上的sda和scl均有信号,不知道是怎么回事,感觉是mcu根本没有识别这个从设备,也就是说res = ioctl(fd, I2C_SLAVE,CHIP_ADDR);这句程序是无效的,那么怎么判断这个从设备已经挂上去了呢?我的这个错误可能是什么原因呢?希望做过类似开发的指点一下,不胜感激!!!
    附测试程序代码:
#include
#include
#include
#include
#include
#include
#include
#include "pvidef.h"
#include "i2c.h"
#include "i2c-dev.h"

#define CHIP_ADDR         0x1d                                        //g-sensor的slave address
#define PAGE_SIZE         256
#define I2C_DEV "/dev/i2c-0"


static int read_eeprom(int fd, char buf[], int addr, int count)
{
        int res;
        
              if(write(fd, &addr, 1)!=1)                            //错误出现在这里!
              {
                        printf("read address error\n");
                        return -1;
              }
              res = read(fd, buf, count);
       
              printf("The character you input is: %s\n", buf);
              return res;
}


static int write_eeprom(int fd, char buff[], int addr, int count)
{
        int res;
              int i;
              static char sendbuffer[PAGE_SIZE];

              memcpy(sendbuffer+1, buff, count);
              sendbuffer[0] = addr;                //enable write 24C16

              if(write(fd, &addr, 1)!=1)
              {
                        printf("write address error\n");
                        return -1;
              }
             
              res = write(fd, sendbuffer, count+1);
       
}


int i2c_main(void)
{
              int fd, n, res,sn_size;
              unsigned char buf_rd[10];

              fd = open(I2C_DEV,O_RDWR);
              if(fd<0)
              {
                        printf("open failed###\n");
                        return -1;
              }
             
                     
              res = ioctl(fd, I2C_TENBIT, 0);                        //7位slave address                  
              res = ioctl(fd, I2C_SLAVE,CHIP_ADDR);      

              read_eeprom(fd, buf_rd, 32, 1);                        //读g-sensor寄存器的值,寄存器的地址为20h(即32),长度为1个字节
                              
              return 0;
}




最新回复

谢谢friendfish. 问题已经解决了,换了芯片,呵呵。  详情 回复 发表于 2009-3-16 10:28
点赞 关注

回复
举报

63

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
我只用单片机用过I2C,一般错误都是口线没上拉啦,时序过快或过慢等一些小问题
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
可能是外围设备的问题;
能和EEPROM通信说明主机的IIC模块工作正常,不能和传感器通信,可能是该设备有问题,按你说的应该是没有应答信号(来自从设备),建议用示波器看下IIC的整个帧的SDA和SCLK,看看在数据传完后,有没有应答位;
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

4
 
示波器看嘛~
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

5
 
谢谢楼上各位。
我用while语句进行循环读操作:
while(1)
{
    read_eeprom(fd, buf_rd, 32, 1); //读g-sensor寄存器的值,寄存器的地址为20h(即32),长度为1个字节
}

用示波器观察SDA和SCL时发现有向低电平的跳变(这个应该就是ACK吧,正确的波形应该是怎样的?)。但是我发现我将slave address改成任意值得时候都有这种跳变,而且写入寄存器地址的时候都出现错误。所以我感觉mcu还是没有识别g-sensor,读eeprom里面的存储空间和读g-sensor寄存器的值可以用同样的方法吗,到底。
 
 
 

回复

83

帖子

0

TA的资源

一粒金砂(初级)

6
 
引用 5 楼 zheng0929 的回复:
谢谢楼上各位。
我用while语句进行循环读操作:
while(1)
{
read_eeprom(fd, buf_rd, 32, 1); //读g-sensor寄存器的值,寄存器的地址为20h(即32),长度为1个字节
}

用示波器观察SDA和SCL时发现有向低电平的跳变(这个应该就是ACK吧,正确的波形应该是怎样的?)。但是我发现我将slave address改成任意值得时候都有这种跳变,而且写入寄存器地址的时候都出现错误。所以我感觉mcu还是没有识别g-sensor,读eeprom里面的存…

既然你看了波形,就比较一下看看;
但是我发现我将slave address改成任意值得时候都有这种跳变
IIC的协议是广播协议,挂在总线上的模块都会收到Master的数据,然后会和自己的地址做比较,然后做出反应,上面你那么说,个人很怀疑那个ACK信号是否正常,建议你换回读写EEPROM,然后咱看看ACK,以作比较;

另外,读写外围设备的方法是不一样的,具体方法要看设备的规格书,看看设备对自己的通信协议是怎么定义的,比如读写EEPROM,你是参照EEPROM的规格书,先发设备地址,然后发读写地址(包含读写命令),然后写数据;甚至EEPROM支持按页写,地址会自动加;所以这是设备定义的;如果你怀疑你读写传感器的方法,你看看你的传感器规格书,看看上面是怎么定义的;
好运哦~
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

7
 
谢谢friendfish!

我比较了挂eeprom和挂sensor的波形,在读一个字节的时候是一样的,都是大约过10ms有一个向低电平的跳变,但在读多个字节的时候eeprom便会有几次跳变,而sensor好像还是这样。

我查看了sensor的datasheet,也是先发设备地址,然后发读写地址(包含读写命令),然后写数据,也支持多字节读写。

我感觉原因可能有两个:

1、就像friendfish兄说的,ack信号不正常。那么,是不是像这种向低电平的跳变都是slave address指定的从设备发出的?就是说,是不是挂在总线上的从设备收到Master的数据,然后会和自己的地址做比较,一致的话才会发出ack信号。如果不是的话,我这个低电平哪来的呢。

2、sensor和mcu已经建立起联系了, read_eeprom(fd, buf_rd, 0x0f, 1)的写法不对。就是说: 读eeprom 0x0f处的数据和读sensor地址为0x0f的寄存器的值,这是一回事吗?能不能用同一个函数来实现。
 
 
 

回复

82

帖子

0

TA的资源

一粒金砂(初级)

8
 
1、就像friendfish兄说的,ack信号不正常。那么,是不是像这种向低电平的跳变都是slave address指定的从设备发出的?就是说,是不是挂在总线上的从设备收到Master的数据,然后会和自己的地址做比较,一致的话才会发出ack信号。如果不是的话,我这个低电平哪来的呢。
ACK信号是要接收数据的那一方发出的,在这里就是你的SLAVE 设备。你能把你抓到的I2C波形图贴出来吗。 ACK信号一般是在第九个时钟的上升沿或下降沿去给出,也就是SDA的值。

2、sensor和mcu已经建立起联系了, read_eeprom(fd, buf_rd, 0x0f, 1)的写法不对。就是说: 读eeprom 0x0f处的数据和读sensor地址为0x0f的寄存器的值,这是一回事吗?能不能用同一个函数来实现。
你最好能把EEPROM和SENSOR的DATASHEET看清楚,看是不是一回事。  如果都是读地址的值当然可以用同一个函数。
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

9
 
引用 7 楼 zheng0929 的回复:
谢谢friendfish!

我比较了挂eeprom和挂sensor的波形,在读一个字节的时候是一样的,都是大约过10ms有一个向低电平的跳变,但在读多个字节的时候eeprom便会有几次跳变,而sensor好像还是这样。

我查看了sensor的datasheet,也是先发设备地址,然后发读写地址(包含读写命令),然后写数据,也支持多字节读写。

我感觉原因可能有两个:

1、就像friendfish兄说的,ack信号不正常。那么,是不是像这种向低电平的跳变都是…

问题现在到什么阶段了?
怎么老感觉你和传感器的通信方式有问题(只是感觉),要不把Datesheet贴出来看看~
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

10
 
谢谢friendfish.
问题已经解决了,换了芯片,呵呵。
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表