b2c信息网

您现在的位置是:首页 > 未分类 > 正文

未分类

导航读i2c错误(i2c 读)

hacker2022-07-08 18:31:26未分类93
本文目录一览:1、stm32硬件i2c缺陷解决方法2、

本文目录一览:

stm32硬件i2c缺陷解决方法

函数中有一个BUG, 也就是SR2不能用WHILE来轮询,而应直接读出.如下面代码段, 因此,在这里说的这是STM32的BUG其实是我的代码的错误:

I2C2-DR = inerAddress[1];

while( (I2C2-SR1Q_I2C_SR1_BIT_BTF)==0 );

I2C2-SR2; // 正解

2010-4-1 1:44,一直都不相信STM32 的I2C接口会存在问题,因为工作经验无数次告诉我,嵌入式系统设计中的99.999%的问题不会是由于MCU本身的设计问题所引起,绝大部分都是硬件工程师或软件工程师的某个设计缺陷所造成的. 这次的设计经历也不例外.

由于终于可以抽多点时间用于设计STM32的I2C的软件接口, 因此, 决定重构之前用于主从STM32通讯所用的I2C模块(基于I2C中断+状态机收发)。I2C的中断发送模块很快就重构完毕并且强化了错误处理和I2C总线hang的自恢复功能代码模块(I2C BUS Hang:也就是SDA 和SCL都被某Slave DEVICE拉低,大部分发生在主机接收从机传过来的数据包的最后一个字节的数据时,没有发送P(停止位)所造成的,这时Slave device (EEPROM)因为接收不到P,从而会DEAD LOOP地发送数据给主机,在主机方向看,I2C总线就相当于一直处于BUSY的状态,也就是网上问得最多的关于I2C的问题-I2C总线TMD的怎么会突然间死掉了、BUSY了、HANG的原因。)。

本以为I2C中断读模块也会很顺利地完成,但是却被卡住了一整天,只要加一个断点,在大部份代码处加无所谓,读FUN每次都正确执行,但只要全速运行,就只能运行一次,然后就过不去了,而且过不去的地方并不固定。由于DUBEG得有点集中不了精力,于是就做好问题的Brainstrom的笔记,放了下,晚上出差到深圳,到客户处做系统需求的讨论会,主要是上位机部分的。然后第二天晚上又赶回来,在车上的半梦半觉中让潜意思去思考。回到家后,选择在我的生物钟的最佳的时侯,晚上10点。开始重新在问题的Brainstorm处接着DUBGE。WORK PLAN如下:

(1)把程序恢复到测试I2C写的测试用例状态,PASS。

(2)一小段代码就DEBUG一次的步步为营方法,按之前的思路把代码加入到读的模块(忽略防守代码,只加入必需的功能代码)。都OK后,全速运行,XXX,又卡住了。细过了一片读模块。PASS。于是进入计划中的(3)

(3)全速运行,然后在可能卡住的地方加上断点,而不是之前的先加断点,然后运行的方式(这种方式,已确认PASS):

加了几处后,发现程序是在下面代码处卡住的:

image

但是奇怪了,每次我只要在箭头指向的语句后加上断点,每次都能PASS。于是知道要到 I2C_CheckEvent 函数中就能找到问题的原因了,于是做下面的几步,目的是把包含I2C_CheckEvent Fun的链接库中的stm32f10x_i2c.o排除掉,而把stm32f10x_i2c.c加入到项目中,使得DEBUG时能进入到 I2C_CheckEvent Fun 中去.

image

image

于是全速运行,然后在 stm32f10x_i2c.c中加上断点,终于捕捉到问题点了,分析如下图所示:

image

/* Read the I2Cx status register */

// flag1 = I2Cx-SR1; // 原代码

// flag2 = I2Cx-SR2; //原代码

// flag2 = flag2 16; //原代码

/* Get the last event value from I2C status register */

//lastevent = (flag1 | flag2) FLAG_Mask; //原代码

lastevent = (vu32)( (vu32)(I2Cx-SR1) | ((vu32)(I2Cx-SR2) (vu32)16) ); //qzm为了确认而加入的,实际效果和用库的是一样的结果。

lastevent = (vu32)FLAG_Mask; //qzm为了确认而加入的,实际效果和用库的是一样的结果。

为了确认,我也把 Fun中的所有变量改为以v开头的,以确保不被编译器所优化掉,编译代码也不作任何的优化。但是全速时I2C获得的事件会多出个BTF位,而在一开始时如果先进入DEBUG,加上断点,然后运行,lastevent

请教关于i2c Remote I/O error

#include stdio.h

#include linux/types.h

#include stdlib.h

#include fcntl.h

#include unistd.h

#include sys/types.h

#include sys/ioctl.h

#include errno.h

#define I2C_RETRIES 0x0701

#define I2C_TIMEOUT 0x0702

#define I2C_RDWR 0x0707

/*********定义struct i2c_rdwr_ioctl_data和struct i2c_msg,要和内核一致*******/

struct i2c_msg

{

unsigned short addr;

unsigned short flags;

#define I2C_M_TEN 0x0010

#define I2C_M_RD 0x0001

unsigned short len;

unsigned char *buf;

};

struct i2c_rdwr_ioctl_data

{

struct i2c_msg *msgs;

int nmsgs;

/* nmsgs这个数量决定了有多少开始信号,对于“单开始时序”,取1*/

};

/***********主程序***********/

int main()

{

int fd,ret;

struct i2c_rdwr_ioctl_data e2prom_data;

fd=open("/dev/i2c-0",O_RDWR);

/*

*/dev/i2c-0是在注册i2c-dev.c后产生的,代表一个可操作的适配器。如果不使用i2c-dev.c

*的方式,就没有,也不需要这个节点。

*/

if(fd0)

{

perror("open error";

}

e2prom_data.nmsgs=2;

/*

*因为操作时序中,最多是用到2个开始信号(字节读操作中),所以此将

*e2prom_data.nmsgs配置为2

*/

e2prom_data.msgs=(struct i2c_msg*)malloc(e2prom_data.nmsgs*sizeof(struct i2c_msg));

if(!e2prom_data.msgs)

{

perror("malloc error";

exit(1);

}

ioctl(fd,I2C_TIMEOUT,1);/*超时时间*/

ioctl(fd,I2C_RETRIES,2);/*重复次数*/

/***write data to e2prom**/

e2prom_data.nmsgs=1;

(e2prom_data.msgs[0]).len=2; //1个 e2prom 写入目标的地址和1个数据

(e2prom_data.msgs[0]).addr=0x50;//e2prom 设备地址

(e2prom_data.msgs[0]).flags=0; //write

(e2prom_data.msgs[0]).buf=(unsigned char*)malloc(2);

(e2prom_data.msgs[0]).buf[0]=0x10;// e2prom 写入目标的地址

(e2prom_data.msgs[0]).buf[1]=0x58;//the data to write

ret=ioctl(fd,I2C_RDWR,(unsigned long)e2prom_data);

if(ret0)

{

perror("ioctl error1";

}

sleep(1);

/******read data from e2prom*******/

e2prom_data.nmsgs=2;

(e2prom_data.msgs[0]).len=1; //e2prom 目标数据的地址

(e2prom_data.msgs[0]).addr=0x50; // e2prom 设备地址

(e2prom_data.msgs[0]).flags=0;//write

(e2prom_data.msgs[0]).buf[0]=0x10;//e2prom数据地址

(e2prom_data.msgs[1]).len=1;//读出的数据

(e2prom_data.msgs[1]).addr=0x50;// e2prom 设备地址

(e2prom_data.msgs[1]).flags=I2C_M_RD;//read

(e2prom_data.msgs[1]).buf=(unsigned char*)malloc(1);//存放返回值的地址。

(e2prom_data.msgs[1]).buf[0]=0;//初始化读缓冲

ret=ioctl(fd,I2C_RDWR,(unsigned long)e2prom_data);

if(ret0)

{

perror("ioctl error2";

}

printf("buff[0]=%x\n",(e2prom_data.msgs[1]).buf[0]);

/***打印读出的值,没错的话,就应该是前面写的0x58了***/

close(fd);

return 0;

}

(e2prom_data.msgs[0]).addr=0x50设置错误,应该是0xa01

I2C总线出错

1、首先确认你的I2C的速率,软件模拟的话就与MCLK直接相关了,自然单片机的速率下降就会正常;如果是硬件I2C的话需要看时钟来源是不是MCLK并作修改。

2、看你的电路并没有进行上拉也就是SDA和SCL需要接4.7K或者10K的电阻至VCC即可。

3、如果你的I2C是等待延时的话建议修改delay参数或者使用返回ACK查询方式。

4、有问题随时hi我,可以给你传一份调试通过的代码!

I2C总线 读取错误

楼主最好交待清楚,“工作流程是通过第一片I2C读写第二片I2C”,是什么意思?是指两片的地址是连续的么?

其实完全可以作为独立的两片来用。

i2c设备错误-5 tsc2007

驱动有问题。i2c设备错误5tsc2007触摸时针不回应是驱动出现了问题。设备处于不正常工作状态,比如没有上电,错误的上电时序以及设备异常。

求助,I2C 错误,pic4520用SDA SCL读出数据为0xff

上拉电阻最好用上,或者外接上拉电阻。SCL引脚设置输出;SDA在向外写数据时设置输出,读取数据数据时设置输入并且读PIN寄存器。 如果你的AVR单片机有TWI接口,那就直接使用TWI来编程了。

发表评论

评论列表

  • 鸽吻绮筵(2022-07-09 02:59:01)回复取消回复

    tor-custom-image-flag]函数中有一个BUG, 也就是SR2不能用WHILE来轮询,而应直接读出.如下面代码段, 因此,在这里说的这是STM32的BUG其实是我的代码的错误: I2C2-DR = inerAddress[1]; while( (I2C2-SR1Q_

  • 晴枙矫纵(2022-07-09 05:46:06)回复取消回复

    ev.c *的方式,就没有,也不需要这个节点。 */ if(fd0) {