基于[三星6818]I2C驱动开发的0.96寸oled屏
找OLED屏的原厂找配置源码
下载地址
更改源码适配LINUX系统(源码是MCU使用的),直接附上改后的源码
dev驱动代码(当使用plaform注册驱动时一般要用到两个.c文件一个是设备代码一个是驱动代码)
#eeprom_dev.c
static struct i2c_board_info gec6818_eeprom_info = {
//第一个参数必须要与drv下I2C的name一致,参数2为i2c设备地址,一般读写位不要整体右移一位
I2C_BOARD_INFO("gec6818_eeprom", 0x3c),
};
static struct i2c_client *gec6818_eeprom_client;
static int gec6818_eeprom_dev_init(void)
{
struct i2c_adapter *i2c_adap;
// 获取设备号为 2 的adpter ,也就是adapter->nr == 2(当使用sda2和sck2时)
i2c_adap = i2c_get_adapter(2);
//直接使用 i2c_new_device 创建 client 自动注册到i2c_bus_type 中去(drv代码probe中有用到)
//client->name == "gec6818_eeprom"
//client->addr = 0x3c
gec6818_eeprom_client = i2c_new_device(i2c_adap, &gec6818_eeprom_info);
// 释放掉 adapter
i2c_put_adapter(i2c_adap);
return 0;
}
static void gec6818_eeprom_dev_exit(void)
{
i2c_unregister_device(gec6818_eeprom_client);
}
module_init(gec6818_eeprom_dev_init);
module_exit(gec6818_eeprom_dev_exit);
drv驱动代码
#eeprom_drv.c
static struct i2c_client *this_client;
static int gec6818_eeprom_open (struct inode * inode, struct file *file)
{
printk("gec6818_eeprom_open \n");
return 0;
}
static int gec6818_eeprom_release (struct inode * inode, struct file *file)
{
printk("gec6818_eeprom_release \n");
return 0;
}
// buf[0] : addr
// buf[1] : data
//
static ssize_t gec6818_eeprom_write (struct file * file, const char __user * buf, size_t len, loff_t * off)
{
int rt;
char wbuf[2]={0};
unsigned char addr, data;
if(len > sizeof wbuf)
return -EINVAL;
rt = copy_from_user(wbuf, buf, 2);//把应用层传下的数据拷贝到内核
if(rt != 0)
return -EFAULT;
//写入的地址
addr = wbuf[0];
//写入的数据
data = wbuf[1];
//printk("addr = %x, data = %x\n", addr, data);
//传输1字节数据
rt = i2c_smbus_write_byte_data(this_client, addr, data);
if(rt < 0)
return rt;
return 2;
}
// 传入: buf[0] : addr
// 输出: buf[0] : data
//
static ssize_t gec6818_eeprom_read (struct file *file, char __user *buf, size_t len, loff_t * offs)
{
int rt=0;
unsigned char addr, data;
rt=copy_from_user(&addr, buf, 1);
if(rt != 0)
return -EFAULT;
//读取1字节数据
rt = i2c_smbus_read_byte_data(this_client, addr);
if(rt < 0)
return rt;
//若正确,获取读取到的字节
data = rt & 0xFF;
rt = copy_to_user(buf, &data, 1);
if(rt != 0)
return -EFAULT;
return 1;
}
static const struct file_operations gec6818_eeprom_fops = {
.owner = THIS_MODULE,
.write = gec6818_eeprom_write,
.open = gec6818_eeprom_open,
.release = gec6818_eeprom_release,
.read = gec6818_eeprom_read,
};
static struct miscdevice gec6818_eeprom_miscdev = {
.minor = MISC_DYNAMIC_MINOR, //MISC_DYNAMIC_MINOR,动态分配次设备号
.name = "gec6818_eeprom", //设备名称,/dev/gec6818_eeprom
.fops = &gec6818_eeprom_fops, //文件操作集
};
static int gec6818_eeprom_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int rt;
//检查是否支持I2C功能
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
{
printk("i2c_check_functionality fail\n");
return -ENODEV;
}
//混杂设备的注册
rt = misc_register(&gec6818_eeprom_miscdev);
if (rt)
{
printk("misc_register fail\n");
return rt;
}
//保存client指针,里面有各种设备信息
this_client = client;
printk("gec6818_eeprom_probe ok\n");
return 0;
}
static int __devexit gec6818_eeprom_remove(struct i2c_client *client)
{
misc_deregister(&gec6818_eeprom_miscdev);
return 0;
}
static const struct i2c_device_id gec6818_eeprom_id[] = {
{ "gec6818_eeprom", 0 }, //设备类型,ID号
{ } //标识结束
};
//添加到内核i2c设备列表
MODULE_DEVICE_TABLE(i2c, gec6818_eeprom_id);
// 分配/设置i2c_driver
static struct i2c_driver gec6818_eeprom_driver = {
.driver =
{
.name = "gec6818_eeprom", //用于匹配设备(dev下的name)
.owner = THIS_MODULE,
},
.probe = gec6818_eeprom_probe, //驱动初始化函数
.remove = __devexit_p(gec6818_eeprom_remove), //驱动删除
.id_table = gec6818_eeprom_id, //添加设备ID
};
//入口函数
static int __init gec6818_eeprom_drv_init(void)
{
printk("gec6818_eeprom_init\n");
//添加I2C设备
return i2c_add_driver(&gec6818_eeprom_driver);
}
//出口函数
static void __exit gec6818_eeprom_drv_exit(void)
{
//删除I2C设备
i2c_del_driver(&gec6818_eeprom_driver);
printk("gec6818 eeprom exit\n");
}
module_init(gec6818_eeprom_drv_init);
module_exit(gec6818_eeprom_drv_exit)
main函数入口
#eeprom_test.c //调用驱动程序代码
#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据
#define u8 unsigned char
int fd=-1;
/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{
unsigned char buf[2]={0};
buf[0]=0x00;
buf[1]=IIC_Command;
write(fd,buf,2);
}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{
unsigned char buf[2]={0};
buf[0]=0x40;
buf[1]=IIC_Data;
write(fd,buf,2);
}
void OLED_WR_Byte(unsigned dat,unsigned cmd)
{
if(cmd)
{
Write_IIC_Data(dat);
}
else
{
Write_IIC_Command(dat);
}
}
void OLED_Set_Pos(unsigned char x, unsigned char y)
{ OLED_WR_Byte(0xb0+y,OLED_CMD);
OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
OLED_WR_Byte((x&0x0f),OLED_CMD);
}
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
{
unsigned char c=0,i=0;
c=chr-' ';
if(x>128-1){x=0;y=y+2;}
if(Char_Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
}
else
{
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
OLED_WR_Byte(F6x8[c][i],OLED_DATA);
}
}
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
{
unsigned char j=0;
while (chr[j]!='\0')
{
OLED_ShowChar(x,y,chr[j],Char_Size);
x+=8;
if(x>120){x=0;y+=2;}
j++;
}
}
void OLED_Clear(void)
{
unsigned char i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD);
OLED_WR_Byte (0x00,OLED_CMD);
OLED_WR_Byte (0x10,OLED_CMD);
for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
}
}
int OLED_init(){
//OLED 初始化
OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
OLED_WR_Byte(0x40,OLED_CMD);//--set start line address
OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
OLED_WR_Byte(0x81,OLED_CMD); // contract control
OLED_WR_Byte(0xFF,OLED_CMD);//--128
OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap
OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
OLED_WR_Byte(0x00,OLED_CMD);//
OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
OLED_WR_Byte(0x80,OLED_CMD);//
OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
OLED_WR_Byte(0x05,OLED_CMD);//
OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
OLED_WR_Byte(0xF1,OLED_CMD);//
OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
OLED_WR_Byte(0x12,OLED_CMD);//
OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
OLED_WR_Byte(0x30,OLED_CMD);//
OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
OLED_WR_Byte(0x14,OLED_CMD);//
OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
}
int main(int argc, char **argv)
{
int len;
int i=0;
char buf[8];
//打开gec6818_eeprom设备
fd = open("/dev/gec6818_eeprom",O_RDWR);
if(fd < 0)
{
perror("open /dev/gec6818_eeprom:");
return fd;
}
OLED_init();//oled初始化
OLED_Clear();//oled清屏
OLED_ShowString(24,0,(u8 *)"Teacher.Wen",16);//oled显示字符串
while(1)
{
}
close(fd);
return 0;
}
效果图
