SPI OLED 驱动

根据之前说过的 SPI 驱动的框架,在我们添加 SPI 设备驱动的时候需要与 SPI Master 完成匹配,通过 spi_register_board_info 进行注册。

构造设备

static struct spi_board_info spi_info_mini2440 = {
     .modalias = "oled",                            /* 对应的 spi_driver 名字也是 "oled" */
     .max_speed_hz = 10000000,                      /* max spi clock (SCK) speed in HZ */
     .bus_num = 0,                                  /* mini2440 里 OLED 接在 SPI CONTROLLER 0 */
     .mode    = SPI_MODE_0,
     .chip_select   = S3C2410_GPG(1),               /* oled_cs, 它的含义由 spi_master 确定 */
     .platform_data = (const void *)S3C2410_GPF(3) ,/* oled_dc, 它在 spi_driver 里使用 */         
}

然后调用 spi_register_board_info 函数完成注册。

内核没有实现对 spi_register_board_info 进行 export_symbol 导出,我们不能在模块中来调用,所以需要修改对应 Makefile 将这个文件编进内核。

设备驱动

/* 构建 spi_driver 结构体 */
static struct spi_driver spi_oled_drv = {
    .driver = {
        .name   = "oled",
        .owner  = THIS_MODULE,
    },
    .probe      = spi_oled_probe,
    .remove     = __devexit_p(spi_oled_remove),
};

/* probe 函数 */
static int __devinit spi_oled_probe(struct spi_device *spi)
{
    spi_oled_dev = spi;
    spi_oled_dc_pin = (int)spi->dev.platform_data;
    
    /* 配置 dc、cs 引脚为 output */
    s3c2410_gpio_cfgpin(spi_oled_dc_pin, S3C2410_GPIO_OUTPUT);
    s3c2410_gpio_cfgpin(spi->chip_select, S3C2410_GPIO_OUTPUT);

    /* 供 copy_from_user 使用 */
    ker_buf = kmalloc(4096, GFP_KERNEL);
    
    /* 注册一个 file_operations */
    major = register_chrdev(0, "oled", &oled_ops);

    class = class_create(THIS_MODULE, "oled");
    
    /* 为了让 mdev 根据这些信息来创建设备节点 */
    device_create(class, NULL, MKDEV(major, 0), NULL, "oled"); /* /dev/oled */
    
    return 0;
}

probe 函数中通过 register_chrdev 创建一个字符设备,然后通过其 ioctl、write 调用 oled 的初始化和写内存函数来完成对 oled 的操作。

最后调用 spi_register_driver 函数完成设备驱动的注册。

测试程序

/* page: 0-7
 * col : 0-127
 * 字符: 8x16象素
 */
void OLEDPutChar(int fd, int page, int col, char c)
{
    int i = 0;
    
    /* 得到字模 */
    const unsigned char *dots = oled_asc2_8x16[c - ' '];

    /* 发给OLED */
    OLEDSetPos(page, col);
    ioctl(fd, OLED_CMD_CLEAR_PAGE, page);
    ioctl(fd, OLED_CMD_SET_POS, page | (col << 8));
    
    /* 发出8字节数据 */
    for (i = 0; i < 8; i++)
        OLEDWriteDat(dots[i]);
    write(fd, &dots[0], 8);

    OLEDSetPos(page+1, col);
    ioctl(fd, OLED_CMD_CLEAR_PAGE, page+1);
    ioctl(fd, OLED_CMD_SET_POS, (page+1) | (col << 8));
    
    /* 发出8字节数据 */
    for (i = 0; i < 8; i++)
        OLEDWriteDat(dots[i+8]);
    write(fd, &dots[8], 8);
}

通过调用 ioctl 与 write 接口就可以完成对 oled 的测试。

转载于:https://www.cnblogs.com/GyForever1004/p/8531607.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值