04年王根走的时候,留了一个液晶模块给我。可惜之后我一直忙于各种事务,把它给忘记了。最近突然有要做点什么东西的想法,想起那个pickit 2还没有怎么发挥作用,于是就把它们都翻了出来准备玩玩。
自从学会了用pic的单片机以后,就很少再用51的单片机,毕竟pic的单片拿来做小东西玩是最方便的。首先pic的单片机从6pin、8pin到14pin、18pin、20pin到再往上的都很多,小型化的可选择面很广。其次,就功能来说,pic的单片机比较多,构造小系统很方便,例如有内置的振荡器,不需要外接晶体就可以干活,即便是8pin的器件也有内置AD、比较器等的器件等等。不过由于其引脚比较少,所以用来做用户接口或者是显示来说,就不太方便了。这也是为什么我想用LCD模块来显示的原因。显示模块的另外一个好处就在于我可以很容易看到内部的运转状况,呵呵,对于没有在线调试器的我来说,这太有用了。
首先翻出来的是液晶模块的说明,介绍了模块的接口,命令字等等,还有MCU软件的范例程序,可惜是51系列的,而且没有太多的注释。还好,基本上可以对照着接口、命令字等看清楚流程。照着范例程序翻译成pic的程序,连接好线,编程,上电......可是屏幕上并没有出现任何的字符。
这往往是最痛苦的一步,因为你根本不知道问题出现在哪里。于是回头对着手册一步一步看,发现没有做液晶初始化的动作。但是手册上的代码设置工作方式前只有一个循环了三次的代码,并注释道“此循环很重要,不要去掉”。我faint,哪有这种注释的,不说原因。于是琢磨是为什么?看其送入的命令字,是让液晶工作在8bit接口状态的命令,可是为什么要送3次呢?
Thinking...
估计是首先假设不清楚LCD模块工作在什么模式下,因此LCD应当有三种情况:
1、LCD处于8bit工作状态下,则送一次命令字即可生效
2、LCD处于4bit工作状态下,且处于等待命令的第一个4bit,此时送两次4bit共8bit的命令字可生效
3、LCD处于4bit工作状态下,且处于等待命令的第二个4bit,此时不管之前的第一个4bit是什么,先送一次4bit完成前一次命令,再送两次4bit共8bit的命令字也可生效。
所以,初始化循环做了3次,确保液晶工作于8bit接口状态。此时,状态就是确定的了,只需要按照所需要的接口状态再送命令字(例如切换到4bit模式,送一次4bit模式高4位,再分高4、低4两次送完整的4bit接口命令字即可)。
理解清楚这个以后,确保初始化动作完整,居然还没有任何反应。再硬着头皮检查,看看4bit接口逻辑是否正确......居然......发现高低4bit的发送顺序反了,oh my god!!!这种低级错误也能发生!faint,改好,再编程,yeah,屏幕上出现了01234567。咦?难道这个是一块8字符的?我一直以为是16字符的液晶。看程序,所有的内存都填了字符了,应该不会有错了,8字符就8字符吧,也够用了,呵呵。一看表,也已经到临晨两点了~~
这次用pic的单片,也发现有很多要注意的地方,也收获很大。
第一是首次用可重定位的代码来写程序,这样以后的移植性会好一些,但是也不可避免会带来一些问题,如冗余代码比较多。因为内存的分配由编译器来完成,这样你就不知道变量处于哪个bank当中,不得不频繁的使用banksel来处理,即便可能这条语句并没有改变当前的状态。更为关键的是这是一条伪指令,生成的是两条代码。当然后期也发现了一些诀窍,例如同一个udata里面定义的数据一定是放在同一个bank里面的,等等。
第二觉得51系列的IO口在IO上还是比pic的方便一些,pic的代码不少花费在切换端口指向上,虽然是双向口,但是需要明确指定是input还是output,更罗嗦的input/output寄存器和端口数据寄存器还不在一个bank上,又不得不作banksel操作,再加上具体的数据也不知道存储位置,选择存储器还要用一个banksel,于是实际代码冗余得就更厉害了;
第三是对pic的初始化部分还不算很熟悉,这次居然没有对IO进行初始化就用了,结果好几个端口处于模拟输入状态上,没有任何的输出反应,这还是在软仿真的时候发现的,晕倒。
总的来说,几个小时搞定了这个事情,又把3年前玩的pic给捡回来了,还是很高兴的~~~
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=921894