前言:我是linux驱动开发的初学者,也是第一次写博客,难免会有许多不周到的地方,我写这篇博客的初衷是为了记录自己学习的点滴,当然如果这篇文章能帮到你的话就更好了。
1.实验目的
因为我手上的板子是正点原子Linux mini开发板,所以没有集成Ap3216c这个I2C外设,所以我用i2c接口的oled替代,也是考验我对I2C驱动的掌握情况。
2.实验器材
硬件 | 数量 |
---|
正点原子Linux mini开发板 | 1 | 0.96寸oled(i2c接口) | 1 | 杜邦线 | 4 |
3.实验步骤
<1> 按照正点原子视频搭建好使用设备树的I2C驱动框架。 <2> 然后再将它这个例程里面的有关于Ap3216c的初始化及读写数据相关代码删掉。 <3> 参考下面这个大佬的代码把oled相关的代码放到上述搭建好的框架中。 链接: https://www.cnblogs.com/Recca/p/12760575.html.
4.实验代码
这个是oled.h
#ifndef _oled_H
#define _oled_H
#define OLED_CMD 0x40
#define OLED_DATA 0x00
#endif
oled.c里有关于oled的函数
static int oled_send_byte(unsigned char data, unsigned char cmd)
{
int ret = 0;
if (cmd)
{
ret = Oled_Wirte_Reg(&I2C_Oled, 0x00, data);
}
else
{
ret = Oled_Wirte_Reg(&I2C_Oled, 0x40, data);
}
if (ret)
return -EIO;
return 0;
}
static void OLED_DisplayTurn(u8 i)
{
if(i==0)
{
oled_send_byte(0xC8,1);
oled_send_byte(0xA1,1);
}
if(i==1)
{
oled_send_byte(0xC0,1);
oled_send_byte(0xA0,1);
}
}
void OLED_Clear(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
oled_send_byte(0xb0 + i, 1);
oled_send_byte(0x00, 1);
oled_send_byte(0x10, 1);
for(n=0;n<128;n++)
{
oled_send_byte(0, 0);
}
}
}
static void oled_set_pos(unsigned int x, unsigned int y)
{
unsigned char temp = 0;
temp = 0xb0 + y;
oled_send_byte(temp, 1);
temp = ((x & 0xf0) >> 4) |0x10;
oled_send_byte(temp, 1);
temp = x & 0x0f;
oled_send_byte(temp, 1);
}
static void oled_show_char(unsigned char x, unsigned char y, unsigned char data)
{
unsigned char c=0,i;
c = data - ' ';
if(x > 127)
{
x = 0;
y = y + 2;
}
if(16 == I2C_Oled.size)
{
oled_set_pos(x, y);
for(i=0; i<8; i++)
oled_send_byte(F8X16[c*16 + i], 0);
oled_set_pos(x, y+1);
for(i=0; i<8; i++)
oled_send_byte(F8X16[c*16 + i + 8], 0);
}
else
{
oled_set_pos(x, y);
for(i=0; i<6; i++)
oled_send_byte(F6x8[c][i], 0);
}
}
static void oled_show_string(unsigned char x, unsigned char y, unsigned char *buf)
{
unsigned char i = 0;
while (buf[i] != '\0')
{
oled_show_char(x, y, buf[i]);
x += 8;
if(x > 120)
{
x = 0;
y += 2;
}
i++;
}
}
void oled_init(void)
{
oled_send_byte(0xAE, 1);
oled_send_byte(0x00, 1);
oled_send_byte(0x10, 1);
oled_send_byte(0x40, 1);
oled_send_byte(0xB0, 1);
oled_send_byte(0x81, 1);
oled_send_byte(0xFF, 1);
oled_send_byte(0xA1, 1);
oled_send_byte(0xA6, 1);
oled_send_byte(0xA8, 1);
oled_send_byte(0x3F, 1);
oled_send_byte(0xC8, 1);
oled_send_byte(0xD3, 1);
oled_send_byte(0x00, 1);
oled_send_byte(0xD5, 1);
oled_send_byte(0x80, 1);
oled_send_byte(0xD8, 1);
oled_send_byte(0x05, 1);
oled_send_byte(0xD9, 1);
oled_send_byte(0xF1, 1);
oled_send_byte(0xDA, 1);
oled_send_byte(0x12, 1);
oled_send_byte(0xDB, 1);
oled_send_byte(0x30, 1);
oled_send_byte(0x8D, 1);
oled_send_byte(0x14, 1);
oled_send_byte(0xAF, 1);
}
与应用层(open,write等)交互函数
static int i2c_open(struct inode *inode, struct file *filp)
{
filp->private_data = &I2C_Oled;
oled_init();
OLED_Clear();
return 0;
}
static ssize_t i2c_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
int ret = 0;
ret = copy_from_user(I2C_Oled.buffer, buf, cnt);
if (ret < 0) {
printk("copy from user failed!\r\n");
return -1;
}
OLED_DisplayTurn(1);
oled_show_string(8, 8, I2C_Oled.buffer);
printk("driver: i2c_write ok!\n");
printk("the buffer is %s", I2C_Oled.buffer);
return 0;
}
static int i2c_release(struct inode *inode, struct file *filp)
{
OLED_Clear();
return 0;
}
应用程序代码
int main(int argc,char *argv[])
{
int fd,ret = 0;
unsigned int i = 0;
unsigned char buf[] = "www.oss.com";
char *filename;
filename = argv[1];
fd = open(filename,O_RDWR);
if(fd < 0)
{
printf("file %s open error\r\n",filename);
return -1;
}
ret = write(fd, buf, sizeof(buf));
if (ret < 0)
{
printf("wirte data to kernel error\r\n");
return -1;
}
while (1);
close(fd);
return 0;
}
实验结果
总结 :以上代码比较粗糙,望读者见谅!也难免存在些bug,如有发现烦请告知。最后,多调多试,总会成功的,求知路上,逐渐迷茫着,慢慢地这样钢铁就练成了!
本文章为原创文章,如若转载请声明,谢谢!文中引用和参考了那位大佬的博客,如有侵犯,烦请告知,必删!
|