1.3 系统软件主程序结构及其函数
系统主程序完成主循环和对各模块函数的调用,调用的文件包括:reg52.h、asc.h、 12864.h,其中reg52.h是 8051内核单片机的标准头文件,定义了单片机内部各寄存器的地址,使用户编程更方便;asc.h存储了本单词记忆测试器的单词和中文汉字字模块,供显示函数调用,而12864.h为LCD12864显示屏的底层驱动程序,包括了屏显示的指令函数和显示中英文的函数。
在KEIL uV3环境下将 主程序文件和reg52.h、asc.h、12864.h放在同一工程工作组中,以便主程序调用,如图13。
图13 keil下的 程序工程文件
主程序的函数:
主程序首先进行存储变量的定义:
bit ERROR; //输入字符错误标志位,输入错误为 1 bit result; //输入的最终结果对错的标志位,为0是正确 bit verify; //标志按过一次确认键
sbit ERR=P2^7; //P2.7 口接一个指示灯警告输入错误 uchar correctNUM; //统计测试正确的单词数,即得分 uchar code
为能动态地显示测试的单词,先将要测试的单词存在一个二维数组中,显示了该数组中的字符时,12864.h中的显示函数会调用 相应字符的字模码(asc.h中);
/***************************************** /** 存储要测试的单词,放在ROM中
/****************************************/ uchar code S[10][5]={ \树
\雨 \水 \飞 \去 \鱼 \雪 \吃 \米 \冰 } ;
SL[10]={4,4,5,3,2,4,4,3,4,3};
//存储各测试单词的长度,如果输入的单词长度与存储的不同,也为错误
该二维数组为行*列 10*5,即10行5列,10行表示有10个单词,实际根据存储ROM的大小,可以增加单词数;列数表示单词在存储器中占的字符数,以最长单词(5个字符)定义,不足5个字符的单词后补空格表示。
前节介绍过键盘的输入是通过矩阵扫描的方法,通过矩阵扫描可使单片机找到按键所在的某行某列,但要得到一个英文字母值,还得在单片机返回的某行某列位置预先定义个字母值,因此5*6矩阵键盘的整个返回字母表可定义一个二维数组存储:
/***************************************** /** 存储键盘的字母值 ,放在ROM中
/****************************************/
uchar code tab1[6][5]={{'a','b','c','d','e'},
{'f','g','h','i','j' }, {'k','l','m','n','o' }, {'p','q','r','s','t' },
{'u','v','w','x','y'}, {'z', 1, 2 , 3 , 4} };
例如在按下键盘时,单片机返回键盘位置为 第二行第三列,就可从上表中查出是对应位置的字母。 键盘扫描函数返回的是键值。
key=tab1[hang][lie];
进入主程序后,先对LCD12864屏进行初始化和清屏操作,然后在LCD12864屏上显示单片机单词记忆测试器的静态的图文,需要动态刷新的字符则在主循环中进行。
LCD12864_init(); ClearLCD(); \
//最后的“1”表示显示为白底黑字,如是0则为黑底白字,即反显 en_disp(4,1,1,Asc,\在第5行,第5列开始显示\
en_disp(6,0,8,Asc,\在第7行,第1列开始显示\
en_disp(6,80,5,Asc,\在第7行 第81列显示\
LCD12864的显示效果如下,此时系统进入单词输入测试就绪状态。
//LCD12864初始化 //清屏
en_disp(2,1,11,Asc,\在第3行 第21列 显示
在系统进入单词输入测试就绪状态后,主程序即进入while(1)的主循环中,循环进行键盘扫描,并判断键盘输入值,再与待测试的单词进行比较,如果输入的字符和字符长度均与被测试的单词一致,则显示correct加1,即为加1分,并进入下一个单词的测试,测试完10个单词后,重新进入第1个单词的测试。
主程序的主循环部分代码及注释如下:
while(1)
{ KeyNum[iword]=kbscan(); 输入值
hz_disp(0,48,1,hz1+hz_Num*32,1); //在第1行,第49列开始显示测试的汉字
temp[0]=(hz_Num+1)/10+0x30; temp[1]=(hz_Num+1)+0x30; 位
en_disp(0,20,1,Asc,\在第1行 第21列显示\ en_disp(0,4,2,Asc,temp,1); //在第1行 第5列 显示测试序号 if(KeyNum[iword]!='_') //键盘有按键按下,无按下返回的是'_' {
if(KeyNum[iword]==1) //如果按下了确定键 {
if(SL[hz_Num]==iword&&verify)
//输入长度等于测试单词的长度,则正确 ,verify表示按下了确认后有效一次 {
correctNUM+=1; if(correctNUM>10) {
correctNUM=10; //最多10个正确的 }
verify=0; //标志位清零 hz_Num++; //测试下一个单词 if(hz_Num==10) hz_Num=0; temp[0]=(correctNUM)/10+0x30; temp[1]=(correctNUM)+0x30; 位
en_disp(6,80,2,Asc,temp,1); //在第7行 第81列 iword=0; Nword=0;
en_disp(4,16,8,Asc,\在第5行,第17列开始显示
//进行矩阵按键扫描,得到扫描键盘的
//将十进制数转换为ASCII字符 //算出测试汉字的序号的第一位和第二
//temp数组用来存储测试的序号
//最多设10个单词
//将十进制数转换为ASCII字符 //算出测试汉字的序号的第一位和第二