完成一个LCD4Linux的USB屏幕

LCD2USB with 1602 LCD

暑假之前就注意了LCD4Linux这个Project,简单说,这就是个硬件版conky的驱动服务,用户自己DIY各式各样的硬件屏幕,自己编写驱动、编写各种插件来控制输出到屏幕上的信息,LCD4Linux就是这样一个平台,也是一个geek味道非常浓郁的、可玩性相当高的一个Project。

图片里面是LCD4Linux项目页里面收集的部分人实现的一些屏幕,有像我这样一块小小的1602,也有用块10多寸的液晶屏作成很拉风的监控屏,甚至,挂一个户外广告那样的LED阵列,你也可以转换成VGA信号输出给大屏幕的电视机,或者弄个天线发射出外太空都是可能的……

这个项目的可玩性就在于硬件的多样性,很可能每个人实现的屏幕都不一样,而作为开源项目,geek们只需或多或少地修改一下别人的驱动就可让屏幕跑起来了。

我实现的这块,是用了一块通用AVR单片机,通过USB接口直接取电和传输的数据的架构,硬件和协议参考的是LCD2USB项目。其原来用的是atmega8芯片,而我手边只有atmega48,算是类似吧,但换换IO口还是在所难免的。

实现一个系统,同时也藉此了解一下相关的技术(不然还真的很难做得出来),首先是USB,USB我们天天在用,但是学校的《微机接口》之类的课程可从来不涉及这些“时髦”技术的,虽然USB已经流行了10多年了。通过V-USB库,在AVR单片机上实现USB设备还真没什么难度,只需要填写设备ID设备名称之类的,然后再实现协议处理函数就完了,在Linux下使用是直接支持,一插上运行lsusb就能认出(Win下需要另外装驱动)。我第一个实验USB就是接了几个二极管开关,用libusb的python binding, pyusb,很容易就控制几个灯。(想起The Big Bang Theory S1E9开头那一段,再import个SimpleHTTPServer,然后让单片机连接几个继电器,就能像他们那样让别人用浏览器来开关我的台灯了,哈!)

其实单纯几个LED都能够作为LCD4Linux的一个设备了,比如能够用来做邮件提醒、pidgin消息之类。同样是用V-USB,有个德国人做了个叫USB-LED-Fader的东东,同样是几个LED,人家可实现了每个灯在pwm控制下以独立的方式闪亮,要知道,atmega8只有两个pwm channel,而USB-LED-Fader里面没有用硬件pwm,而是用io口来输出的,为了实现独立波形,还实现了一个message queue,俨然一个操作系统了……所以他的固件编译出来4K多,即使我修改后也刷不进去mega48里面,就没得看看他的效果了。不过赞一下的是,这个项目虽然是玩具级别的,但是人家的电路、电路板、固件代码(注释)、文档、上位机控制(包括win版、win驱动)通通一应俱全,非常规范和详细,俨然一个商业项目。

将USB模块跟显示屏驱动模块合起来并没什么难度,几个月前我自己写过这个1602的驱动程序,虽然当时花了好几天,但实际上都只是很简单的几个函数。不过这次,因为接上USB后这块28针的mega48就没那么多io给我挥霍了,此前的驱动用的都是8位数据线,现在只能用4位,分两次传送。不过还好,这类HD44780的驱动几乎满地都是,一般外国人写的不像国内一些网站上面的,扔几个函数在那里就完事,LCD2USB的代码里面用的是Peter Fleury的LCD Library,封装得很漂亮,不过原来的代码只能讲4位数据线连接在一组io口的高四位上,而接上外置晶振后的mega48仅剩的带高位PortD,刚好又是几个pwm波输出,我打算另外再扩展协议让LCD2USB带有几个漂亮的提示灯,就重写了一下LCD的两个底层函数,当然不是仅仅重写,不然对不起原来那些漂亮的代码,用了宏定义来设置数据线是接在HIGHER_BIT or LOWER_BIT。

其实相比之下,LCD4Linux最精彩的地方在于它的驱动、插件的编写,新版里面其也支持了Python,意味着做个硬件版twitter器不是什么难事了!不过LCD4Linux本身的安装让我困扰了一天,大概作者没有时间吧,这个项目的主代码很几年没更新了,一个版本更新的跨幅有好几年,以致稍旧点的版本在新版本的内核里面编译不了,比如有个rdtscl的宏调用,在新内核里面被移除了……这个问题在LCD4Linux的SVN里面的版本倒是解决了,但是因为autotool的更新,编译过程又出错,折腾了半天,发现原来autoconf检查python的模块ac_python_devel 因为莫名的原因会让configure文件出错,下载一个新版的ax_python_devel.m4覆盖掉就好了。另外发现AUR里面的lcd4linux-svn包是“弃婴”,于是“收养”了回来更新,添加了个编译的patch,现在Archer们直接yaourt lcd4linux就可以编译安装了,O.O .

还是一句,LCD4Linux的可玩性非常高,说技术性嘛,不算高也不算低吧,召唤大家一起玩一起交流哈……

文章分类 Programming, 单片机 标签: , , , , , , ,
21 comments on “完成一个LCD4Linux的USB屏幕
  1. xifs说道:

    有点想玩这个..现在还闲置了一块at89s52的开发板

  2. stranger说道:

    Twitter观光团。。。
    博主什么专业的?

  3. PT说道:

    @stranger 呵呵……好像avr-gcc不支持89系列的MCU,遗憾阿……不过我倒是没买什么开发板,都是用芯片跟元件在面包板上面插的

    @欢迎推特er,哈哈!我网络工程专业,不过玩这东西好像跟专业关系不大,只要是理工科的玩这些应该都比较容易。

  4. maomaol说道:

    0.0 我又想玩。。。

  5. 517659780qq说道:

    我现在正在作51+USBD12,+LED。驱动部分VC不熟,只好用python,pyusb你的程序能看看吗。你的博客也无联系方式。

  6. BOYPT说道:

    pyusb使用没什么复杂的,打开pydoc就能看到文档了。

  7. PT说道:

    USBD12是不是能做全速和快速USB设备的?

  8. BOYPT说道:

    晕,你自己的设备别人怎么知道你怎么编阿……

    如果你说控制led这类简单的协议,用controlMsg足够了吧,自己先设计一个协议,配合单片机的固件才行。

    python写界面是很容易,但我怎么看也不觉得这个东西有必要写界面。

  9. BOYPT说道:

    =。=你想干吗?

    busses = usb.busses()
    for bus in busses:
    for dev in bus:
    xxxxxxx

    这样开始不就可以了

  10. 517659780qq说道:

    还有3问题:
    1;Wndows自带USB驱动,为什么开发一个USB设备要写驱动,是从头开始写吗?判断是否有USB设备插入——复位——设备描述符请——设置地址….而且USB协议规定包结束的标志是D+和D-同时为low for two bit time.我怎么才能控制PC输出D+和D-同时为low的信号。
    2;上面那个日本人的程序里:
    d=handle.controlMsg(requestType=0xc0,request=0xa2,
    value=offset*1024,index=2|(eeprom_address<<4)|(1<<8),
    buffer = 1024,timeout=1000)
    requestType=0xc0,0xc0=11000000.根据USB协议,
    Bit7: 0=Host to Device,1=Device to Host
    Bit6-5 :00=Standard,01=Class,02=Vendor,03=Reserved
    这是一个从设备到主机的类请求,我只查到了标准请求,不知道他这个类请求是起什么作用。
    3;主机如何识别USB–如何复位——如何设备描述符请求——如何设置地址…,是操作系统自动完成的呢?还是需要自己写呢?现在我做的USB control LED用控制传输,只用到pyusb中的DeviceHandle类的controlMsg。DeviceHandle类中其他的函数是不是用来作识别USB的啊。
    谢谢

  11. 517659780qq说道:

    楼主还没sleep啊

  12. 517659780qq说道:

    busses = usb.busses()
    dev = “”
    for bus in busses:
    devices = bus.devices
    for d in devices:
    if d.idVendor==vendor_id and d.idProduct==product_id:
    busses()在usb模块中是一个函数,返回a tuple with the usb busses
    但是我dir(usb.busses)
    没有发现usb.busses有devices这个变量啊?

  13. 517659780qq说道:

    你的QQ号是多少啊?现在我在线

  14. BOYPT说道:

    usb.busses当然没有阿,没看到bus是复数吗?busses是一个tuple,tuple里面的每个元素才有devices,devices又是一个tuple,每个是一个device……

    http://paste.ubuntu.org.cn/44961
    这个是我上次测试写的测试程序,随机控制几个灯亮灭,第一个值是选择灯0~3,第二个0或1控制开关

  15. BOYPT说道:

    =。=还有什么D+D-低电平之类的,libusb不会提供这么底层的东西,我看你也没必要用这样控制

  16. 517659780qq说道:

    恩,明白了。在单片机中我把要发送的interface 描述符的class 设制为HiD,以report形式返回数据。

    我不知道controlMsg中的参数如何确定。

  17. 517659780qq说道:

    还有你的文件中self.handle.claimInterface(self.device_descriptor.interface_id)是什么意思啊?
    claimInterface(…)
    | claimInterface(interface) -> None
    |
    | Claims the interface with the Operating System.
    | Arguments:
    | interface: interface number or an Interface object.
    唤醒系统 的接口?参数:接口数或者一个接口对像,
    |

  18. BOYPT说道:

    你管他什么意思,反正就是告诉操作系统你的用到这个设备,详细的看libusb的文档去;还有拜托别再在留言里面贴代码了,没看到paste.ubuntu.org.cn么……也不要单纯贴一个网址,会被spam掉;你可以用gtalk跟我聊。

  19. 蘑菇花说道:

    老大,用pyusb的话,要用写驱动吗?

  20. PT说道:

    呃,其实pyusb不关驱动事;驱动是操作系统跟usb设备之间的识别,这个跟设备的usb endpoint class信息有关;一般来说linux下不用驱动,插上后只要lsusb出现了设备的描述,就可以用pyusb打开了;Windows下,有些需要安装通用驱动,不然完全没法设备,当然也打不开了

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*