一.问题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秒左右,非常蛋疼。
请教各位这两个问题该如何解决?谢谢大家了。
离线
刚刚搜了一下,大部分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速度
离线
参考链接: 动态更改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)
离线
谢谢两位了。我接下来尝试在设备树中修改速度。
离线
1,刚翻了一下1306的资料,看起来是支持400k的速度的,楼主先用示波器抓一下现有的iic波形,看系统输出有没有异常(sclk周期,波形),若波形不好添加上拉电阻试试。
2,通常芯片的linux驱动里面默认应该都是400k,具体能不能通过dts来改,还是建议源码里面具体的驱动实现(这里面经常有坑的)
3,另外楼主用的芯片是什么型号?最好翻一下其寄存器看能否支持速度调整
离线
1,刚翻了一下1306的资料,看起来是支持400k的速度的,楼主先用示波器抓一下现有的iic波形,看系统输出有没有异常(sclk周期,波形),若波形不好添加上拉电阻试试。
2,通常芯片的linux驱动里面默认应该都是400k,具体能不能通过dts来改,还是建议源码里面具体的驱动实现(这里面经常有坑的)
3,另外楼主用的芯片是什么型号?最好翻一下其寄存器看能否支持速度调整
我用的芯片是V3S,上拉电阻我使用的是10K。
我也觉得这个芯片应该是支持400Khz的速度,因为我找了些STM32硬件I2c的程序,他们设置的就是400Khz速率,可以正常通信。
但是我相同的接口去连接mpu6050可以直接读写,说明芯片I2c是正常工作的,这就让我摸不着头脑了。
离线
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试试。最好用示波器看一下,很容易确认问题。
离线
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
离线
本人想起程式中交替 I2C clock frequency 400kHz <> 1000kHz, 但是只搵了單一更改 clock frequency 方法 drivers/i2c/busses/i2c=sunxi.h "SUNXI_TWI_SPEED_400K (400000) -> SUNXI_TWI_SPEED_1000K (1000000)". 請問有冇方法起程式更改到?
我是用這方式寫I2C
离线
程序运行中,动态修改 i2c 的频率对吧?
不知道标准驱动有没有这个接口,
如果没有在 ioctl 驱动中添加一个修改频率的命令就可以了
离线
想請教什麼在 ioctl 驱动中添加一个修改频率的命令?
离线