基于8155的LCD显示电子码表设计
51单片机软件设计报告
——基于8155的LCD显示电子码表设计一、实验目的
本次课程设计是基于51单片机在理论课程的基础上,通过电路设计、理论计算、实际编程、调试、测试、分析查找故障,解决在实际设计中的问题,
使设计好的电路能正常工作。学习在理论课程的基础上,重点培养动手能力,
通过电路设计、理论计算、实际编程、调试、测试、分析查找故障,解决在实
际设计中的问题。学习Proteus软件的MCS51单片机仿真。
学习和完成的任务:
1.实验板的原理图结构研究
2.51单片机的编程技术
二、实验设备
(1)计算机一台
(2)Proteus软件平台
(3)KeiuVision软件平台
三、实验内容
电子码表类:基于8155的LCD显示电子码表设计
基本要求:
1 设计秒表功能,精度为0。01秒。
2 可同时记录和存储10个秒表数据。(连续记录并显示已存储记录数)
3 秒表记录数据查询和清除功能。
发挥部分:
1 外部脉冲数据记录(一信道,快速脉冲信号)。
2 外部记录触发信号输入(二信道,慢速存储信号)
3 自动存储和手动回放。
动态显示格式:
自定
四、实验原理
本次课程设计是在理论课程的基础上,目的在于培养我们的动手能力,通过电路设计、理论计算、实际编程、调试、测试、分析查找故障,解决在实际设计中的问题,使设计好的电路能正常工作,并可能结合实际的实验板进行下载测试。在此基础上根据实验大纲的要求,按“51单片机课程设计选题表”每人一题(随机分配),实现其功能。
单片机微型计算机简称单片机,是指在一块芯片体上集成了中央处理器CPU、随机存储器RAM、程序存储器ROM或EPROM、定时器/计数器、中断控制器以及串行和并行I/O 接口等部件,构成一个完整的微型计算机。目前,新型单片机内还有A/D及D/A转换器、高速输入/输出部件、DMA通道、浮点运算等特殊功能部件。由于它的结构和指令功能都是按工业控制设计要求设计的,特别适用于工业控制及其数据处理场合,因此,确切的称谓是微控制器,单片机只是习惯称呼。
(1)单片机的特点
1)有优异的性能价值比。
2)集成度高、体积小、有很高的可靠性。单片机把各个功能部件集成在一块芯片上,内部采用总线结构,减少了各芯片之间的连线,大大提高了单片机的可靠性与抗干扰能力。另外,其体积小,对于强磁场环境易于采取措施,适合于恶劣环境下工作;也易于产品化。
3)控制功能强。为了满足工业控制的要求,一般单片机的指令系统中均有及其丰富的转移指令、I/O口逻辑操作及位处理指令。一般来说,单片机的逻辑控制功能及运行速度高于同意档次的微机。
4)单片机的系统扩展和系统配置都比较典型、规范,而且非常容易构成各种规模的应用系统。
(2)单片机并行I/O接口的扩展
单片机与外部交换信息是通过I/O接口电路来实现的。A T89C51单片机本身有4个8位的并行I/O口P0-P3,但实际使用时往往再增加些I/O口,以便与外部设备交换数据。AT89C51单片机外部RAM和扩展I/O接口是统一编址的。用户可以把外部64KB RAM空间的一部分作为扩展I/O接口地址空间,每一个I/O接口相当于一个RAM存储单元,访问外部RAM存储单元就像访问外部I/O接口,即用“MOVX”指令对扩展I/O接口进行输入输出操作。
查询式键盘属于独立式键盘,键盘的各个按键之间彼此是独立的且是最简单的键盘电路。每个键地接入一根数据输入线。如图所示。注意:由于每一个按键均需要一根I/O口线,当键盘按键数量比较多时,需要的I/O口线也较多,因此独立式键盘只适合于按键较少的应用场合。一般情况下,按键数等于占用I/O端口数。
查询式键盘的结构图如图所示:
图2-5 查询式键盘的接口电路
查询式键盘可以工作在多种方式下,中断方式、程序查询方式、定时查询发送和中断查询方式。
在中断模式下,按键的数量受到外部中断源的限制。在有特殊需要的场合,还可以借用内部的定时器中断。所以在这种模式下,按键的数目小于外部中断源和单片机定时器数量之和。
程序查询和定时查询类似,都是通过读I/O状态,当有键被按下时相应的I/O口线变为低电平,而未被按下的键对应的I/O口线保持为高电平,这样通过读I/O口状态可判断是否有键按下和哪一个键被按下。
1.键盘定义
K1:开始、暂停记时
K2:记录数据
K3:计数器清零
K4:查看存储数据
2.流程图
(1)主流程图
(2)扫描键盘流程图
3.主程序
/***********************基于8155的LCD显示电子表设计************************************************/
#include
#include
#include
/*******************************************宏定义
***************************************************/
#define uint unsigned int
#define uchar unsigned char
/*******************************************定义8155地址
***********************************************/
#define COM8155 XBYTE[0X7FF8] //8155的命令口
#define PA8155 XBYTE[0X7FF9] //8155的PA
#define PB8155 XBYTE[0X7FFA] //8155的PB
#define PC8155 XBYTE[0X7FFB] //8155的PC
/*************************************************************延迟****************************************/
void delay_ms(uint z)
{
uint y;
for(;z>0;z--)
for(y=110;y>0;y--);
}
/*************************************************************向8155的输出端写入数据****************************************/
void write_com(unsigned char com)
PB8155=0x00;
PA8155=com ;
delay_ms(2);
PB8155=0x02;
delay_ms(2);
PB8155=0x00;
}
void write_data(unsigned char da)
{
PB8155=0x01;
PA8155=da ;
delay_ms(2);
PB8155=0x03;
delay_ms(2);
PB8155=0x01;
}
void write_str(unsigned char *str,unsigned char num) {
unsigned char i;
for(i=0;i write_data(str[i]); void lcd_init() { PB8155=0x00; write_com(0x38);//设置16X2 5X7点阵 write_com(0x0c);//开显示不显示光标 write_com(0x06);//写一个字符后地址指针加1 write_com(0x01);//lcd清屏 } void lcd_pos(unsigned char X,unsigned char Y) //第一行和第二行 { unsigned char pos; if(X==0) X=0x80; if(X==1) X=0x80+0x40; pos=X+Y; write_com(pos); } /*******************************************初始化程序 ***********************************************/ void initial() { COM8155=0x03; lcd_init(); //lcd初始化 } /*******************************************定义lcd显示的码值**************************************/ uchar dis_buf[8]={0}; //lcd显示缓存 /*******************************************定义系统变量 ***************************************************/ bit flag=0; //计时状态标志位 bit flag1=0,flag2=0,flag3=0,flag4=0; //按键状态标志位 uchar num,second,minute,hour; //秒表变量 uchar count=0; //计数器变量 uchar num_store[10],second_store[10],minute_store[10]; //储存秒表数据变量 uchar x; //记录数据计数器 /*******************************************键盘扫描程序 ***********************************************/ void keyscan() { uchar m; m=PC8155; m=m&0x0f; if(m!=0x0f) { delay_ms(20); //延时消抖 m=PC8155; m&=0x0f; if(m!=0x0f) //有键被按下 { m=PC8155; m&=0x0f; switch(m) { case(0x0e):flag1=1;break; //按键一被按下,其标志位置1 case(0x0d):flag2=1;break; //按键二被按下,其标志位置1 case(0x0b):flag3=1;break; //按键三被按下,其标志位置1 case(0x07):flag4=1;break; //按键四被按下,其标志位置1 } } while(PC8155!=0x0f); //判断键是否松开 } if(flag1==1) //按键一被按下,开始计时或停止计时 { TR0=~TR0; //计时开关取反 flag=0; flag1=0; //按键一标志位清零 } if(flag2==1) //按键二被按下 { if(TR0==1) //秒表计时,记录数据 { if(x<10) { minute_store[x]=minute; second_store[x]=second; num_store[x]=num; //记录秒表值 x++; //计数器加1 } } else //秒表停止,删除正在查看被记录的数据 { if(flag==1) { minute_store[count-1]=0; second_store[count-1]=0; num_store[count-1]=0; //删除当前查看的记录数据 } } flag2=0; //按键二标志位清零 } if(flag3==1) //按键三被按下,计时数据清零 { if(TR0==0) { num=0; second=0; minute=0; flag=0; //数据清零 } flag3=0; //按键三标志位清零 } if(flag4==1) //按键四被按下,查询记录的数据 { if(TR0==0) //判断计时状态 { flag=1; count++; //计数器加1,查看下一个被记录的数据 if(count>=11) //判断计数器是否超过范围 count=1; } flag4=0; //按键四标志位清零 } } void trans_data() { if(flag==0) //判断秒表是否处于计时状态 { if(hour==0&&minute<59) { dis_buf[0]=minute/10; dis_buf[1]=minute%10; dis_buf[3]=second/10; dis_buf[4]=second%10; dis_buf[6]=num/10; dis_buf[7]=num%10; //计时小于1小时,数据转换 } else { dis_buf[0]=hour/10; dis_buf[1]=hour%10; dis_buf[3]=minute/10; dis_buf[4]=minute%10; dis_buf[6]=second/10; dis_buf[7]=second%10; //计时超过1小时,数据转换 } } else { dis_buf[0]=minute_store[count-1]/10; dis_buf[1]=minute_store[count-1]%10; dis_buf[3]=second_store[count-1]/10; dis_buf[4]=second_store[count-1]%10; dis_buf[6]=num_store[count-1]/10; dis_buf[7]=num_store[count-1]%10; //对记录数据进行转换 } } /******************************************定时器*初始化程序***********************************************/ void init() { TMOD=0x11; //定义定时器的工作方式 TH0=(65536-10000)/256; TL0=(65536-10000)%256; //给T0装初值 //TH1=(65536-100)/256; //TL1=(65536-100)%256; //给T1装初值 ET0=1; //开T0的中断 //ET1=1; //开T1的中断 EA=1; //开总中断 TR0=0; //关闭T0 TR1=1; //开T0 hour=0; minute=0; second=0; num=0; //秒表变量初始化} /*******************************************主程序***************************************************/ void main() { initial(); init(); while(1) { keyscan(); trans_data(); lcd_pos(0,0x03); write_data(dis_buf[0]+48); write_data(dis_buf[1]+48); write_data(':'); write_data(dis_buf[3]+48); write_data(dis_buf[4]+48); write_data(':'); write_data(dis_buf[6]+48); write_data(dis_buf[7]+48); } } /*******************************************T0中断程序 *************************************************/ void timer0() interrupt 1 { TH0=(65536-10000)/256; TL0=(65536-10000)%256; //给T0装初值 num++; //0.01秒到,计数器加1 if(num==100) //判断1s时间是否到 { //1s到,num清零 num=0; //计数 second++; //秒加1, if(second==60) //判断1分钟是否到 { second=0; //秒清零 minute++; //分钟加1 if(minute==60) //判断1小时是否到 { minute=0; hour++; if(hour==24) hour=0; } } } } 五、实验过程及其记录 1.实验连接图 2.运行 3.K1闭合,开始计时, 4.K2点击两次记录两次数据,K1暂停计时 5.K4查看记录数据