一.问题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秒左右,非常蛋疼。
请教各位这两个问题该如何解决?谢谢大家了。
离线
谢谢两位了。我接下来尝试在设备树中修改速度。
离线
1,刚翻了一下1306的资料,看起来是支持400k的速度的,楼主先用示波器抓一下现有的iic波形,看系统输出有没有异常(sclk周期,波形),若波形不好添加上拉电阻试试。
2,通常芯片的linux驱动里面默认应该都是400k,具体能不能通过dts来改,还是建议源码里面具体的驱动实现(这里面经常有坑的)
3,另外楼主用的芯片是什么型号?最好翻一下其寄存器看能否支持速度调整
我用的芯片是V3S,上拉电阻我使用的是10K。
我也觉得这个芯片应该是支持400Khz的速度,因为我找了些STM32硬件I2c的程序,他们设置的就是400Khz速率,可以正常通信。
但是我相同的接口去连接mpu6050可以直接读写,说明芯片I2c是正常工作的,这就让我摸不着头脑了。
离线