摘 要
随着现代工业的飞速发展,整个世界对能源的需求越来越大,而我们知道世界能源的总量是一定的,针对能源的日益匮乏,节能产品的开发成功迅速成为人们的首选。此次本组做的工业节能控制器就是基于节能、节支的理念,利用芯片STC89C52和8255设计的一种节能装置。其核心实际是一台基于单片机的数字电子钟,设有四位LED数码管显示,具有两个时间控制点,可通过按键来实现电器的工作时间的可调性。同时其体积小、成本低,不仅适合嵌入到各种能耗大的工控设备中进行控制,也适合居民的家用电器节能控制。体现了实用价值高、应用前景广泛等特点。
关键词:节能节支;芯片STC89C52;8255;可调性;应用前景。
工业节能时控器
设计要求
1.由单片机的数字电子计数器,由4位LED数码管显示;
2.设定2个时间控制点;
3.通过对继电器的控制来实现电路的通断;
4.能够通过键盘的输入来调整开关时间。
1 方案论证与对比 1.1 方案一
该方案的系统由单片机、数码管、键盘扫描和继电器4部分组成。单片机是整个系统的核心,其定时器的设置是实现所有功能的关键。整个系统的运行方式如:产生精确时钟及定时,LED数码管显示器输出扫描显示,同时控制继电器的工作与停止。一旦有中断响应就立刻进行键盘扫描,通过按键重置继电器的工作时段。中断返回后即按照设定的模式进入工作状态。框图如图1所示:
SHAPE \* MERGEFORMAT
图 1 方案一系统方框图
1.2 方案二
此方案的设计思路与方案一有着大同小异的区别,在方案一的基础上添加了一个串行口控制模块。该模块也由单片机STC89C52来控制,通过PC机来实现单片机与PC机的串行口通信,在键盘上扫描,由4位LED动态显示出来。具体运行模式为:由单片机产生精确的时钟和定时,驱动继电器的工作,按键按下后,由PC机通过串行口通信实现数据的写入,再通过键盘扫描输出动态的LED显示。从而也能使得继电器的工作时段可调,达到节能的效果。
SHAPE \* MERGEFORMAT
图2 方案二系统方框图
1.3方案对比与选择
以上两个方案均可实现节能时控器要求的功能,所做出成品的体积小,控制都计较精确。但是相比之下,方案二在实现所要求的功能的前提下所用的硬件资源更多,这会导致CPU的运行速度相对慢点,同时所需要的元器件也将增多;除此之外,通过PC机与单片机进行串行口通信来实现数据的写入和键盘扫描该步控制比较复杂,不易操作。
显然,在可以实现所有功能的条件下,方案一的设计思路比较简单,操作容易。故本组采用方案一来进行工业节能时控器的设计。
2 各模块电路的设计 2.1 继电器电路的设计
继电器是一种电子控制器件,它具有控制系统和被控制系统,通常应用于自动控制电路,它实际上用较小的电流去控制较大电流的一种“自动开关”。故在电路中起着自动调节、安全保护、转换电路等作用。
根据设计要求要通过对继电器的控制来实现电路的通断。这里由一个单刀双掷开关来实现电路的通断,同时通过芯片STC89C52的P1.2口来控制继电器的工作与否,而且在继电器的电路中设置一个发光二极管来直观地显示出继电器的工作状态。整个继电器模块的电路图如下图3所示:
图 3 放大电路原路图
如上图所示,继电器的一端接地,另一端由一个三极管接到单片机的P12引脚。当单片机的P12引脚输出高电平时,三极管截止,此时继电器不工作;当单片机的P12引脚输出低电平时,三极管导通,继电器的衔铁吸合,使得开关打向R13端。测试时,先将S6开关接到P1-COMVCC,下载继电器程序运行,按一下复位键,此时继电器工作,LED2灯亮。
2.2 4位LED动态显示模块电路的设计
在该电路的设计中需要用到4个数码管,每个数码管的8段有芯片8255的PB口控制亮灭,每个数码管的公共脚分别由8255的PA2-PA5经三极管扩流后进行控制,原理图如图4所示:
图 4 整形电路原理图
数码管的笔画顺序,本组用到的数码管是共阳极的,当在公共引脚接上电源正极,笔画脚通过一个220欧姆的电阻接负极,对应的笔画就会点亮。显示的数字0~9的8位二进制码如表1所示:
表 1 数码管显示数值所对应的段码表
显示码
数字
十六进制
二进制
g
c
dp
d
e
b
f
a
0
0XA0
1
0
1
0
0
0
0
0
1
0XBB
1
0
1
1
1
0
1
1
2
0X62
0
1
1
0
0
0
1
0
3
0X2A
0
0
1
0
1
0
1
0
4
0X39
0
0
1
1
1
0
0
1
5
0X2C
0
0
1
0
1
1
0
0
6
0X24
0
0
1
0
0
1
0
0
7
0XBA
1
0
1
1
1
0
1
0
8
0X20
0
0
1
0
0
0
0
0
9
0X28
0
0
1
0
1
0
0
0
注:‘1’对应的笔画熄灭,‘0’对应的笔画点亮。注:‘1’对应的笔画熄灭,‘0’对应的笔画点亮。
要在某位数码管上显示一个数字,首先把待显示的数字的显示码送给8255的PB口,接着选中要显示的位。例如:要在开发板中最右边的数码管上显示一个‘0’,则需要先把‘0’的显示码0XC0送至PB口,接着给PA5赋低电平,随后让单片机保持这个值不变,下载时钟程序即可让数码管显示规定的数字。由于我们需要让四位数码管同时动态显示,还应考虑到显示时间的长短,这时用一个延时程序来控制即可。
2.3 键盘扫描模块电路的设计
在单片机系统中键盘中按钮数量较多时,为了减少I/O口的占用,常常将按钮排列成矩阵形式。而在本设计中为了通过键盘来调整开关时间,时间要在4位数码管上显示出来,故我们用4个按键分别来改变数码管4位的数值,电路如图5所示:
图 5 键盘扫描电路
判断键盘中有无键盘按下的方法:先将PA0拉高,然后扫描PC各行的电平状态,若哪一行出现高电平,即可知道该行的按键被按下。当按键每被按下一次,所对应的数码管的数值就会加1,超过‘9’时,又回到‘0’。从而很容易地实现了时间的可调。
2.4 系统复位电路设计
单片机的复位电路如图6示:
图 6 复位电路图
RST:复位输入。晶振工作时,RST脚持续2个机器周期高电平将使单片机复位。看门狗计时完成后,RST脚输出96个晶振周期的高电平。特殊寄存器AUXR上的DISRT0位可以使此功能无效。DISRT0默认状态下,复位高电平有效。
2.5 系统晶振电路设计
本系统采用的是12MHZ的晶振,其电路图如图7所示:
图 7 晶振电路图
XTAL1:振荡器反相放大器和内部时钟发生电路的输入端。
XTAL2:振荡器反相放大器的输出端。
2.6 STC89C52芯片与8255芯片的介绍
STC89C52芯片如图8所示:
图 8 STC89C52芯片图
STC89C52是低功耗、高性能的CMOS8位微控制器。8字节的flash,256字节的RAM,32位的I/O口线,看门狗定时器,2个数据指针,3个16位定时器/计数器。全双工串行口,片内晶振及时钟电路,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,内容被保存,振荡器被冻结。
8255芯片引脚图如图9所示:
图 9 8255芯片引脚图
8255西片是一种典型的课编程通用并行接口芯片,用来扩展单片机的端口,它具有3个8位的并行口,有三位工作方式,可作为单片与各种外部设备连接的接口电路。
CS:片选信号线,当该引脚为低电平时,8255被选中,允许8255与CPU通讯。
RESET:复位输入线,当该引脚为高电平时,内部寄存器被清除,所有I/O口均被置成输入方式。
A0、A1:地址输入线。
当A0A1=00时,PA口被选中;
当A0A1=01时,PB口被选中;
当A0A1=10时,PC口被选中;
当A0A1=11时,控制寄存器被选中。
2.7 节能时控器总的电路图
节能时控器整个系统电路图如图10所示:
图 10 系统总电路图
3 系统设计的流程图
SHAPE \* MERGEFORMAT
图 11 系统流程图
4 系统软件的初始化设计 4.1 8255芯片的初始化
随着大规模集成电路的发展,接口电路也被集成在单一的芯片上,许多芯片可以通过编程方法设定工作方式,这种接口芯片被称为可编程I/O接口芯片,8255芯片是最常用的一种。使用8255芯片前,必须对其各个端口地址进行设置,不然无法进行与CPU进行通信。由于本设计中需要通过8255的PA、PB、PC口分别来控制数码管的位选信号、段选信号、键盘的输入,同时还需要对其方式控制字进行设置。具体如下:
#define a8255_PA XBYTE[0xD1FF] /*PA口地址*/
#define a8255_PB XBYTE[0xD2FF] /*PB口地址*/
#define a8255_PC XBYTE[0xD5FF] /*PC口地址*/
#define a8255_CON XBYTE[0xD7FF] /*控制字地址*/
4.2 定时器T0的初始化
源于该设计的时间显示要非常精确,可以使系统的时序是用定时单位来描述的,在此选用定时器0,而单片机内部的时钟频率为12MHZ,那么它的一个时钟周期为1/12us,而一个机器周期是一个时钟周期的12倍,即一个机器周期的时间为1us.
根据设计要求,我们需要50ms作为一个单位时间,选用定时器T0,对其的初始化过程如下:
⑴ 选择工作方式1:16位定时器/计数器方式,最多可以计到2的16次方,即65536.
⑵ 工作方式寄存器TMOD的设置:TMOD=0X01.
⑶ 50ms的精确定时:TH0=0x3C,TL0=0Xb0.
定时器T0具体初始化程序如下:
void Timer0_Init(void) //0.5mS
{ TMOD |= 0x01;
TH0 = 0x3C;
TL0 = 0xB0;
ET0 = 1;
}
void GInt_Init(void)
{
EA = 1;
EX0 = 1;
IT0 = 1;
}
4.3 1S中断程序
根据设计要求,要求实现时间倒计时,为此我们将1s的中断程序放在外部中断0内,当外部中断0响应时,完成1s计时,改变显示的时间。
详细的中断程序如下:
void ISR_Timer0(void) interrupt 1
{
Timer_Count++;
if(Timer_Count == 20) //1s
{
Timer_Count = 0;
Flag_Second = 1; //设置1s标志
}
Timer0_Init();
}
4.4 数码管显示数值程序
数码管显示函数程序采用的是ASCII代码,具体程序如下:
unsigned char const dis_table[16]={
0xA0, /*0*/
0xBB, /*1*/
0x62, /*2*/
0x2A, /*3 */
0x39, /*4*/
0x2C, /*5 */
0x24, /*6*/
0xBA, /*7*/
0x20, /*8*/
0x28, /*9 */
0x30, /*A*/
0x25, /*B*/
0xE4, /*C*/
0x23, /*D*/
0x64, /*E*/
0x74, /*F */
};
void display(unsigned char place, unsigned char num)
{
unsigned char i = 0,display_num = 0;
a8255_CON=0x89;
a8255_PB=0xff;
a8255_PA=0xff;
a8255_PA= ~(0x1
if(num >= 0x30 && num
a8255_PB = dis_table[num - 0x30];
else if(num >= 0x41 && num
a8255_PB = dis_table[num - 0x37];
else
a8255_PB = 0xff;
delay(2);
}
4.5 延时函数程序
数码管动态显示必须要求每一个数值显示有所延时,可用下面的延时程序来实现
延时程序:
void delay05s(unsigned int Num)
{
unsigned char i, j, k;
unsigned int count = 0;
for(count = Num; count > 0; count--)
{
for( i = 5; i > 0 ; i--)
{
for( j = 25; j > 0; j--)
{
for( k = 2; k > 0; k--);
}
}
}
}
4.6 键盘扫描函数程序
进行键盘扫描,实现数码管数值的可调。程序如下:
unsigned char Scan_Keyboard(void)
{
unsigned char i = 0,j = 0,PC_data = 0;
unsigned char test_x=0,test_y=0;
a8255_CON=0x89;
a8255_PB=0xff;
a8255_PA=0xff;
PC_data=a8255_PC;
for(j = 0;j
{
if((PC_data & (1
{
delay(10);
if((PC_data & (1
{
for(i = 0;i
{
a8255_PA=1
PC_data=a8255_PC;
if((PC_data & (1
{
test_x = i;
test_y = j;
flag_button = 1;
break;
}
}
}
}
}
a8255_PA=0xff;
while( a8255_PC & 0xf);
if(test_x == 0 && test_y == 3)
return('+');
else if(test_x == 1 && test_y == 3)
return('-');
else if(test_x == 2 && test_y == 3)
return('=');
else if(test_x == 3 && test_y == 3)
return('0');
else if(test_x == 0 && test_y == 0)
return('*');
else if(test_x == 1 && test_y == 0)
return('/');
}
5 系统功能测试与整体调试 5.1 继电器工作与数码管同步显示
此模块的程序见附录1.1,编译成功生成hex文件后下载,可观察到继电器的停止状态和工作状态与数码管显示的时间同步。
5.2 数码管上的数值可调
此模块的程序见附录1.2,编译成功生成hex文件后下载,可观察到数码管的时间显示有两个时间段,这两个时间段构成一个周期。这个周期段是数值开始从‘1500’减为‘0000’,在显示‘0000’那刻末数值立刻变到‘0200’,接着又从‘0200’减到‘0000’。只要有中断响应,数码管的数值就可由四个按键来分别改变。
5.3 整个系统的调试
整体调试的程序见附录1.3,下载后系统按初始化的程序在执行,继电器和数码管正常工作,一旦有中断响应,通过扫描键盘上按键的按下来调整继电器的开关时间,使得继电器的开关时间段发生变化。若复位键按下,则系统按初始化的程序运行。因此很好地完成了此次单片机课程设计所规定的要求。
6详细仪器清单 表2 仪器清单
仪器名称
数量
STC89C52芯片
1
8255芯片
1
1K电阻
21
型号为9015的三极管
5
30pf电容
2
极性电容
1
8段共阳极数码管
5
继电器
1
开关
2
石英晶振
1
矩形按键
6
7总结及致谢
单片机课程设计历时十天,在整整十天的日子里,可以说得是苦多于甜,但是可以学到很多很多的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。以前在上课的时候,老师经常强调在做设计的时候,一定要事先把设计原理方框图画出来,但是我开始总觉得这样做没必要,很浪费时间。但是,这次课程设计完全改变了我以前的那种错误的认识,以前我接触的那些程序都是很短、比较基础的,但是在课程设计中碰到的那些需要很多小模块才能完成的任务,画原理图是很有必要的。因为通过原理图,在做设计的过程中,我们每一步要做什么,每一步要完成什么任务都有一个很清楚的思路,而且在功能测试的过程中也有利于查错。
通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,这毕竟第一次做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固。这次课程设计终于顺利完成了,在设计中遇到了很多问题,,我了解到自己在设计原理图方面还有很多不足,以后我会更加努力。
在这次设计中我们遇到过很多问题,每次询问同学和老师时他们总会耐心地给我们讲述,在此衷心的感谢帮助过我们的所有同学,以及要特别感谢老师、岳老师、方老师和谭老师的耐心指导。没有你们的教导和解答,我们不可能这么容易完成这次的课程设计。
参考文献 [1] 朱定华. 戴汝平. 单片微机原理与应用(M). 北京: 清华大学出版社,2003
[2] 张鑫. 单片机原理及应用(M). 北京: 电子工业出版社,2005.8
[3] 楼然苗. 李光飞. 单片机课程设计指导(M). 北京: 北京航空航天大学出版社,2007.7
[4] 陈家俊. 郑滔. 程序设计教程—用C++语言编程(M). 北京: 机械工业出版社,2004.8
附录1: 附录1.1节能时控器主程序 #include "reg51.h"
#include "math.h"
#define k_dtzt 1
#define k_dkzt 2
#define k_zcdt 3
//外部函数申明
extern void display(unsigned char place,unsigned char num); //数码管显示函数
extern unsigned char Scan_Keyboard(void);
sbit CS=P1^2;
extern void GInt_Init(void);
extern unsigned char flag_button; //在keyboard.c中定义并被赋值
extern void Timer0_Init(void);
unsigned char Display_Array[6]; //显示用数组
unsigned char Timer_Count = 0;
unsigned char Flag_Second = 0;
void main(void)
{
unsigned char i = 0;
unsigned char temp = 0; //零时变量
unsigned long k_dqzt= 0;
unsigned char times = 0,light1=0; //循环次数
k_dqzt = k_dtzt;
for(i = 0; i
Display_Array[i] = '0';
while(1)
{
display(1,Display_Array[0]);
display(2,Display_Array[1]);
display(3,Display_Array[2]);
display(4,Display_Array[3]);
display(5,Display_Array[4]);
display(6,Display_Array[5]); //显示部分
temp = Scan_Keyboard(); //获得键值
if((temp == '+' || temp == '-' )&& flag_button == 1) //有按键,且按键的内容为0到9 时
{
flag_button = 0;
if(temp == '+' )
{
Display_Array[5]++;
if(Display_Array[5]>'9')
{
Display_Array[5]='0' ;
Display_Array[4]++;
}
}
else if(temp == '-' )
{
Display_Array[5]--;
if(Display_Array[5]
{
Display_Array[5]='9';
Display_Array[4]--;
}
}
Display_Array[5]= Display_Array[5];
Display_Array[4]= Display_Array[4];
}
else if (temp=='='&&flag_button == 1)
{
flag_button = 0;
CS = 0;
k_dqzt = k_dtzt;
Timer0_Init(); //定时器0的初始化, 50mS的定时
GInt_Init(); //开中断
TR0 = 1;
}
else if(Flag_Second == 1 && k_dqzt == k_dtzt)
{
Flag_Second = 0;
Display_Array[5]--;
if(Display_Array[5]
{
Display_Array[5]='9';
Display_Array[4]--;
}
if(Display_Array[5]=='0'&&Display_Array[4]=='1')
{
CS = 1;
k_dqzt=k_dkzt;
}
}
else if (Flag_Second == 1 && k_dqzt == k_dkzt)
{
Flag_Second = 0;
Display_Array[5]--;
if(Display_Array[5]
{
Display_Array[5]='9';
Display_Array[4]--;
}
if(Display_Array[5]=='5'&&Display_Array[4]=='0')
{
CS = 0;
k_dqzt=k_zcdt;
}
}
else if(Flag_Second == 1 && k_dqzt == k_zcdt)
{Flag_Second = 0;
Display_Array[5]--;
if(Display_Array[5]=='0'&&Display_Array[4]=='0')
{
CS = 1;
TR0 = 0;
}
}
} }
void ISR_Timer0(void) interrupt 1
{
Timer_Count++;
if(Timer_Count == 20) //1S
{
Timer_Count = 0;
Flag_Second = 1; //设置1s标志
}
Timer0_Init(); }
摘 要
随着现代工业的飞速发展,整个世界对能源的需求越来越大,而我们知道世界能源的总量是一定的,针对能源的日益匮乏,节能产品的开发成功迅速成为人们的首选。此次本组做的工业节能控制器就是基于节能、节支的理念,利用芯片STC89C52和8255设计的一种节能装置。其核心实际是一台基于单片机的数字电子钟,设有四位LED数码管显示,具有两个时间控制点,可通过按键来实现电器的工作时间的可调性。同时其体积小、成本低,不仅适合嵌入到各种能耗大的工控设备中进行控制,也适合居民的家用电器节能控制。体现了实用价值高、应用前景广泛等特点。
关键词:节能节支;芯片STC89C52;8255;可调性;应用前景。
工业节能时控器
设计要求
1.由单片机的数字电子计数器,由4位LED数码管显示;
2.设定2个时间控制点;
3.通过对继电器的控制来实现电路的通断;
4.能够通过键盘的输入来调整开关时间。
1 方案论证与对比 1.1 方案一
该方案的系统由单片机、数码管、键盘扫描和继电器4部分组成。单片机是整个系统的核心,其定时器的设置是实现所有功能的关键。整个系统的运行方式如:产生精确时钟及定时,LED数码管显示器输出扫描显示,同时控制继电器的工作与停止。一旦有中断响应就立刻进行键盘扫描,通过按键重置继电器的工作时段。中断返回后即按照设定的模式进入工作状态。框图如图1所示:
SHAPE \* MERGEFORMAT
图 1 方案一系统方框图
1.2 方案二
此方案的设计思路与方案一有着大同小异的区别,在方案一的基础上添加了一个串行口控制模块。该模块也由单片机STC89C52来控制,通过PC机来实现单片机与PC机的串行口通信,在键盘上扫描,由4位LED动态显示出来。具体运行模式为:由单片机产生精确的时钟和定时,驱动继电器的工作,按键按下后,由PC机通过串行口通信实现数据的写入,再通过键盘扫描输出动态的LED显示。从而也能使得继电器的工作时段可调,达到节能的效果。
SHAPE \* MERGEFORMAT
图2 方案二系统方框图
1.3方案对比与选择
以上两个方案均可实现节能时控器要求的功能,所做出成品的体积小,控制都计较精确。但是相比之下,方案二在实现所要求的功能的前提下所用的硬件资源更多,这会导致CPU的运行速度相对慢点,同时所需要的元器件也将增多;除此之外,通过PC机与单片机进行串行口通信来实现数据的写入和键盘扫描该步控制比较复杂,不易操作。
显然,在可以实现所有功能的条件下,方案一的设计思路比较简单,操作容易。故本组采用方案一来进行工业节能时控器的设计。
2 各模块电路的设计 2.1 继电器电路的设计
继电器是一种电子控制器件,它具有控制系统和被控制系统,通常应用于自动控制电路,它实际上用较小的电流去控制较大电流的一种“自动开关”。故在电路中起着自动调节、安全保护、转换电路等作用。
根据设计要求要通过对继电器的控制来实现电路的通断。这里由一个单刀双掷开关来实现电路的通断,同时通过芯片STC89C52的P1.2口来控制继电器的工作与否,而且在继电器的电路中设置一个发光二极管来直观地显示出继电器的工作状态。整个继电器模块的电路图如下图3所示:
图 3 放大电路原路图
如上图所示,继电器的一端接地,另一端由一个三极管接到单片机的P12引脚。当单片机的P12引脚输出高电平时,三极管截止,此时继电器不工作;当单片机的P12引脚输出低电平时,三极管导通,继电器的衔铁吸合,使得开关打向R13端。测试时,先将S6开关接到P1-COMVCC,下载继电器程序运行,按一下复位键,此时继电器工作,LED2灯亮。
2.2 4位LED动态显示模块电路的设计
在该电路的设计中需要用到4个数码管,每个数码管的8段有芯片8255的PB口控制亮灭,每个数码管的公共脚分别由8255的PA2-PA5经三极管扩流后进行控制,原理图如图4所示:
图 4 整形电路原理图
数码管的笔画顺序,本组用到的数码管是共阳极的,当在公共引脚接上电源正极,笔画脚通过一个220欧姆的电阻接负极,对应的笔画就会点亮。显示的数字0~9的8位二进制码如表1所示:
表 1 数码管显示数值所对应的段码表
显示码
数字
十六进制
二进制
g
c
dp
d
e
b
f
a
0
0XA0
1
0
1
0
0
0
0
0
1
0XBB
1
0
1
1
1
0
1
1
2
0X62
0
1
1
0
0
0
1
0
3
0X2A
0
0
1
0
1
0
1
0
4
0X39
0
0
1
1
1
0
0
1
5
0X2C
0
0
1
0
1
1
0
0
6
0X24
0
0
1
0
0
1
0
0
7
0XBA
1
0
1
1
1
0
1
0
8
0X20
0
0
1
0
0
0
0
0
9
0X28
0
0
1
0
1
0
0
0
注:‘1’对应的笔画熄灭,‘0’对应的笔画点亮。注:‘1’对应的笔画熄灭,‘0’对应的笔画点亮。
要在某位数码管上显示一个数字,首先把待显示的数字的显示码送给8255的PB口,接着选中要显示的位。例如:要在开发板中最右边的数码管上显示一个‘0’,则需要先把‘0’的显示码0XC0送至PB口,接着给PA5赋低电平,随后让单片机保持这个值不变,下载时钟程序即可让数码管显示规定的数字。由于我们需要让四位数码管同时动态显示,还应考虑到显示时间的长短,这时用一个延时程序来控制即可。
2.3 键盘扫描模块电路的设计
在单片机系统中键盘中按钮数量较多时,为了减少I/O口的占用,常常将按钮排列成矩阵形式。而在本设计中为了通过键盘来调整开关时间,时间要在4位数码管上显示出来,故我们用4个按键分别来改变数码管4位的数值,电路如图5所示:
图 5 键盘扫描电路
判断键盘中有无键盘按下的方法:先将PA0拉高,然后扫描PC各行的电平状态,若哪一行出现高电平,即可知道该行的按键被按下。当按键每被按下一次,所对应的数码管的数值就会加1,超过‘9’时,又回到‘0’。从而很容易地实现了时间的可调。
2.4 系统复位电路设计
单片机的复位电路如图6示:
图 6 复位电路图
RST:复位输入。晶振工作时,RST脚持续2个机器周期高电平将使单片机复位。看门狗计时完成后,RST脚输出96个晶振周期的高电平。特殊寄存器AUXR上的DISRT0位可以使此功能无效。DISRT0默认状态下,复位高电平有效。
2.5 系统晶振电路设计
本系统采用的是12MHZ的晶振,其电路图如图7所示:
图 7 晶振电路图
XTAL1:振荡器反相放大器和内部时钟发生电路的输入端。
XTAL2:振荡器反相放大器的输出端。
2.6 STC89C52芯片与8255芯片的介绍
STC89C52芯片如图8所示:
图 8 STC89C52芯片图
STC89C52是低功耗、高性能的CMOS8位微控制器。8字节的flash,256字节的RAM,32位的I/O口线,看门狗定时器,2个数据指针,3个16位定时器/计数器。全双工串行口,片内晶振及时钟电路,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,内容被保存,振荡器被冻结。
8255芯片引脚图如图9所示:
图 9 8255芯片引脚图
8255西片是一种典型的课编程通用并行接口芯片,用来扩展单片机的端口,它具有3个8位的并行口,有三位工作方式,可作为单片与各种外部设备连接的接口电路。
CS:片选信号线,当该引脚为低电平时,8255被选中,允许8255与CPU通讯。
RESET:复位输入线,当该引脚为高电平时,内部寄存器被清除,所有I/O口均被置成输入方式。
A0、A1:地址输入线。
当A0A1=00时,PA口被选中;
当A0A1=01时,PB口被选中;
当A0A1=10时,PC口被选中;
当A0A1=11时,控制寄存器被选中。
2.7 节能时控器总的电路图
节能时控器整个系统电路图如图10所示:
图 10 系统总电路图
3 系统设计的流程图
SHAPE \* MERGEFORMAT
图 11 系统流程图
4 系统软件的初始化设计 4.1 8255芯片的初始化
随着大规模集成电路的发展,接口电路也被集成在单一的芯片上,许多芯片可以通过编程方法设定工作方式,这种接口芯片被称为可编程I/O接口芯片,8255芯片是最常用的一种。使用8255芯片前,必须对其各个端口地址进行设置,不然无法进行与CPU进行通信。由于本设计中需要通过8255的PA、PB、PC口分别来控制数码管的位选信号、段选信号、键盘的输入,同时还需要对其方式控制字进行设置。具体如下:
#define a8255_PA XBYTE[0xD1FF] /*PA口地址*/
#define a8255_PB XBYTE[0xD2FF] /*PB口地址*/
#define a8255_PC XBYTE[0xD5FF] /*PC口地址*/
#define a8255_CON XBYTE[0xD7FF] /*控制字地址*/
4.2 定时器T0的初始化
源于该设计的时间显示要非常精确,可以使系统的时序是用定时单位来描述的,在此选用定时器0,而单片机内部的时钟频率为12MHZ,那么它的一个时钟周期为1/12us,而一个机器周期是一个时钟周期的12倍,即一个机器周期的时间为1us.
根据设计要求,我们需要50ms作为一个单位时间,选用定时器T0,对其的初始化过程如下:
⑴ 选择工作方式1:16位定时器/计数器方式,最多可以计到2的16次方,即65536.
⑵ 工作方式寄存器TMOD的设置:TMOD=0X01.
⑶ 50ms的精确定时:TH0=0x3C,TL0=0Xb0.
定时器T0具体初始化程序如下:
void Timer0_Init(void) //0.5mS
{ TMOD |= 0x01;
TH0 = 0x3C;
TL0 = 0xB0;
ET0 = 1;
}
void GInt_Init(void)
{
EA = 1;
EX0 = 1;
IT0 = 1;
}
4.3 1S中断程序
根据设计要求,要求实现时间倒计时,为此我们将1s的中断程序放在外部中断0内,当外部中断0响应时,完成1s计时,改变显示的时间。
详细的中断程序如下:
void ISR_Timer0(void) interrupt 1
{
Timer_Count++;
if(Timer_Count == 20) //1s
{
Timer_Count = 0;
Flag_Second = 1; //设置1s标志
}
Timer0_Init();
}
4.4 数码管显示数值程序
数码管显示函数程序采用的是ASCII代码,具体程序如下:
unsigned char const dis_table[16]={
0xA0, /*0*/
0xBB, /*1*/
0x62, /*2*/
0x2A, /*3 */
0x39, /*4*/
0x2C, /*5 */
0x24, /*6*/
0xBA, /*7*/
0x20, /*8*/
0x28, /*9 */
0x30, /*A*/
0x25, /*B*/
0xE4, /*C*/
0x23, /*D*/
0x64, /*E*/
0x74, /*F */
};
void display(unsigned char place, unsigned char num)
{
unsigned char i = 0,display_num = 0;
a8255_CON=0x89;
a8255_PB=0xff;
a8255_PA=0xff;
a8255_PA= ~(0x1
if(num >= 0x30 && num
a8255_PB = dis_table[num - 0x30];
else if(num >= 0x41 && num
a8255_PB = dis_table[num - 0x37];
else
a8255_PB = 0xff;
delay(2);
}
4.5 延时函数程序
数码管动态显示必须要求每一个数值显示有所延时,可用下面的延时程序来实现
延时程序:
void delay05s(unsigned int Num)
{
unsigned char i, j, k;
unsigned int count = 0;
for(count = Num; count > 0; count--)
{
for( i = 5; i > 0 ; i--)
{
for( j = 25; j > 0; j--)
{
for( k = 2; k > 0; k--);
}
}
}
}
4.6 键盘扫描函数程序
进行键盘扫描,实现数码管数值的可调。程序如下:
unsigned char Scan_Keyboard(void)
{
unsigned char i = 0,j = 0,PC_data = 0;
unsigned char test_x=0,test_y=0;
a8255_CON=0x89;
a8255_PB=0xff;
a8255_PA=0xff;
PC_data=a8255_PC;
for(j = 0;j
{
if((PC_data & (1
{
delay(10);
if((PC_data & (1
{
for(i = 0;i
{
a8255_PA=1
PC_data=a8255_PC;
if((PC_data & (1
{
test_x = i;
test_y = j;
flag_button = 1;
break;
}
}
}
}
}
a8255_PA=0xff;
while( a8255_PC & 0xf);
if(test_x == 0 && test_y == 3)
return('+');
else if(test_x == 1 && test_y == 3)
return('-');
else if(test_x == 2 && test_y == 3)
return('=');
else if(test_x == 3 && test_y == 3)
return('0');
else if(test_x == 0 && test_y == 0)
return('*');
else if(test_x == 1 && test_y == 0)
return('/');
}
5 系统功能测试与整体调试 5.1 继电器工作与数码管同步显示
此模块的程序见附录1.1,编译成功生成hex文件后下载,可观察到继电器的停止状态和工作状态与数码管显示的时间同步。
5.2 数码管上的数值可调
此模块的程序见附录1.2,编译成功生成hex文件后下载,可观察到数码管的时间显示有两个时间段,这两个时间段构成一个周期。这个周期段是数值开始从‘1500’减为‘0000’,在显示‘0000’那刻末数值立刻变到‘0200’,接着又从‘0200’减到‘0000’。只要有中断响应,数码管的数值就可由四个按键来分别改变。
5.3 整个系统的调试
整体调试的程序见附录1.3,下载后系统按初始化的程序在执行,继电器和数码管正常工作,一旦有中断响应,通过扫描键盘上按键的按下来调整继电器的开关时间,使得继电器的开关时间段发生变化。若复位键按下,则系统按初始化的程序运行。因此很好地完成了此次单片机课程设计所规定的要求。
6详细仪器清单 表2 仪器清单
仪器名称
数量
STC89C52芯片
1
8255芯片
1
1K电阻
21
型号为9015的三极管
5
30pf电容
2
极性电容
1
8段共阳极数码管
5
继电器
1
开关
2
石英晶振
1
矩形按键
6
7总结及致谢
单片机课程设计历时十天,在整整十天的日子里,可以说得是苦多于甜,但是可以学到很多很多的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。以前在上课的时候,老师经常强调在做设计的时候,一定要事先把设计原理方框图画出来,但是我开始总觉得这样做没必要,很浪费时间。但是,这次课程设计完全改变了我以前的那种错误的认识,以前我接触的那些程序都是很短、比较基础的,但是在课程设计中碰到的那些需要很多小模块才能完成的任务,画原理图是很有必要的。因为通过原理图,在做设计的过程中,我们每一步要做什么,每一步要完成什么任务都有一个很清楚的思路,而且在功能测试的过程中也有利于查错。
通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,这毕竟第一次做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固。这次课程设计终于顺利完成了,在设计中遇到了很多问题,,我了解到自己在设计原理图方面还有很多不足,以后我会更加努力。
在这次设计中我们遇到过很多问题,每次询问同学和老师时他们总会耐心地给我们讲述,在此衷心的感谢帮助过我们的所有同学,以及要特别感谢老师、岳老师、方老师和谭老师的耐心指导。没有你们的教导和解答,我们不可能这么容易完成这次的课程设计。
参考文献 [1] 朱定华. 戴汝平. 单片微机原理与应用(M). 北京: 清华大学出版社,2003
[2] 张鑫. 单片机原理及应用(M). 北京: 电子工业出版社,2005.8
[3] 楼然苗. 李光飞. 单片机课程设计指导(M). 北京: 北京航空航天大学出版社,2007.7
[4] 陈家俊. 郑滔. 程序设计教程—用C++语言编程(M). 北京: 机械工业出版社,2004.8
附录1: 附录1.1节能时控器主程序 #include "reg51.h"
#include "math.h"
#define k_dtzt 1
#define k_dkzt 2
#define k_zcdt 3
//外部函数申明
extern void display(unsigned char place,unsigned char num); //数码管显示函数
extern unsigned char Scan_Keyboard(void);
sbit CS=P1^2;
extern void GInt_Init(void);
extern unsigned char flag_button; //在keyboard.c中定义并被赋值
extern void Timer0_Init(void);
unsigned char Display_Array[6]; //显示用数组
unsigned char Timer_Count = 0;
unsigned char Flag_Second = 0;
void main(void)
{
unsigned char i = 0;
unsigned char temp = 0; //零时变量
unsigned long k_dqzt= 0;
unsigned char times = 0,light1=0; //循环次数
k_dqzt = k_dtzt;
for(i = 0; i
Display_Array[i] = '0';
while(1)
{
display(1,Display_Array[0]);
display(2,Display_Array[1]);
display(3,Display_Array[2]);
display(4,Display_Array[3]);
display(5,Display_Array[4]);
display(6,Display_Array[5]); //显示部分
temp = Scan_Keyboard(); //获得键值
if((temp == '+' || temp == '-' )&& flag_button == 1) //有按键,且按键的内容为0到9 时
{
flag_button = 0;
if(temp == '+' )
{
Display_Array[5]++;
if(Display_Array[5]>'9')
{
Display_Array[5]='0' ;
Display_Array[4]++;
}
}
else if(temp == '-' )
{
Display_Array[5]--;
if(Display_Array[5]
{
Display_Array[5]='9';
Display_Array[4]--;
}
}
Display_Array[5]= Display_Array[5];
Display_Array[4]= Display_Array[4];
}
else if (temp=='='&&flag_button == 1)
{
flag_button = 0;
CS = 0;
k_dqzt = k_dtzt;
Timer0_Init(); //定时器0的初始化, 50mS的定时
GInt_Init(); //开中断
TR0 = 1;
}
else if(Flag_Second == 1 && k_dqzt == k_dtzt)
{
Flag_Second = 0;
Display_Array[5]--;
if(Display_Array[5]
{
Display_Array[5]='9';
Display_Array[4]--;
}
if(Display_Array[5]=='0'&&Display_Array[4]=='1')
{
CS = 1;
k_dqzt=k_dkzt;
}
}
else if (Flag_Second == 1 && k_dqzt == k_dkzt)
{
Flag_Second = 0;
Display_Array[5]--;
if(Display_Array[5]
{
Display_Array[5]='9';
Display_Array[4]--;
}
if(Display_Array[5]=='5'&&Display_Array[4]=='0')
{
CS = 0;
k_dqzt=k_zcdt;
}
}
else if(Flag_Second == 1 && k_dqzt == k_zcdt)
{Flag_Second = 0;
Display_Array[5]--;
if(Display_Array[5]=='0'&&Display_Array[4]=='0')
{
CS = 1;
TR0 = 0;
}
}
} }
void ISR_Timer0(void) interrupt 1
{
Timer_Count++;
if(Timer_Count == 20) //1S
{
Timer_Count = 0;
Flag_Second = 1; //设置1s标志
}
Timer0_Init(); }