• 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 的测试。

  • 相关阅读:
    笔记
    软件工程第二次作业
    现代软件工程 第一周作业
    2019春季学期期末总结
    2019第十四周作业
    2019第十二周左右
    2019第十一周作业
    2019第十周作业
    2019第九周作业
    2019第八周作业
  • 原文地址:https://www.cnblogs.com/GyForever1004/p/8531607.html
Copyright © 2020-2023  润新知