荔枝派 V3S Linux 應用層 IIC 使用OLED
阿新 • • 發佈:2018-04-12
ddr 開始 出現 驅動程序 line 但是 IE HR 手冊
1.開始
我想在荔枝派上驅動oled屏,但是在內核中寫驅動對我來說肯定是非常麻煩的,所以我退而求其次,想在應用層中操作通用i2c接口來實現oled的驅動程序。
我買的OLED是中景園經典款,四針IIC接口oled。首先我參考了NanoPi的Matrix庫,參考他的IIC應用層函數。我發現他多include了一個i2c-dev.h 並且這個函數的內容是比我/usr/inlucde/linux/i2c-dev.h中的內容多的,他多了以下幾個函數
static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,int size, union i2c_smbus_data *data) static inline __s32 i2c_smbus_write_quick(int file, __u8 value) static inline __s32 i2c_smbus_read_byte(int file) static inline __s32 i2c_smbus_write_byte(int file, __u8 value) static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command) staticinline __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value) static inline __s32 i2c_smbus_read_word_data(int file, __u8 command) static inline __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value)static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value) /* Returns the number of read bytes */ static inline __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values) static inline __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, __u8 *values) /* Returns the number of read bytes */ static inline __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 *values) static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length, __u8 *values) /* Returns the number of read bytes */ static inline __s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length, __u8 *values)
我在網上查詢了這些函數,這個是一種smbus協議,是對應用層i2c的進一步封裝。我可以使用這個快速的對i2c數據進行讀寫。
之後我就參考了別人的OLED代碼,開始了移植。
2.問題出現
我發現我設置好了從機地址之後,進行讀寫一直出現No Such Device Or Addres 的錯誤。經過一天的尋找,我終於發現了錯誤所在。
在網上的那個oled程序,都是將0x78作為從機地址。並且數據手冊中也是這樣寫的,那麽我理所當然將0x78作為從機地址。但是接下來我們看數據手冊以及代碼片段
ssd1306:
數據手冊片段:
ssd1306的讀寫函數片段:
/*********************OLED寫數據************************************/ void OLED_WrDat(unsigned 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:
數據手冊
代碼片段:
//IIC讀一個字節 //reg:寄存器地址 //返回值:讀到的數據 u8 MPU_Read_Byte(u8 reg) { u8 res; IIC_Start(); IIC_Send_Byte((MPU_ADDR<<1)|0);//發送器件地址+寫命令 IIC_Wait_Ack(); //等待應答 IIC_Send_Byte(reg); //寫寄存器地址 IIC_Wait_Ack(); //等待應答 IIC_Start(); IIC_Send_Byte((MPU_ADDR<<1)|1);//發送器件地址+讀命令 IIC_Wait_Ack(); //等待應答 res=IIC_Read_Byte(0);//讀取數據,發送nACK IIC_Stop(); //產生一個停止條件 return res; }
大家發現錯誤沒有? 那就是對兩個器件寫地址的時候,oled的地址沒有左移!那麽問題就出現在這裏,linux中設置好了從機地址後,他的發送時會自動根據讀寫來對地址進行左移後或上0、1的操作。
所以我這個0x78就是他的已經左移一位了的地址,那麽我給linux中設置的從機地址應該是0x78右移一位得出的0x3C!現在我就可以正常讀寫了。
3.代碼
下面附上我修改的i2c代碼驅動地址。
荔枝派 V3S Linux 應用層 IIC 使用OLED