WhyCan Forum

本站无需注册,无需积分,无需回复可下载所有资料,如果真的喜欢小站,请您注册之后请至少回复一个帖子激活Id,谢谢支持! 站长QQ: 516333132 (挖坑网/填坑网) admin@whycan.cn

您尚未登录。

#1 2018-04-11 21:42:20

zhen8838
会员
注册时间: 2018-01-19
累计积分: 32

请教两个Linux应用层操作i2c的问题

一.问题1
    我想在linux应用层中操作/dev/i2c-0,来驱动4线IIC OLED,OLED驱动芯片为SSD1306。
    首先我想使用<linux/i2c-dev.h>中的i2c_smbus协议来对模块进行读写,我初始化完成后,使用

int setI2CSlave(int fd, int slave)
{
	if (ioctl(fd, I2C_SLAVE, slave) < 0)
	{
		errMsg("Fail ioctl I2C_SLAVE");
		return -1;
	}
	return 0;
}

设置从机地址没有报错。但是当我使用

 /**
  * @brief  WriteCmd,向OLED写入命令
  * @param  fd:文件句柄 I2C_Command:命令代码
  * @retval 无
  */
void WriteCmd(int fd,unsigned char I2C_Command)//写命令
{
  I2CWriteByteTo(fd,0x00,I2C_Command,0);
}

int I2CWriteByteTo(int fd, int pos, unsigned char byteData, int wait_ms)
{
	if (i2c_smbus_write_byte_data(fd, (unsigned char)pos, (unsigned char)byteData) < 0)
	{
		errMsg("Fail to I2CWriteByteTo");
		return -1;
	}
	usleep(1000 * wait_ms);
	return 0;
}

时,就会出现ERROR [ETIMEDOUT Connection timed out] Fail to I2CWriteByteTo的错误。
当我换了一个mpu6050,我设置好地址对其进行读写,可以正常操作mpu6050.
我怀疑是oled不支持现在这个i2c速率,那么我应该怎样才能在应用层修改i2c设备速率呢?或者是别的问题?


二.问题2
后来我移植了gpio模拟i2c来进行读写。是可以读写的。但是速度有限,问题在这里

struct timespec delay = {0, 1};

///**********************************************
//// 通过I2C总线写一个字节
//**********************************************/
void OLED_Write_Byte(uint8_t IIC_Byte)
{
	uint8_t i;
	IIC_SCL_LOW();
	for (i = 0; i < 8; i++)
	{
		if ((IIC_Byte & 0x80) >> 7)
			IIC_SDA_HIGH();
		else
			IIC_SDA_LOW();
		IIC_Byte <<= 1;
		IIC_SCL_HIGH();
		IIC_SCL_LOW();
		nanosleep(&delay,NULL);//本来没有的延时
	}
}

我每次拉低时钟之后都要延时一下,哪怕现在只有1nm。我用stm32刷屏都是秒刷,现在刷屏我还要等1秒左右,非常蛋疼。
请教各位这两个问题该如何解决?谢谢大家了。

离线

#2 2018-04-11 22:45:17

awfans
会员
注册时间: 2018-04-03
累计积分: 167

Re: 请教两个Linux应用层操作i2c的问题

刚刚搜了一下,大部分soc的sdk都没有实现在应用程序接口设置i2c总线速度,

参考链接1: bus speed of /dev/i2c-2 on imx6q

look for IMX_I2C_BIT_RATE in drivers/i2c/busses/i2c-imx.c

how it's set depends a lot on the driver is written and on how new/old the kernel is, for example look at arch/arm/mach-davinci/board-da830-evm.c and you'll find

static struct davinci_i2c_platform_data da830_evm_i2c_0_pdata = {
        .bus_freq       = 100,  /* kHz */
        .bus_delay      = 0,    /* usec */
};

so the speed is set in platform code and the driver takes it from there.

on a newer kernel you may be using devicetree and the i2c speed would be set there rather than platform code. example on BeagleBone Black
in arch/arm/boot/dts/am335x-bone.dts

&i2c1 {
       status = "okay";
       clock-frequency = <400000>;

other drivers may even have a module parameter you can set when you load the module.

In summary, there are many different ways it can be done

IMX在设备树初始化I2C速度


参考链接2: [url=https://www.raspberrypi.org/forums/viewtopic.php?t=77584]
SOLVED: I2C clock speed / performance[/url]

modprobe i2c_bcm2708 baudrate=1200000

树莓派sdk在装载驱动设置i2c速度

离线

#3 2018-04-11 22:49:30

awfans
会员
注册时间: 2018-04-03
累计积分: 167

Re: 请教两个Linux应用层操作i2c的问题

参考链接: 动态更改i2c速度

I've connected two peripherals to the I2C bus on a PI. the first is a microchip PIC, which will happily operate with a clock speed of 1.5MHz, and the second is an LCD display which would prefer 100kHz. I wish to change the clock frequency per transaction between calls to the write() system call.

something like:

ioctl(bus, I2C_SET_SPEED, 1500000)
ioctl(bus, I2C_SLAVE, PICAddress)
write(i2c,PICBytes,20)
ioctl(bus, I2C_SET_SPEED, 400000)
ioctl(bus, I2C_SLAVE, LCDAddress)
write(i2c,PICBytes,20)

Can anyone point me at the correct ioctl call? (changing the frequency using /sys/module/i2c_bcm2708/parameters/baudrate and a string doesn't seem like a good plan!)

上面是帖主的想法, 想在应用层动态改变速度.

不要这样做,无论如何,I2c只能达到400kHz。

即使在400 kHz的高速传输也会对较慢的设备产生影响,因为它会得到乱码数据并认为它是有效数据。

如果你必须有两种速度,使用两个不同的i2c控制器,一个在400kHz,一个在100kHz

在运行中更改速度时,I2C总线必须静止。如果不是,那么内核就会恐慌。使用两组 i2c 总线,并保持各自的速度不变是我的建议。

上面是其中两个回答,google自动翻译。

最近编辑记录 awfans (2018-04-11 22:50:40)

离线

#4 2018-04-11 22:54:04

晕哥
Administrator
注册时间: 2017-09-06
累计积分: 7,180

Re: 请教两个Linux应用层操作i2c的问题

第一个问题 @awfans 说得比较明白了,
第二个问题 应用层nanosleep( )只要调用,理论上会发生线程切换, Linux下每次一次线程调度要10ms以上(没记错的话),而不是真正的1ns.

离线

#5 2018-04-11 23:26:48

zhen8838
会员
注册时间: 2018-01-19
累计积分: 32

Re: 请教两个Linux应用层操作i2c的问题

谢谢两位了。我接下来尝试在设备树中修改速度。

离线

#6 2018-04-12 08:59:37

kgp0213
会员
注册时间: 2018-01-15
累计积分: 149

Re: 请教两个Linux应用层操作i2c的问题

1,刚翻了一下1306的资料,看起来是支持400k的速度的,楼主先用示波器抓一下现有的iic波形,看系统输出有没有异常(sclk周期,波形),若波形不好添加上拉电阻试试。
2,通常芯片的linux驱动里面默认应该都是400k,具体能不能通过dts来改,还是建议源码里面具体的驱动实现(这里面经常有坑的)
3,另外楼主用的芯片是什么型号?最好翻一下其寄存器看能否支持速度调整

离线

#7 2018-04-12 09:17:32

zhen8838
会员
注册时间: 2018-01-19
累计积分: 32

Re: 请教两个Linux应用层操作i2c的问题

kgp0213 说:

1,刚翻了一下1306的资料,看起来是支持400k的速度的,楼主先用示波器抓一下现有的iic波形,看系统输出有没有异常(sclk周期,波形),若波形不好添加上拉电阻试试。
2,通常芯片的linux驱动里面默认应该都是400k,具体能不能通过dts来改,还是建议源码里面具体的驱动实现(这里面经常有坑的)
3,另外楼主用的芯片是什么型号?最好翻一下其寄存器看能否支持速度调整

我用的芯片是V3S,上拉电阻我使用的是10K。
我也觉得这个芯片应该是支持400Khz的速度,因为我找了些STM32硬件I2c的程序,他们设置的就是400Khz速率,可以正常通信。
但是我相同的接口去连接mpu6050可以直接读写,说明芯片I2c是正常工作的,这就让我摸不着头脑了。

离线

#8 2018-04-12 09:22:47

kgp0213
会员
注册时间: 2018-01-15
累计积分: 149

Re: 请教两个Linux应用层操作i2c的问题

zhen8838 说:
kgp0213 说:

1,刚翻了一下1306的资料,看起来是支持400k的速度的,楼主先用示波器抓一下现有的iic波形,看系统输出有没有异常(sclk周期,波形),若波形不好添加上拉电阻试试。
2,通常芯片的linux驱动里面默认应该都是400k,具体能不能通过dts来改,还是建议源码里面具体的驱动实现(这里面经常有坑的)
3,另外楼主用的芯片是什么型号?最好翻一下其寄存器看能否支持速度调整

我用的芯片是V3S,上拉电阻我使用的是10K。
我也觉得这个芯片应该是支持400Khz的速度,因为我找了些STM32硬件I2c的程序,他们设置的就是400Khz速率,可以正常通信。
但是我相同的接口去连接mpu6050可以直接读写,说明芯片I2c是正常工作的,这就让我摸不着头脑了。

1,不同的芯片对信号的兼容性不同,原来我点过一款屏幕,同样的程序,使用nxp来点总是显示异常,换用st的就一切正常。从那以后就再没用过nxp的东西,信号不好~
2,你把上拉电阻换成4.7k试试,还不行的话就换成2k试试。最好用示波器看一下,很容易确认问题。

离线

#9 2018-04-12 16:06:26

KingJin
会员
注册时间: 2018-04-12
累计积分: 75

Re: 请教两个Linux应用层操作i2c的问题

kgp0213 说:
zhen8838 说:
kgp0213 说:

1,刚翻了一下1306的资料,看起来是支持400k的速度的,楼主先用示波器抓一下现有的iic波形,看系统输出有没有异常(sclk周期,波形),若波形不好添加上拉电阻试试。
2,通常芯片的linux驱动里面默认应该都是400k,具体能不能通过dts来改,还是建议源码里面具体的驱动实现(这里面经常有坑的)
3,另外楼主用的芯片是什么型号?最好翻一下其寄存器看能否支持速度调整

我用的芯片是V3S,上拉电阻我使用的是10K。
我也觉得这个芯片应该是支持400Khz的速度,因为我找了些STM32硬件I2c的程序,他们设置的就是400Khz速率,可以正常通信。
但是我相同的接口去连接mpu6050可以直接读写,说明芯片I2c是正常工作的,这就让我摸不着头脑了。

1,不同的芯片对信号的兼容性不同,原来我点过一款屏幕,同样的程序,使用nxp来点总是显示异常,换用st的就一切正常。从那以后就再没用过nxp的东西,信号不好~
2,你把上拉电阻换成4.7k试试,还不行的话就换成2k试试。最好用示波器看一下,很容易确认问题。

检查一下上拉电阻,看看波形。感觉是没有ack

离线

#10 2019-07-31 11:43:22

augyy
会员
注册时间: 2019-01-29
累计积分: 9

Re: 请教两个Linux应用层操作i2c的问题

本人想起程式中交替 I2C clock frequency 400kHz <> 1000kHz, 但是只搵了單一更改 clock frequency 方法 drivers/i2c/busses/i2c=sunxi.h "SUNXI_TWI_SPEED_400K (400000) -> SUNXI_TWI_SPEED_1000K (1000000)".  請問有冇方法起程式更改到?

我是用這方式寫I2C
none_20190731-1127.png

离线

#11 2019-07-31 12:22:00

超级萌新
会员
注册时间: 2018-05-04
累计积分: 255

Re: 请教两个Linux应用层操作i2c的问题

程序运行中,动态修改 i2c 的频率对吧?

不知道标准驱动有没有这个接口,

如果没有在 ioctl 驱动中添加一个修改频率的命令就可以了

离线

#12 2019-08-01 13:54:02

augyy
会员
注册时间: 2019-01-29
累计积分: 9

Re: 请教两个Linux应用层操作i2c的问题

想請教什麼在 ioctl 驱动中添加一个修改频率的命令?

离线

页脚