•  

    Linux内核驱动程序示例:
    • drivers\spi\spidev.c

一、 SPI时序:

oled操作方法

ssd1306:

访问显存:

哪一列,哪一页(设置地址模式)

三种模式:

页地址模式

 

image

 

水平地址模式

image

 

垂直地址模式

image

 

初始化时序

image

 

关键来了,能否上网找相应的驱动或者从内核获取相应的驱动???

image

  • oled Device (设备描述):
    • 信息来源: 设备树 (Device Tree)
    • 核心属性:
    • compatible:my,oled_drv
    • reg: reg<1>
    • 挂载点: spi5 下
    • dc引脚
    • spi节点描述 用pinctrl 子系统描述
  • oled Driver (驱动程序):
    • 核心结构体:struct spi_driver ,struct spi_device
    • 函数:spi_write(oled, buf, len);
    • probe函数,注册设备节点,以及操作(注册设备(有操作函数))-->设备类-->设备节点)
    • remove,销毁设备节点
    • 操作函数
    • write
    • spidev_ioctl
    • module__init(__init函数,注册驱动)
    • module__exit(__exit函数__销毁驱动)
static int __init i2c_driver_ap3216c_init(void)
{
  printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
  return i2c_add_driver(&i2c_ap3216c_driver);
}

probe函数:

static int spi_probe(struct spi_device *pdev)
{
    /* 记录设备 */
    oled = pdev;
    /* 注册设备 */
    major = register_chrdev(0, "spi_oled", &spidev_fops);
    /* 创建类 */
    spidev_class  = class_create(THIS_MODULE, "spi_oled");
    /* 创建设备 */
    device_create(spidev_class , NULL, MKDEV(major, 0), NULL, "spi_oled");
    /* 获取GPIO */
    dc_gpio = gpiod_get(&oled->dev, "dc", 0);
    return 0;
}

操作函数:

//写操作函数
static ssize_t spidev_write(struct file *filp, const char __user *buf,
		size_t count, loff_t *f_pos)
{
	char *ker_buf;
	int err;

	ker_buf = kmalloc(count, GFP_KERNEL);
	err = copy_from_user(ker_buf, buf, count);
	
	dc_pin_set(1);//拉高,表示写入数据
	spi_write(oled, ker_buf, count);
	kfree(ker_buf);
	return count;
}

 

//操作函数
static long spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
  int x, y;
  
  /* 根据cmd操作硬件 */
  switch (cmd)
  {
    case OLED_IOC_INIT: /* init */
    {
      dc_pin_init();
      oled_init();
      break;
    }
    case OLED_IOC_SET_POS: /* set pos */
    {
      x = arg & 0xff;
      y = (arg >> 8) & 0xff;
      OLED_DIsp_Set_Pos(x, y);
      break;
    }

  }

  return 0;
}

 

结果:

image

 至于oled画线画点,之后再说把