1. Start
I want to drive the OLED screen on the lychee pie, but the write driver in the kernel is definitely a hassle for me, so I'm going to go back to the second, I want to operate the generic I²c interface in the application layer to implement the OLED driver.
I bought the OLED is the classic model, four-pin IIC interface OLED. First I refer to Nanopi's Matrix Library, referring to his IIC application layer function. I found out he included a i2c-dev.h and the content of this function is more than what I/usr/inlucde/linux/i2c-dev.h, he has the following functions
StaticInline __s32 i2c_smbus_access (intFileCharread_write, __u8 command,intSize, Union I2c_smbus_data *data)StaticInline __s32 I2c_smbus_write_quick (intfile, __u8 value)StaticInline __s32 I2c_smbus_read_byte (intfile)StaticInline __s32 I2c_smbus_write_byte (intfile, __u8 value)StaticInline __s32 I2c_smbus_read_byte_data (intfile, __u8 command)StaticInline __s32 I2c_smbus_write_byte_data (intfile, __u8 command, __u8 value)StaticInline __s32 I2c_smbus_read_word_data (intfile, __u8 command)StaticInline __s32 I2c_smbus_write_word_data (intfile, __u8 command, __u16 value)StaticInline __s32 I2c_smbus_process_call (intfile, __u8 command, __u16 value)/*Returns the number of read bytes*/StaticInline __s32 I2c_smbus_read_block_data (intfile, __u8 command, __u8*values)StaticInline __s32 I2c_smbus_write_block_data (intfile, __u8 command, __u8 length, __u8*values)/*Returns the number of read bytes*/StaticInline __s32 I2c_smbus_read_i2c_block_data (intfile, __u8 command, __u8*values)StaticInline __s32 I2c_smbus_write_i2c_block_data (intfile, __u8 command, __u8 length, __u8*values)/*Returns the number of read bytes*/StaticInline __s32 I2c_smbus_block_process_call (intfile, __u8 command, __u8 length, __u8*values)
I have queried these functions on the Internet, which is a SMBus protocol and a further encapsulation of application-level i²c. I can use this fast to read and write to the i²c data.
Then I started the transplant by referencing someone else's OLED code.
2. Problem arises
I found that after I set the slave address, I read and write all the time there was no Such Device Or addres error. After a day of searching, I finally found the mistake.
The OLED program on the internet is 0x78 as the slave address. And this is also written in the data sheet, so I take 0x78 as the slave address for granted. But then we'll look at the data sheet and the code snippet
ssd1306:
Data Sheet Fragment:
ssd1306 read-write function fragment:
/* ********************oled Write Data *********************************** */ void Char Iic_data) { iic_start (); Iic_send_byte ( 0x78); // d/c#=0; R/w#=0 iic_wait_ack (); Iic_send_byte (0x40); // Write Data iic_wait_ack (); Iic_send_byte (iic_data); Iic_wait_ack (); Iic_stop ();}
mpu6050:
Data Sheet
Code snippet:
//IIC read one byte//REG: Register address//return value: The data readU8 Mpu_read_byte (U8 reg) {U8 res; Iic_start (); Iic_send_byte ((mpu_addr <<1) |//Send device Address + Write commandIic_wait_ack ();//waiting for an answerIic_send_byte (REG);//Write register AddressIic_wait_ack ();//waiting for an answerIic_start (); Iic_send_byte ((mpu_addr<<1)|1);//Send device address + read commandIic_wait_ack ();//waiting for an answerRes=iic_read_byte (0);//read data, send NackIic_stop ();//Create a Stop condition returnRes; }
Have you found any mistakes? That is, when the address of two devices is written, the address of the OLED does not move to the left! Then the problem is here, when the slave address is set up in Linux, he will automatically send the address after the left or 0 or 1 of the operation according to the read and write.
So my 0x78 is his left one address, then I give Linux set the slave address should be 0x78 right shift a 0x3c! Now I can read and write normally.
3. Code
The following is a copy of my modified I²c code driver address .
Litchi pie v3s Linux Application layer IIC using OLED