计数器设计.docx
《计数器设计.docx》由会员分享,可在线阅读,更多相关《计数器设计.docx(27页珍藏版)》请在冰豆网上搜索。
计数器设计
专业项目设计
&综合项目设计
题目警报计数器的设计与实现
学院计算机学院
专业计算机科学与技术
班别10级(6)班
学号
姓名
指导老师
2014年1月10日
目录
前言2
一、课程设计目的3
二、运行环境3
三、需求分析3
四、详细设计3
1、AT89C52介绍3
2、AT89C52系列单片机外引脚功能4
3、仿真电路图5
4、警报电路设计5
5、矩阵键盘设计6
6、主要功能函数代码6
五、各模块详细功能8
1.计数功能8
2.设置计数初值功能9
3.设置警报9
六、心得与体会10
七、参考文献10
八、附录:
(源代码)11
前言
摘要:
单片机在电子产品中的应用越来越广泛,其具有使用方便、价格低廉等优势,其中计数器在单片机电子产品中得到广泛的应用,例如电子时钟,秒表,各类检测器等。
本设计是基于AT89C52的一个警报计数器,包括74HC245,7445,7SEG-MPX8-CC,能够实现警报,计数,设置的多功能计数器。
所有功能能够通过按钮实现,符合人们实际的生活所需,具有整体性好、人性化强、可靠性高等优点
关键词:
计数器AT89C524X4矩阵键盘7SEG-MPX8-CC
一、课程设计目的
1.掌握MCS-51系列单片机的基本结构和原理。
2.学会用C语言对单片机的内部和外围器件的编程。
3.掌握计数器中断处理程序的编程。
4.掌握ProtuesISIS仿真环境。
二、运行环境
Proteus7Professional,KeiluVision4,MicrosoftVisualStudio2010
三、需求分析
基于AT89C52芯片开发功能性需求如下:
1.设计一个计数器,使其能够进行顺数,倒数计数。
2.能够自由设置计数初值。
3.计数器具有警报功能。
4.能够自由设置警报值
四、详细设计
系统主要由3部分组成,分别是7SEG-MPX8-CC、74HC245、7445组成的显示时间模块、4X4矩阵输入模块、蜂鸣警报器模块。
用AT89C52芯片作为核心主控芯片。
1、AT89C52介绍
AT89C52是一个低电压,高性能CMOS 8位单片机,片内含8k bytes的可反复擦写的Flash只读程序存储器和256 bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位中央处理器和Flash存储单元,功能强大的AT89C52单片机可为您提供许多较复杂系统控制应用场合。
AT89C52有40个引脚,32个外部双向输入/输出(I/O)端口,同时内含2个外中断口,3个16位可编程定时计数器,2个全双工串行通信口,2 个读写口线,AT89C52可以按照常规方法进行编程,也可以在线编程。
其将通用的微处理器和Flash存储器结合在一起,特别是可反复擦写的Flash存储器可有效地降低开发成本。
2、AT89C52系列单片机外引脚功能
AT89C52有PDIP、PQFP/TQFP及PLCC等三种封装形式,以适应不同产品的需求。
主要功能特性:
兼容MCS51指令系统·8k可反复擦写(>1000次)FlashROM
·32个双向I/O口·256x8bit内部RAM
·3个16位可编程定时/计数器中断·时钟频率0-24MHz
·2个串行中断·可编程UART串行通道
·2个外部中断源·共6个中断源
·2个读写中断口线·3级加密位
·低功耗空闲和掉电模式·软件设置睡眠和唤醒功能
3、仿真电路图
定义P0为段输出口,定义P2为位输出口,定义P1为矩阵键盘接口,定义P3为警报器接口
4、警报电路设计
因为单片机的IO口驱动能力不够让蜂鸣器发出声音,所以我们通过三极管放大驱动电流,从而可以让蜂鸣器发出声音,你要是输出低电平,三极管导通,集电极电流通过蜂鸣器让蜂鸣器发出声音,当输出高电平时,三极管截止,没有电流流过蜂鸣器,所以就不会发出声音。
5、矩阵键盘设计
P1口接矩阵键盘,其中P1.0~P1.3接行线,P1.4~P1.7接列线。
本设计使用的方法就是通过给单片机的端口赋值两次,最后得出所按键的值。
例如:
1.我们给P1口赋值0x0f,即00001111,假设7键按下了,则这时P1口的实际值为00000001;
2.我们给P1口再赋值0xf0,即11110000,如果0键按下了,则这时P1口的实际值为00010000;
3.我们把两次P1口的实际值相加得00010001,即0x11。
由此我们便得到了按下7键时所对应的数值0x11,以此类推可得出其他15个按键对应的数值,8键为00000001|00100000=0x21有了这种对应关系,矩阵键盘编程问题也就解决了,
6、主要功能函数代码
矩阵键盘扫描:
ucharbutton_scan(void)/**扫描按键函数-2步判别扫描法**/
{
ucharreadkey,rereadkey;
ucharx_temp,y_temp;
BUTTON_PORT=0x0f;
x_temp=BUTTON_PORT&0x0f;
if(x_temp==0x0f)return(0xff);/*无按键,退出*/
BUTTON_PORT=0xf0;
y_temp=BUTTON_PORT&0xf0;
readkey=x_temp|y_temp;
time(8);/*延时10ms后再测按键*/
BUTTON_PORT=0x0f;
x_temp=BUTTON_PORT&0x0f;
if(x_temp==0x0f)return(0xff);/*无按键,退出*/
BUTTON_PORT=0xf0;
y_temp=BUTTON_PORT&0xf0;
rereadkey=x_temp+y_temp;
if(readkey==rereadkey){/*2次一致*/
return(~rereadkey);
}
return(0xff);
}
按键处理程序:
voidbutton_process(void)/*键值处理程序*/
{
switch(button_value)/*根据中断源分支*/
{
/*按第1行键*/
case0x11:
dt=7;
i++;
printf("Key(R1,C1)ispressed\n");
/*输入数字7*/
break;
case0x21:
dt=8;
i++;
printf("Key(R1,C2)ispressed\n");
/*输入数字8*/
break;
…………………………………………(省略若干按键功能详述)
case0x88:
flag=1;
if(bt==1)//警报设置赋值
{
bgg=g1*10+g2;
bhh=h1*10+h2;
bmm=m1*10+m2;
bss=s1*10+s2;
gg=0;
hh=0;
mm=0;
ss=0;
}
if(bt==0)//计数设置赋值
{
gg=g1*10+g2;
hh=h1*10+h2;
mm=m1*10+m2;
ss=s1*10+s2;
}
printf("Key(R4,C4)ispressed\n");
/*确定按钮*/
break;
default:
break;
}
if(flag==-1)
{
if(i==1)g1=dt;
if(i==2)g2=dt;
if(i==3)h1=dt;
if(i==4)h2=dt;
if(i==6)m1=dt;
if(i==7)m2=dt;
if(i==8)s1=dt;
if(i==9)s2=dt;
}
}
五、各模块详细功能
1.计数功能
顺数,从0计数到10
倒数,从15倒数至5,在15时先按下顺数/倒数键,再按启动/暂停键,进行倒数,到5时再按启动/暂停键
2.设置计数初值功能
按下设置键,输入12334556,然后按下确定键,再按启动进行计算(若按设置键前是顺数计数则顺数计数)
3.设置警报
按下设置警报键,设置警报值12345678,然后按下确定键,再按启动进行计算
等到到达警报值,蜂鸣器连续响7下以示警报,然后继续计数。
若不进行设置初始警报值为学号后四位6097
六、心得与体会
本次的专项设计不仅仅是单片机知识的应用,其中还包含了很多其他科目的知识应用其中,例如电工学,C语言设计等,使得项目变得更具综合性,使我的综合专业知识得到了一定的提高。
在本次的设计中,最难的部分就是蜂鸣器的电路设计,由于自己的电工学知识略显不足,三极管的不正确运用使得蜂鸣器的驱动电路无法正常运行,为此还数次请教指导老师,在老师的帮助下,自己对三极管的应用有了更深的了解,最终还是完成了该功能。
其次就是矩阵电路的设计和编程,矩阵键盘却没有自己想的那么灵敏,大概是自己使用行列法而非状态法的原因吧,使得其效率较低,但由于自己的知识有限,只能暂时挑选较为简单的行列法。
最后的问题就是I/O口的运用问题,第一次出来的电路图I/O口浪费十分严重,以至于后面的扩展功能无法加入,但经过老师指导和上网搜集资料,改为使用段位显示的7SEG-MPX8-CC,配合老师推荐的74HC245,7455,为此省下了不少的I/O口来扩展功能。
在这次专项设计中,不仅学习到了不少的专业知识,更重要的是锻炼了自己的自学能力,看似不能完成的任务,其实可以通过自己力所能及的能力一点一点的做起来。
倘若我们都不去走第一步,那么我们未开始就注定失败,倘若一步一脚印的走来,我们可能虽不是最成功的,但我们终究有收获的,最后感谢老师的悉心指导。
七、参考文献
[1]谭浩强.C程序设计.北京:
清华大学出版社,2005.
[2]张齐.单片机原理与嵌入式系统设计.北京:
电子工业出版社,2011
[3]秦曾煌.电工学.北京:
高等教育出版社,2010
[4]陈赜.ARM嵌入式技术原理与应用.北京:
北京航空航天大学出版社,2002
八、附录:
(源代码)
#include"common.h"
#include
#defineTRUE1
#definedataPortP0/*定义P0为段输出口*/
#defineledConPortP2/*定义P2为位输出口*/
#defineBUTTON_PORTP1/*按键接在BUTTON_PORT口*/
//gg……ss分别为显示管从左到右的两位数,g1……s2分别是他们的高低四位
intgg=0,hh=0,mm=0,ss=0,g1=0,g2=0,h1=0,h2=0,m2=0,m1=0,s1=0,s2=0,dt=0;
intbgg=0,bhh=0,bmm=60,bss=97;//警报初值
intpacket=0,start=0,bt=0,flag=-1;//paket,start,flag分别为顺数倒数,清零启动,设置警报,设置计数的标志
ucharbutton_value=0xff;//存放键值
ucharbutton_scan(void);//扫描按键函数-2步判别扫描法
voidbutton_process(void);//键值处理程序
unsignedchari=0;//显示计数变量
unsignedcharcodech[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//LED灯0~9译码
unsignedcharcounter;
sbitbell_set=P3^0;//警报设置按钮
sbitbell=P3^1;//蜂鸣器
voidtime(unsignedintucMs);//延时单位:
ms
voiddisplay();
voiddisplay2();
voidinit();
voidbell_scan();//警报设置函数
voidmain(void)
{
bell=1;
initUart();//初始化串口
TMOD=0x10;//设置定时器1为工作方式1
TH0=-50000>>8;TL0=-50000%256;
TH1=-10000>>8;TL1=-10000%256;//定时器1每10000计数脉冲发生1次中断,12MHz晶振,定时时间10000us
TCON=0x55;
IE=0x8f;//打开定时器中断
TR0=0;
button_value=0xff;
bell_scan();//警报按键扫描
while(TRUE)
{
bell_scan();
if(button_value==0x48)//启动/暂停切换
{
if(TR0==0)
{
TR0=1;
}
elseTR0=0;
}
if(button_value==0x28)//顺数、倒数切换
{
TR0=0;
if(packet==0)
{
packet=1;
}
elsepacket=0;
}
if(button_value==0x81)//清零
{
TR0=0;
init();
while
(1)
{
button_process();//键值处理程序
display2();
if(start==1)break;
}
start=0;
gg=g1*10+g2;
hh=h1*10+h2;
mm=m1*10+m2;
ss=s1*10+s2;
button_value=0xff;//重置键值
}
if(button_value==0x84)//如果按下设置键
{
init();
bt=0;
while
(1)
{
button_process();//键值处理程序
display2();
if(flag==0||flag==1)break;
}
dt=0;
flag=-1;
i=0;
button_value=0xff;//重置键值
}
display();
}
}
/*******************************************************************************************/
voidtimer1int3(void)interrupt3
{
TH1=0xd8;TL1=0xf0;//定时器1每10000计数脉冲发生1次中断,12MHz晶振,定时时间10000us
button_value=button_scan();
}
voidtimer1int0(void)interrupt1
{
TH0=0x08;TL0=0x88;//定时器0每10000计数脉冲发生1次中断,12MHz晶振,定时时间10000us
if(gg==bgg&hh==bhh&mm==bmm&ss==bss&&bt==0)
{
inti;
TR0=0;
for(i=0;i<8;i++)
{
bell=0;
time(500);
bell=1;
time(500);
}
TR0=1;
}
if(packet==0)//顺数计数
{
ss++;
if(ss>=100)
{
ss=0;
mm++;
}
if(mm>=100)
{
mm=0;
hh++;
}
if(hh>=100)
{
hh=0;
gg++;
}
if(gg>=100)
{
gg=0;
}
}
if(packet==1)//倒数计数
{
ss--;
if(ss<0)
{
ss=100;
mm--;
}
if(mm<0)
{
mm=99;
hh--;
}
if(hh<0)
{
hh=99;
gg--;
}
if(gg<0)
{
gg=99;
}
}
}
voidbell_scan()//警报设置函数
{
if(bell_set==0)
{
init();
bt=1;
while
(1)
{
button_process();//键值处理程序
display2();
if(flag==0||flag==1)break;
}
dt=0;
flag=-1;
i=0;
button_value=0xff;//重置键值
}
}
voidbutton_process(void)/*键值处理程序*/
{
switch(button_value)/*根据中断源分支*/
{
/*按第1行键*/
case0x11:
dt=7;
i++;
printf("Key(R1,C1)ispressed\n");
/*输入数字7*/
break;
case0x21:
dt=8;
i++;
printf("Key(R1,C2)ispressed\n");
/*输入数字8*/
break;
case0x41:
dt=9;
i++;
printf("Key(R1,C3)ispressed\n");
/*输入数字9*/
break;
case0x81:
printf("Key(R1,C4)ispressed\n");
/*清零按钮*/
break;
/*按第2行键*/
case0x12:
dt=4;
i++;
printf("Key(R2,C1)ispressed\n");
/*输入数字4*/
break;
case0x22:
dt=5;
i++;
printf("Key(R2,C2)ispressed\n");
/*输入数字5*/
break;
case0x42:
dt=6;
i++;
printf("Key(R2,C3)ispressed\n");
/*输入数字6*/
break;
case0x82:
flag=0;
bt=0;
printf("Key(R2,C4)ispressed\n");
/*取消按钮*/
break;
/*按第3行键*/
case0x14:
dt=1;
i++;
printf("Key(R3,C1)ispressed\n");
/*输入数字1*/
break;
case0x24:
dt=2;
i++;
printf("Key(R3,C2)ispressed\n");
/*输入数字2*/
break;
case0x44:
dt=3;
i++;
printf("Key(R3,C3)ispressed\n");
/*输入数字3*/
break;
case0x84:
printf("Key(R3,C4)ispressed\n");
/*设置按钮*/
break;
/*按第4行键*/
case0x18:
dt=0;
i++;
printf("Key(R4,C1)ispressed\n");
/*输入数字0*/
break;
case0x28:
printf("Key(R4,C2)ispressed\n");
/*顺数倒数切换按钮*/
break;
case0x48:
start=1;
printf("Key(R4,C3)ispressed\n");
/*启动暂停切换*/
break;
case0x88:
flag=1;
if(bt==1)//警报设置赋值
{
bgg=g1*10+g2;
bhh=h1*10+h2;
bmm=m1*10+m2;
bss=s1*10+s2;
gg=0;
hh=0;
mm=0;
ss=0;
}
if(bt==0)//计数设置赋值
{
gg=g1*10+g2;
hh=h1*10+h2;
mm=m1*10+m2;
ss=s1*10+s2;
}
printf("Key(R4,C4)ispressed\n");
/*确定按钮*/
break;
default:
break;
}
if(flag==-1)
{
if(i==1)g1=dt;
if(i==2)g2=dt;
if(i==3)h1=dt;
if(i==4)h2=dt;
if(i==6)m1=dt;
if(i==7)m2=dt;
if(i==8)s1=dt;
if(i==9)s2=