四、软件编程篇
对软件编程的一些体会
我开做的第一软件是,静态的显示一个汉字,所以一直有这样的问题。字的颜色的深浅有些问题。后来看到别的同学已经有人做出了滚动字幕,于是让我加紧了对软件的开发,把显示问题放了一下。在软件开发中我又遇见了一些问题,就是原来用的编译软件masm51,编译出来的.hex文件不能直接通过isp下载线烧写到芯片,总是说没有找到000000001记录,开始时,我就下了一个hex转换成bin的小工具转换解决了此问题,但每编译一次都需要繁琐的dos命令行操作,使我下定决心,更换开发环境。我下了keil51开发环境,但是在上面只用它来做汇编的开发,我知道,他是专门来开发c的,但是不知道怎么用c,就暂时用它来做汇编的开发,也去图书馆了本keil 的书来,了解了其调试开发的用法。发现用keil编译生成的.hex文件,可以被isp下载线很好的支持,现在,我调试一个程序就只要按两下按钮就可以了,极大地方便了我的开发。
开始,一上来就进行字幕机的开发,让我根本没有见到什么成效,显示器上一直视乱码。估计是显示的时间问题。又查阅了相关的资料,直到了,显示器要让人眼能够看到图像,必须让扫描频率高于视觉暂留频率16Hz以上,为了消除鬼影(TBLANK),在切至下一行扫描线时,必须把上一行关闭一段时间(约50us)。有了这两个概念后,我的软件设计思路就基本有了。
就是每秒钟,至少在显示器上输出16帧图像,每扫描一行图像后要停留50us。我的设计思路是就打到16帧的额定帧数,是16*16的点阵,16帧做字幕机的话,正好走完一个汉字。
每帧所用的时间=1000(毫秒)/16帧=62.5毫秒/帧
一帧由16个扫描行组成
行显示时间=62.5*1000(微秒)/16行=3906.25us/行
然后再减去每行50微秒的暗时间,和子程序运行时间,我把行亮的时间设置为3000微秒,灭的时间设为50微秒
这样就完成了时间的计算问题。
接下来的编程问题,我运用了很多的子程序,每个问题都划分成更细微的问题,大概是受了学java语言面向对象编程思想的影响。比如说读取一个字ReadWord,我把它分成了两部去做,先写了一个读取一个字ReadByte的子程序,然后再让ReadWord,来调用两次ReadByte。这样程序就很好纠错,结构清晰了。
还有这次用汇编的开发过程,也让我更进一步的了解到了计算机的原理。才确确实实的是和硬件在打交道了。发现汇编里面就是程序的结构化不够清晰,循环,判断,等操作的出口与如口都要自己操作,主要是要解决好出口与入口的问题。 CJNE可以解决汇编程序的判断问题,用jmp解决出口问题,写汇编,我的体会是,写了汇编时脑子一定要清醒,你要了解程序运行的每一个状态,某一个寄存器的状态,这样,所写程序运行的结果菜会如你所愿。
从总体上看来,我的这个字幕机的软件制作过程中,有两个难点。
第一:16位的数据指针的控制问题。在101个命令中我就发现了INC DPTR 和 MOV DPTR,#data,两个可以改变dptr命令的指令,后来用直接寻址的方法,直接加减DPTR的两个寄存器82h和83h很好的解决了DPTR的控制问题。
第二: 就是在最后的数据区盘尾标示上,我开始时用的是10101010B这个字节判尾,后来发现汉字码中有这个表示.后来又试验了几个,汉字中都与他又重码,我原本已经打算重写一个判尾子程序了,就是把尾部的32个数据全部读入,判断空字节数是否达到了32,但这个代码量也不小。但在最后几次试验中使我找到了 0CFH这个尾标识汉字中好像没有重码。(2005年11月 修改 发现并非如此,cf也有重码)然后我就使用了这个代码。后来听老师说0CFH是常用的汉字判尾标识,这真是殊途同归。
最后,为了多方借个汉字,我进行了一点代码的优化,比如吧开发时多定义的一些变量删除,让代码区更小些,然后再把一些原来用送立即数的清零方式(占两个字节的指令)改为用ANL A,MOV P1,A;的方式(占一个字节的指令来代替)。
还有汉字的点阵提取是使用一个叫“提取汉字点阵程序v1.1”的程序完成的,所以对字幕的修改非常的方便。一些相关的制作参考资料我附在随文档的光盘中了。
五、总结
通过这次对单机的学习,一方面使我基本对单片机有了些了解,但我觉得很重要的一方面是使我懂得了一套解决问题的方法,面对问题,可以先分析,然后再查阅相关资料,正式可行性,让后解决问题。渐渐的可以独立的解决一些问题,在解决问题中成长题高。
附录1 开发实战中相对应的程序源代码
;字幕机员程序
ORG 00H;
CALL CLRP02; P0,P2清零
MOV P1,A;
MOV DPTR,#TAB;
DISPLAY:
JMP EOF;
;判断数据指针是否到了数据区的尾部
EOFRET:
;EOF的返入口
CALL ZHEN;
MOV R3,#01EH; 数据指针退30格 ,从 下一行开始重新扫描;
DECDPTRLH:CALL DECDPTR;
DJNZ R3,DECDPTRLH
JMP DISPLAY;
EOF:MOV A,#00H; 判断数据指针是否到了数据区的尾部
MOVC A,@A+DPTR;
CJNE A,#0CFH,EOFRET;
MOV DPTR,#TAB;
JMP EOFRET;
ZHEN: MOV R2,#010H; 显示一帧,一个画面
ZHEN1:CALL CLRP02;
CALL RW
MOV R6,#5
D1:MOV R7,#248;
DJNZ R7,$
DJNZ R6,D1;
CALL CLRP02;
MOV R7,#25;
DJNZ R7,$;
INC P1;
DJNZ R2,ZHEN1;
RET
RW: CALL RB; READ A WORD 读取一个字,两个byte
MOV 21H,A;
CALL RB;
MOV 22H,A;
JMP QUAA;
QUAARET:
MOV P0,21H;
MOV P2,22H;
RET;
QUAA:
;消除显示时尾因为末尾标记而产生的字幕结束时的拖尾
MOV A,21H;
CJNE A,#0CFH,QUAARET;
MOV 21H,#00H;
JMP QUAARET;
RB: MOV A,#00H;READ BYTE读取一个byte
MOVC A,@A+DPTR;
INC DPTR;
RET;
CLRP02: ANL A,#00H;
MOV P2,A; P0,P2清零
MOV P0,A;
RET
DECDPTR:
;DPTR减一
CALL C82H0; 判断
DEC 82H;
RET
C82H0:
;看82h(DPL)的值是减到了零 考虑83h(DPH)退位
MOV A,82H;
JZ TUIWEI83H; DPH退位
RET
TUIWEI83H:
;DPH退位(DPTR高字节)
DEC 83H;
RET
TAB:
DB 00H,00H,00H,00H,00H,00H,00H,00H
DB 00H,00H,00H,00H,00H,00H,00H,00H
DB 00H,00H,00H,00H,00H,00H,00H,00H
DB 00H,00H,00H,00H,00H,00H,00H,00H
;------------过渡头数据------------
;数据区,可以直接填入汉字的点阵编码,无需修改程序
DB 0CFH;尾标示
;------------过渡尾数据--------------
DB 00H,00H,00H,00H,00H,00H,00H,00H
DB 00H,00H,00H,00H,00H,00H,00H,00H
DB 00H,00H,00H,00H,00H,00H,00H,00H
DB 00H,00H,00H,00H,00H,00H,00H,00H
END;
附录2 参考资料在盘上的位置
文件夹 PATH 列表
卷序列号码为 0006FE80 50CE:704B
E:.
├─我在文曲星上开发的一个500行的basic小程序完全独立开发
└─附从零开始学单片机学习及关参考资料
├─2个Hex转Bin的小程序
├─IC芯片的技术资料
│ ├─atmel89c51
│ ├─atmel89s51
│ └─SN74LS138N
├─单片机自学资料
│ ├─document
│ ├─smcu.51.net
│ └─www.01mcu.com
│ └─mcu_cai
│ └─experiment
│ └─soft
├─发光二极管相关资料
│ ├─发光二极管(LED)_files
│ ├─电子技术天地--超高亮度发光二极管TLC-58_files
│ ├─飞达光学 - 光学论文 - 半导体发光二极管(LED)_files
│ │ └─bdun_files
│ └─飞达光学 - 光学论文 - 白色LED的开发和应用_files
│ └─bdun_files
├─开发工具资料
│ ├─isp下载线相关资料
│ └─自制ez51编程器制作参考资料
└─提取汉字点阵程序