• 【Linux开发】linux设备驱动归纳总结(十二):简单的数码相框


    linux设备驱动归纳总结(十二):简单的数码相框


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    其实代码很简单,实现lcd驱动,使lcd能够显示图片,当按下按键后切换图片。

    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    先要说明一下几处地方:

    1、代码中显示的图片都是*.bin文件(显示模式是使用16位数据来表示一个像素的颜色——5:6:5),将jpg文件转为*.bin文件的工具在我上传的mkimage目录中。转换图片的尺寸在fb.h中指定,我的图片是480*272,所以:

    #define X 480

    #define Y 272

    转换的命令也很简单:

    ./mkimage src_file dis_file

    源代码都上传了,自己摸索,源码面前没有秘密。 mkimage.rar   


    2、我的lcd480*272,即使是同样的尺寸的lcd,因为接线的不一样,我也不能保证能够驱动成功。但是,显示器的不同也只需要修改lcd配置函数就可以了。


    接下来介绍一下我编写时的顺序。


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    一、实现lcd的基本操作:12th_lcd/1st


    代码具体做了以下几件事:

    1、定义了一个结构体:struct _lcd_t

    2、实现了lcd即基本操作,包括:

    配置lcds3c_lcd_config(struct _lcd_t *lcd)

    启动lcds3c_lcd_enabe(struct _lcd_t *lcd)

    关闭lcds3c_lcd_disable(struct _lcd_t *lcd)

    3、封装了lcd设备的初始化和注销函数:

    init_lcd_device(struct _lcd_t *lcd)

    destory_lcd_device(struct _lcd_t *lcd)

    其中有一个我在之前的总结中没有介绍的知识点——DMA编程,简单的理解就会调用一个函数,函数给你返回两个地址,一个是虚拟地址,一个是对应的物理地址。只要你的程序往虚拟地址中读写数据,实际就会往物理地址写数据。主要的特点就是:数据的传输不需要经过处理器,而是2440中的DMA负责传输。具体的以后有机会再补充。

    其实就是一个函数:

    void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)


    注意:如果显示屏不一样的话,就要修改s3c_lcd_config里面的代码。


    装载模块时,会调用test_lcd函数测试是否成功,该函数会让屏幕全红。


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    二、实现字符型设备:12th_lcd/2nd


    第二个代码在原来的基础上注册了杂设备,并且实现了write操作,当在应用层将图片数据写到设备文件/dev/test_lcd中,就会将图片显示出来。

    大致知识点:

    ·linux设备驱动归纳总结(三):2open.close.read.write

    ·linux设备驱动归纳总结(十):1.udev&misc


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    三、实现图片切换:12th_lcd/3rd


    第三个代码要实现的功能是:当按键按下时,应用层切换新的图片传给lcd


    这里要添加两个东西:

    1、添加中断,当按键按下时执行中断处理函数。

    2、添加字符设备的异步通知机制,在中断处理函数发送信号到应用层,应用程序接到信号后更换图片。

    大致知识点:

    ·linux设备驱动归纳总结(六):1.中断的实现


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    四、实现按键去抖:12th_lcd/4th


    在上面的程序,如果硬件本身不好的话,按下一次的按键可能产生多次的中断,所以按键去抖很有必要。实现很简单,就是添加一个定时器。

    大致知识点:

    ·linux设备驱动归纳总结(七):2.内核定时器


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    五、实现静态平台类驱动:12th_lcd/5th


    其实就是在原来的程序上加上平台类驱动的注册,然后修改3处的内核代码:

    1arch/arm/mach-s3c2440/mach-mini2440.c

    250 static struct platform_device *mini2440_devices[] __initdata = {

    251 &s3c_device_usb,

    252 &s3c_device_rtc,

    253 &s3c_device_lcd,

    254 &s3c_device_wdt,

    255 &s3c_device_led,

    256 &s3c_device_wdt_xb,

    257 &s3c_device_lcd_xb, //这是新添加的

    258 &s3c_device_i2c0,

    259 &s3c_device_iis,

    260 &s3c_device_dm9k,

    261 &net_device_cs8900,

    262 &s3c24xx_uda134x,

    263 };

    2arch/arm/plat-s3c24xx/devs.c

    405 static struct resource s3c_lcd_xb_resource[] = {

    406 [0] = {

    407 .start = 0x4d000000,

    408 .end = 0x4d0000ff,

    409 .flags = IORESOURCE_MEM,

    410 },

    411 [1] = {

    412 .start = 0x56000000,

    413 .end = 0x560000ff,

    414 .flags = IORESOURCE_MEM,

    415 },

    416 [2] = {

    417 .start = IRQ_EINT1,

    418 .end = IRQ_EINT1,

    419 .flags = IORESOURCE_IRQ,

    420 }

    421 };

    422

    423 struct platform_device s3c_device_lcd_xb = {

    424 .name = "s3c_lcd_xb",

    425 .id = -1,

    426 .num_resources = ARRAY_SIZE(s3c_lcd_xb_resource),

    427 .resource = s3c_lcd_xb_resource,

    428 };

    429

    430 EXPORT_SYMBOL(s3c_device_lcd_xb);

    3arch/arm/plat-s3c/include/plat/devs.h

    5 extern struct platform_device s3c_device_lcd_xb;

    大致知识点:

    ·linux设备驱动归纳总结(九):1.platform设备驱动


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    六、实现字符设备操作mmap12th_lcd/6th


    这个知识点我还没总结,大体上就是在应用程序中调用mmap,驱动就会把一块实际的内存地址映射到应用层,并返回一个地址给用户操作。

    具体就是在字符设备中添加mmap操作。详细请看代码,我就不详细介绍了,可以看《LDD3P418


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    七、为驱动添加信号量:12th_lcd/7th


    其实这一步在这里可以说是多于的,在非抢占单处理器的情况下根本不需要添加防止并发和竞态的机制,我这里也只是仅仅加上,当是复习。

    大致知识点:

    ·linux设备驱动归纳总结(四):5.SMP下的竞态和并发


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    八、完善代码:12th_lcd_8th


    之前为了代码看起来短小一点,我没有在代码中添加错误操作,如申请中断号失败时的操作。这里稍稍修改了一下,添加了一下错误检查的代码。


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    源代码: 12th_lcd_1.rar   12th_lcd_2.rar    

  • 相关阅读:
    ASCII 32个控制字符含义
    MFC中获取指定打印机的打印队列的方法
    某品牌led报文信息分析
    SQL Server 企业版没有 Management Studio管理工具 无法安装工作站组件 的解决方法(无需卸载重装)
    xla文件修改办法
    关于ALILIB
    编译器如何根据头文件来找到相应实现的cpp文件?
    C#调用C++接口提示找不到指定的模块解决方法,本机正常
    DataGridView中实现右击选中当前行功能,并通过ContextMenuStrip获取当前行
    C#递归获取文件列表
  • 原文地址:https://www.cnblogs.com/huty/p/8518547.html
Copyright © 2020-2023  润新知