常熟理工学院单片机实习

更新时间:2024-06-16 21:27:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

目录

第一章 总体设计方案

1.1总体设计方案﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒2页 1.2软硬件功能分析 ﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒ 2页 第二章 硬件电路设计

2.1单片机最小系统电路设计﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒3页 2.2 总电路 ﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒3页 2.3 显示电路的设计 ﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒4页 2.4调时电路设计﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒5页 第三章 系统软件设计

3.1 软件总体设计思路 ﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒6页 3.2 主程序流程设计 ﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒6页 3.3 中断服务子程序设计 ﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒7页 实习总结 ﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒8页 参考文献 ﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒9页 附录 ﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒10页 附录1 总仿真图 ﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒10页 附录2 源程序 ﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒11页 附录3 元器件介绍 ﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒32页

1

第1章 总体设计方案

1.1 总体设计方案

本设计是可编程作息时间控制器设计,由单片机AT89C51芯片和LCD、LED

显示器,辅以必要的电路,构成一个单片机四路可调闹钟。电子钟可采用数字电路实现,也可以采用单片机来完成。LCD显示“时”,“分”,LED亮灯来表示闹钟的到来,定时时间到能发出警报声。现在是自动化高度发达的时代,特别是电子类产品都是靠内部的控制电路来实现对产品的控制,达到自动运行的目的,这就需要我们这里要做的设计中的电器元件及电路的支持。

在这次设计中主要是用AT89C51来进行定时,也结合着其他辅助电路实施控制,在定时的时候,按一下控制小时的键对小时加一;按一下控制分钟的键对分钟加一;到达预设的时间,此电路就会发出报警声音提示已经到点。

下图为可编程作息时间控制器系统框图。

可编程作息时间控制器系统框图。

1.2 软硬件功能分析

系统的总体工作过程是这样的:

首先是LCD和单片机的初始化,通过不断进行按键检测,判断是否有键按下。如果有,则进入相应的子程序中进行按键的处理。如果没有,则继续更新屏幕显示时间。本系统的计时是通过定时器T1实现的,在T1中断程序中囊括了时钟的进位,时钟的计时,以及对是否达到闹钟时间进行判断并进行处理。

此外,还进行了秒表、温度显示等功能的拓展。

2

第2章 硬件电路设计

2.1单片机最小系统电路设计

电片机最小系统设计是单片机应用系统设计的基础。AT89C51单片机最小系

统电路如下图所示。

单片机最小系统电路

2.2 总电路

总电路包括:显示电路,调时电路,震荡电路,铃声电路等。

3

总电路

2.3显示电路的设计

本设计利用LCD作为显示单元,电路如下。(仅供查看,与实际实验箱不同)

显示电路

4

2.4 调时电路设计

本系统调时电路由四个独立按键组成,如下图:

调时电路

按键功能如下:

(1)时钟时间的设置:首先单击Kl进入时钟设置模式。此时每单击一下Kl,则小时增l,单击一下K2,则分钟增1,再单击K3则设置完成,返回时钟显示模式。此时小时和分钟均已发生变化。

(2)闹铃的时间设置:首先单击,K3进入闹铃的设置模式。此时每单击一下Kl,则小时增1,单击一下K2,则分钟增l,最后单击.K3则设置完成,返回闹铃显示模式。此时闹铃的小时和分钟均已发生变化。

(3) K4的功能:进入闹钟设置模式时,按下K4,更换所要设置的闹钟。 (4) K2单独的功能:显示闹铃时间。

5

附录2 源程序(此程序与实验箱相配)

#include #define uint unsigned int #define uchar unsigned char sbit key1=P3^2; sbit key2=P3^3; sbit key3=P3^4; sbit key4=P3^5; sbit lcden=P2^7; sbit lcdrs=P2^6; sbit lcdrw=P2^5; sbit led=P2^2; sbit sound=P1^0;

int a,b,i,min,hour,minge,minshi,hourge,hourshi,sec,secge,secshi,cnt,cnt1, nian=2014,yue=3,ri=7, amin1=1,ahour1,aminge1,aminshi1,ahourge1,ahourshi1, amin2=1,ahour2,aminge2,aminshi2,ahourge2,ahourshi2, amin3=1,ahour3,aminge3,aminshi3,ahourge3,ahourshi3, amin4=1,ahour4,aminge4,aminshi4,ahourge4,ahourshi4;

uchar code table1[]={'0','1','2','3','4','5','6','7','8','9'}; uchar code table2[]=\ \;

uchar code table3[]={0x1F,0x11,0x11,0x1F,0x11,0x11,0x11,0x1F}; uchar code table4[]={0x00,0x0E,0x0A,0x0E,0x00,0x00,0x00,0x00}; uchar code table5[]={0x0F,0x09,0x0f,0x09,0x0f,0x09,0x09,0x11}; uchar code table6[]={0x06,0x09,0x08,0x08,0x09,0x06,0x00,0x00}; uchar code table7[]={0x01,0x1E,0x04,0x1F,0x0E,0x15,0x04,0x04}; uchar code table8[]={0x04,0x0E,0x15,0x04,0x02,0x04,0x18,0x00}; uchar code table9[]={0x08,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02}; uchar code Alarm_1[]=\ %uchar code Alarm_2[]=\ %uchar code Alarm_3[]=\ %uchar code Alarm_4[]=\ %uchar code riqi[]=\ \

uchar num1,num2,alarm1,alarm2,alarm3,alarm4; bit flag=0;

void delay(unsigned int z) //延时程序 { uint i,j; for(i=z;i>0;i--) for(j=110;j>0;j--);

11

}

void write_com(uchar com) //LCD命令控制,写指令函数 { delay(5) ; lcdrs=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; }

void write_data(uchar date) //LCD数据控制,写数据函数 { delay(5); lcdrs=1; P0=date; delay(5); lcden=1; delay(5); lcden=0; }

void write_nian(uchar add , uint date) //年显示函数 {

uchar qian,bai,shi,ge; qian=date/1000;

bai=(date-1000*qian)/100;

shi=(date-qian*1000-bai*100)/10; ge=date;

write_com(0x80+0x40+add); write_data(table1[qian]); write_data(table1[bai]); write_data(table1[shi]); write_data(table1[ge]); }

void write_yue(uchar add , uchar date) //月显示函数 {

uchar shi,ge; shi=date/10; ge=date;

write_com(0x80+0x40+add); write_data(0x30+shi); write_data(0x30+ge);

12

}

void write_ri(uchar add , uchar date) //日显示函数 {

uchar shi,ge; shi=date/10; ge=date;

write_com(0x80+0x40+add); write_data(0x30+shi); write_data(0x30+ge); }

void qi() //总日期显示函数 {

write_nian(0,nian); write_yue(5,yue); write_ri(8,ri);

write_com(0x80+0x40+7);

write_data(0x01);//显示自定义“月”字 write_com(0x80+0x40+4); write_data('-'); write_com(0x80+0x40+10); write_data(0x00);//显示自定义“日”字 }

void time() //设置时间函数 { while(1) { if(key1==0) { delay(10); if(key1==0) //按键检测与消抖 { if(hour==23) //\时\设置 hour=0; else hour++; hourge=hour; hourshi=hour/10;

13

write_com(0x0f); //显示开,光标开且闪烁 delay(2); write_com(0x80+6); write_data(table1[hourge]); //\时\个位写入LCD第1行第6位 delay(5); write_com(0x80+5); delay(2); write_data(table1[hourshi]); //\时\十位写入LCD第1行第5位 while(!key1); //松手检测 } } if(key2==0) { delay(10); if(key2==0) { if(min==59) //\分\设置 min=0; else min++; minge=min; minshi=min/10; write_com(0x0f); //显示开,光标开且闪烁 write_com(0x80+9); write_data(table1[minge]); //\分\个位写入LCD第二行第9位 delay(1); write_com(0x80+8); write_data(table1[minshi]); //\分\十位写入LCD第二行第8位 delay(1); while(!key2); //松手检测 } } if(key3==0) { delay(10); if(key3==0) { write_com(0x0c); //整体显示,关光标,不闪烁 TR1=1; //定时计数器1启动 while(!key3); break; //key3松开时,显示时间\时\分\位均已设置完毕

14

} } } }

void display1() //设置闹钟1时间函数 { while(1) { if(key1==0) { delay(10); if(key1==0) { if(ahour1==23) //闹钟\时\设置 ahour1=0; else ahour1++; ahourge1=ahour1; ahourshi1=ahour1/10; write_com(0x0f); //显示开,光标开且闪烁 write_com(0x80+0x40+8); //写入显示地址 write_data(':'); write_com(0x80+0x40+7); write_data(table1[ahourge1]); delay(1); write_com(0x80+0x40+6); write_data(table1[ahourshi1]); delay(1); while(!key1); } } if(key2==0) //闹钟\分\设置 { delay(10); if(key2==0) { if(amin1==59) amin1=0; else amin1++; aminge1=amin1; aminshi1=amin1/10; write_com(0x0f); write_com(0x80+0x40+10);

15

write_data(table1[aminge1]); delay(1); write_com(0x80+0x40+9); write_data(table1[aminshi1]); delay(1); while(!key2); } } if(key3==0) { alarm1=~alarm1; delay(10); if(key3==0) { write_com(0x0c); //开显示,关光标关闪烁 write_com(0x80+0x40); for(i=0;i<11;i++) write_data(riqi[i]); while(!key3); break; //设置结束,此时LCD第二行无数据显示,只有第一行有时间显示 } } } }

void display2() //设置闹钟2时间函数 { while(1) { if(key1==0) { delay(10); if(key1==0) { if(ahour2==23) //闹钟\时\设置 ahour2=0; else ahour2++; ahourge2=ahour2; ahourshi2=ahour2/10; write_com(0x0f);

16

write_com(0x80+0x40+8); write_data(':'); write_com(0x80+0x40+7); write_data(table1[ahourge2]); delay(1); write_com(0x80+0x40+6); write_data(table1[ahourshi2]); delay(1); while(!key1); } }

if(key2==0) //闹钟\分\设置 { delay(10); if(key2==0) { if(amin2==59) amin2=0; else amin2++; aminge2=amin2; aminshi2=amin2/10; write_com(0x0f); write_com(0x80+0x40+10); write_data(table1[aminge2]); delay(1); write_com(0x80+0x40+9); write_data(table1[aminshi2]); delay(1); while(!key2); } }

if(key3==0) {

alarm2=~alarm2; delay(10); if(key3==0) { write_com(0x0c); write_com(0x80+0x40); for(i=0;i<11;i++) write_data(riqi[i]); while(!key3);

17

break; //设置结束,此时LCD第二行无数据显示,只有第一行有时间显示 } } } }

void display3() //设置闹钟3时间函数 { while(1) { if(key1==0) { delay(10); if(key1==0) { if(ahour3==23) //闹钟\时\设置 ahour3=0; else ahour3++; ahourge3=ahour3; ahourshi3=ahour3/10; write_com(0x0f); write_com(0x80+0x40+8); write_data(':'); write_com(0x80+0x40+7); write_data(table1[ahourge3]); delay(1); write_com(0x80+0x40+6); write_data(table1[ahourshi3]); delay(1); while(!key1); } } if(key2==0) //闹钟\分\设置 { delay(10); if(key2==0) { if(amin3==59) amin3=0; else amin3++;

18

aminge3=amin3; aminshi3=amin3/10; write_com(0x0f); write_com(0x80+0x40+10); write_data(table1[aminge3]); delay(1); write_com(0x80+0x40+9); write_data(table1[aminshi3]); delay(1); while(!key2); } } if(key3==0) {

alarm3=~alarm3; delay(10); if(key3==0) { write_com(0x0c); write_com(0x80+0x40); for(i=0;i<11;i++) write_data(riqi[i]); while(!key3); break; //设置结束,此时LCD第二行无数据显示,只有第一行有时间显示 } } } }

void display4() //设置闹钟4时间函数 { while(1) { if(key1==0) { delay(10); if(key1==0) { if(ahour4==23) //闹钟\时\设置 ahour4=0; else

19

ahour4++; ahourge4=ahour4; ahourshi4=ahour4/10; write_com(0x0f); write_com(0x80+0x40+8); write_data(':'); write_com(0x80+0x40+7); write_data(table1[ahourge4]); delay(1); write_com(0x80+0x40+6); write_data(table1[ahourshi4]); delay(1); while(!key1); } }

if(key2==0) //闹钟\分\设置 { delay(10); if(key2==0) { if(amin4==59) amin4=0; else amin4++; aminge4=amin4; aminshi4=amin4/10; write_com(0x0f); write_com(0x80+0x40+10); write_data(table1[aminge4]); delay(1); write_com(0x80+0x40+9); write_data(table1[aminshi4]); delay(1); while(!key2); } }

if(key3==0) {

alarm4=~alarm4; delay(10); if(key3==0) { write_com(0x0c);

20

write_com(0x80+0x40); for(i=0;i<11;i++) write_data(riqi[i]); while(!key3); break; //设置结束,此时LCD第二行无数据显示,只有第一行有时间显示 } } } }

void keyscan() //键盘扫描 { if(key1==0) { delay(10); if(key1==0) { while(!key1); //key1键松开后执行下一行程序 time(); //调用time()函数,即时间设置 } } else if(key2==0) { cnt1++; delay(10); if(cnt1==1) { while(!key2) { ahourge1=ahour1; ahourshi1=ahour1/10; write_com(0x80+0x40+7); write_data(table1[ahourge1]); delay(5); write_com(0x80+0x40+6); delay(2); write_data(table1[ahourshi1]); aminge1=amin1; aminshi1=amin1/10; write_com(0x80+0x40+10);

21

write_data(table1[aminge1]); delay(5); write_com(0x80+0x40+9); delay(2); write_data(table1[aminshi1]); write_com(0x80+0x40+8); write_data(':'); write_com(0x80+0x40); for(i=0;i<6;++i) write_data(Alarm_1[i]); } write_com(0x80+0x40); for(i=0;i<11;i++) write_data(riqi[i]); 时间,闹钟设置时间不显示 } if(cnt1==2) { while(!key2) { ahourge2=ahour2; ahourshi2=ahour2/10; write_com(0x80+0x40+7); write_data(table1[ahourge2]); delay(5); write_com(0x80+0x40+6); delay(2); write_data(table1[ahourshi2]); aminge1=amin1; aminshi1=amin1/10; write_com(0x80+0x40+10); write_data(table1[aminge2]); delay(5); write_com(0x80+0x40+9); delay(2); write_data(table1[aminshi2]); write_com(0x80+0x40+8); write_data(':'); write_com(0x80+0x40); for(i=0;i<6;++i) write_data(Alarm_2[i]); } write_com(0x80+0x40);

//显示闹钟设置的时间 //key2松开后,LCD只有第一行显示 //显示闹钟设置的时间 22

for(i=0;i<11;i++) write_data(riqi[i]); //key2松开后,LCD只有第一行显示时间,闹钟设置时间不显示 } if(cnt1==3) { while(!key2) { ahourge3=ahour3; ahourshi3=ahour3/10; write_com(0x80+0x40+7); write_data(table1[ahourge3]); delay(5); write_com(0x80+0x40+6); delay(2); write_data(table1[ahourshi3]); aminge1=amin1; aminshi1=amin1/10; write_com(0x80+0x40+10); write_data(table1[aminge3]); delay(5); write_com(0x80+0x40+9); delay(2); write_data(table1[aminshi3]); write_com(0x80+0x40+8); write_data(':'); write_com(0x80+0x40); for(i=0;i<6;++i) write_data(Alarm_3[i]); } write_com(0x80+0x40); for(i=0;i<11;i++) write_data(riqi[i]); 时间,闹钟设置时间不显示 } if(cnt1==4) { while(!key2) { ahourge4=ahour4; ahourshi4=ahour4/10;

//显示闹钟设置的时间 //key2松开后,LCD只有第一行显示23

write_com(0x80+0x40+7); write_data(table1[ahourge4]); delay(5); write_com(0x80+0x40+6); delay(2); write_data(table1[ahourshi4]); aminge1=amin1; aminshi1=amin1/10; write_com(0x80+0x40+10); write_data(table1[aminge4]); delay(5); write_com(0x80+0x40+9); delay(2); write_data(table1[aminshi4]); write_com(0x80+0x40+8); write_data(':'); write_com(0x80+0x40); for(i=0;i<6;++i) write_data(Alarm_4[i]); //显示闹钟设置的时间 } write_com(0x80+0x40); for(i=0;i<11;i++) write_data(riqi[i]); //key2松开后,LCD只有第一行显示时间,闹钟设置时间不显示 }

if(cnt1>4) cnt1=0; }

else if(key3==0) { loop: cnt++; delay(10); if(cnt==1) { while(!key3); //表示闹钟时间设置退出 ahourge1=ahour1; ahourshi1=ahour1/10; write_com(0x80+0x40+7); write_data(table1[ahourge1]); delay(5); write_com(0x80+0x40+6); delay(2);

24

write_data(table1[ahourshi1]); aminge1=amin1; aminshi1=amin1/10; write_com(0x80+0x40+10); write_data(table1[aminge1]); delay(5); write_com(0x80+0x40+9); delay(2); write_data(table1[aminshi1]); write_com(0x80+0x40+8); write_data(':'); write_com(0x80+0x40); for(i=0;i<6;++i) write_data(Alarm_1[i]); while(P3==0xff); if(key1==0||key2==0||key3==0) { delay(10); if(key1==0||key2==0||key3==0) {display1(); } } else if(key4==0) goto loop; } if(cnt==2) { while(!key3); //表示闹钟时间设置退出 ahourge2=ahour2; ahourshi2=ahour2/10; write_com(0x80+0x40+7); write_data(table1[ahourge2]); delay(5); write_com(0x80+0x40+6); delay(2); write_data(table1[ahourshi2]); aminge2=amin2; aminshi2=amin2/10; write_com(0x80+0x40+10); write_data(table1[aminge2]); delay(5); write_com(0x80+0x40+9); delay(2); write_data(table1[aminshi2]); write_com(0x80+0x40+8);

25

write_data(':'); write_com(0x80+0x40); for(i=0;i<6;++i) write_data(Alarm_2[i]); while(P3==0xff); if(key1==0||key2==0||key3==0) { delay(10); if(key1==0||key2==0||key3==0) {display2(); } } else if(key4==0) goto loop; } if(cnt==3) { while(!key3); //表示闹钟时间设置退出 ahourge3=ahour3; ahourshi3=ahour3/10; write_com(0x80+0x40+7); write_data(table1[ahourge3]); delay(5); write_com(0x80+0x40+6); delay(2); write_data(table1[ahourshi3]); aminge3=amin3; aminshi3=amin3/10; write_com(0x80+0x40+10); write_data(table1[aminge3]); delay(5); write_com(0x80+0x40+9); delay(2); write_data(table1[aminshi3]); write_com(0x80+0x40+8); write_data(':'); write_com(0x80+0x40); for(i=0;i<6;++i) write_data(Alarm_3[i]); while(P3==0xff); if(key1==0||key2==0||key3==0) { delay(10); if(key1==0||key2==0||key3==0) {display3();

26

} } else if(key4==0) goto loop; }

if(cnt==4) { while(!key3); //表示闹钟时间设置退出 ahourge4=ahour4; ahourshi4=ahour4/10; write_com(0x80+0x40+7); write_data(table1[ahourge4]); delay(5); write_com(0x80+0x40+6); delay(2); write_data(table1[ahourshi4]); aminge4=amin4; aminshi4=amin4/10; write_com(0x80+0x40+10); write_data(table1[aminge4]); delay(5); write_com(0x80+0x40+9); delay(2); write_data(table1[aminshi4]); write_com(0x80+0x40+8); write_data(':'); write_com(0x80+0x40); for(i=0;i<6;++i) write_data(Alarm_4[i]); while(P3==0xff); if(key1==0||key2==0||key3==0) { delay(10); if(key1==0||key2==0||key3==0) {display4(); } } else if(key4==0) goto loop; }

if(cnt>4) {

cnt=0; }

27

} }

void lcd_init() //LCD初始化 { lcden=0; lcdrw=0; write_com(0x38); //设置8位格式,2行,5×7 write_com(0x0c); //整体显示,关光标,不闪烁 write_com(0x06); //设定输入方式,增量不转移 write_com(0x01); //清除屏幕显示 delay(2); write_com(0x80); for(i=0;i<16;i++) { write_data(table2[i]); //写入显示时间数据 delay(1); }

write_com(0x40); for(i=0;i<8;i++) { write_data(table3[i]); //写入自定义字符“日” delay(1); } write_com(0x40+8); for(i=0;i<16;i++) { write_data(table5[i]); //写入自定义字符“月” delay(1); } write_com(0x40+16); for(i=0;i<8;i++) { write_data(table4[i]); //写入自定义字符 delay(1); } write_com(0x40+24); for(i=0;i<8;i++) { write_data(table6[i]); //写入自定义字符 “C” delay(1);

28

} write_com(0x40+32); for(i=0;i<8;i++) { write_data(table7[i]); //写入自定义字符“秒” delay(1); } write_com(0x40+40); for(i=0;i<8;i++) { write_data(table8[i]); delay(1); } write_com(0x40+48); for(i=0;i<8;i++) { write_data(table9[i]); delay(1); } }

void judge() { if(sec==60) { min++; sec=0; } if(min==60) { hour++; min=0; } if(hour==24) { ri++; hour=0; } if(ri==30) { yue++; ri=1; }

//写入自定义字符“秒” //写入自定义字符“年” 29

if(yue==12) { nian++; yue=1; } }

void init() //C51初始化函数 { key1=1;key2=1;key3=1;key4=1;sec=0;a=0;sound=1; TMOD=0x10; //定时计数器T1工作在方式1 TL1=0xB0; TH1=0x3C; //计数初值为15536,50ms定时 EA=1; ET1=1; TR1=1; }

void speak()//music { if(amin1==min&&ahour1==hour||amin2==min&&ahour2==hour||amin3==min&&ahour3==hour||amin4==min&&ahour4==hour) //显示时间与闹钟设置时间完全一样且闹钟\ { delay(5); sound=~sound; led=0; // delay(10); // delay(10); // delay(10); } else {led=1; sound=1;} }

void led1() interrupt 3 //LED1中断函数 50ms定时 { TL1=0xB0; TH1=0x3C; speak(); //num1++; num2++;

30

if(num2==20) //1s定时 {sec++; num2=0; judge(); } }

void main() //主函数 { lcd_init(); //LCD初始化函数 init(); //51初始化函数 while(1) { keyscan(); //调用扫描函数 minge=min; minshi=min/10; write_com(0x80+9); write_data(table1[minge]); delay(5); write_com(0x80+8); write_data(table1[minshi]); hourge=hour; hourshi=hour/10; write_com(0x80+6); write_data(table1[hourge]); delay(5); write_com(0x80+5); write_data(table1[hourshi]); write_com(0x80+7); write_data(':'); delay(5); secge=sec; //扩展秒表功能 secshi=sec/10; write_com(0x80+13); write_data(table1[secge]); delay(5); write_com(0x80+12); write_data(table1[secshi]); write_com(0x80+0x40+12);//拓展温度显示 write_data('1'); write_data('8');

31

write_com(0x80+0x40+14);//自定义字符“℃”显示 write_data(0x02);

write_com(0x80+0x40+15); write_data(0x03); write_com(0x80+14); write_data(0x04); write_data(0x05);

qi();

} }

附录3 元器件介绍 1.1602LCD液晶显示器介绍

管脚及其功能

1602LCD的基本参数及引脚功能:

1602LCD分为带背光和不带背光两种,基控制器大部分为HD44780,带背光的比不带背光的厚,是否带背光在应用中并无差别,两者尺寸差别如下图所示:

32

1602LCD尺寸图

1602LCD主要技术参数: 显示容量:16×2个字符 芯片工作电压:4.5—5.5V 工作电流:2.0mA(5.0V) 模块最佳工作电压:5.0V

字符尺寸:2.95×4.35(W×H)mm 引脚功能说明

1602LCD采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如下表所示: 引脚接口说明表 编号 符号 引脚说明 编号 符号 引脚说明 1 VSS 电源地 9 D2 数据 2 VDD 电源正极 10 D3 数据 3 VL 液晶显示偏压 11 D4 数据 4 RS 数据/命令选择 12 D5 数据 5 R/W 读/写选择 13 D6 数据 6 E 使能信号 14 D7 数据 7 D0 数据 15 BLA 背光源正极 8 D1 数据 16 BLK 背光源负极 第1脚:VSS为地电源。 第2脚:VDD接5V正电源。

第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。

第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。

第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。

第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。

第7~14脚:D0~D7为8位双向数据线。 第15脚:背光源正极。 第16脚:背光源负极。

1602液晶模块内部的控制器共有11条控制指令,如下表所示: 控制命令表 序号 指令 RS R/W D7 D6 D5 D4 D3 D2 D1 D0 1 清显示 0 0 0 0 0 0 0 0 0 1 2 光标返回 0 0 0 0 0 0 0 0 1 * 3 置输入模式 0 0 0 0 0 0 0 1 I/D S 4 显示开/关控制 0 0 0 0 0 0 1 D C B 5 光标或字符移位 0 0 0 0 0 1 S/C R/L * * 6 置功能 0 0 0 0 1 DL N F * * 33

7 置字符发生存贮器地址 0 0 0 1 字符发生存贮器地址 8 置数据存贮器地址 0 0 1 显示数据存贮器地址 9 读忙标志或地址 0 1 BF 计数器地址 10 写数到CGRAM或DDRAM) 1 0 要写的数据内容 11 从CGRAM或DDRAM读数 1 1 读出的数据内容 指令1:清显示,指令码01H,光标复位到地址00H位置。 指令2:光标复位,光标返回到地址00H。

指令3:光标和显示模式设置 I/D:光标移动方向,高电平右移,低电平左移 S:屏幕上所有文字是否左移或者右移。高电平表示有效,低电平则无效。 指令4:显示开关控制。 D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示 C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。

指令5:光标或显示移位 S/C:高电平时移动显示的文字,低电平时移动光标。

指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线 N:低电平时为单行显示,高电平时双行显示 F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。

指令7:字符发生器RAM地址设置。 指令8:DDRAM地址设置。

指令9:读忙信号和光标地址 BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。 指令10:写数据。

指令11:读数据。

基本操作时序表: 读状态 输入 RS=L,R/W=H,E=H 输出 D0—D7=状态字 RS=L,R/W=L,D0—D7=指令码,E=高写指令 输入 输出 无 脉冲 读数据 输入 RS=H,R/W=H,E=H 输出 D0—D7=数据 RS=H,R/W=L,D0—D7=数据,E=高脉写数据 输入 输出 无 冲 读写操作时序如图所示:

34

读操作时序

写操作时序

1602LCD的RAM地址映射及标准字库表 液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,下图是1602的内部显示地址。

1602LCD内部显示地址

35

例如第二行第一个字符的地址是40H,那么是否直接写入40H就可以将光标定位在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位D7恒定为高电平1所以实际写入的数据应该是01000000B(40H)+10000000B(80H)=11000000B(C0H)。

在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标是自动右移的,无需人工干预。每次输入指令前都要判断液晶模块是否处于忙的状态。

1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如图3-3-5所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。

字符代码与图形对应图

36

例如第二行第一个字符的地址是40H,那么是否直接写入40H就可以将光标定位在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位D7恒定为高电平1所以实际写入的数据应该是01000000B(40H)+10000000B(80H)=11000000B(C0H)。

在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标是自动右移的,无需人工干预。每次输入指令前都要判断液晶模块是否处于忙的状态。

1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如图3-3-5所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。

字符代码与图形对应图

36

本文来源:https://www.bwwdw.com/article/2ys3.html

Top