单片机课程设计报告扩展模块.docx
《单片机课程设计报告扩展模块.docx》由会员分享,可在线阅读,更多相关《单片机课程设计报告扩展模块.docx(26页珍藏版)》请在冰豆网上搜索。
单片机课程设计报告扩展模块
石家庄经济学院信息工程学院
电子信息工程专业
单片机课程设计报告
题目基于AT89C51单片机的扩展设计
姓名
学号
班级
指导教师
2012年7月6日
要求:
1.指导教师按照课程设计大纲要求完成学生课程设计指导工作。
2.课程设计任务书由指导教师照大纲要求填写,内容要全面。
3.课程设计报告由参加本学生填写。
课程设计结束时交指导教师。
(电子稿就行)
4.指导教师要根据每一位学生课程设计任务完成情况,认真审核设计报告,并在课程设计结束时,给出客观、准确的评语和成绩。
5.课程设计任务书和报告要语言流畅,图表正确规范。
6.本表要用钢笔、圆柱笔填写或打印,字迹工整。
(请把此页打印在封面的背面,打印时请删除此句话)
课程设计任务书
班级姓名学号
课程设计题目基于AT89C51单片机的扩展设计
课程设计起止日期2012-06-18至2012-07-05
实习地点实验楼-5-106
课程设计内容与要求(包括:
设计任务及要求、设计原理、所需仪器设备、验收标准)
(一)设计任务及要求
良:
应用DS1302完成时钟设计,动态循环显示时、分、秒,用键盘输入当前时间。
优:
在良的基础上,应用DS18B20S实现温度的采集与显示。
(二)设计原理
本设计应用的是DS1302时钟芯片进行计时,DS18B20温度传感器芯片进行温度采集,再通过AT89C51进行数据处理,依次进行时间和温度的显示,并通过键盘来加减时间,进行时间的调整。
(三)所需仪器设备
扩展模块所需的仪器:
AT89C51、DS1302、DS18B20、74LS373、74LS138、LED显示、键盘等。
指导教师:
2012年07月05日
一、设计原理与技术方法:
图1单片机实验板总体电路图
图1单片机实习系统电路图
图2Proteus仿真电路
8051芯片的说明:
单片机的40个引脚大致可分为4类:
电源、时钟、控制和I/O引脚。
1.电源:
⑴VCC-芯片电源,接+5V;
⑵VSS-接地端;
2.时钟:
XTAL1、XTAL2-晶体振荡电路反相输入端和输出端。
3.控制线:
控制线共有4根,
1ALE/PROG:
地址锁存允许/片内EPROM编程脉冲
①ALE功能:
用来锁存P0口送出的低8位地址
②PROG功能:
片内有EPROM的芯片,在EPROM编程期间,此引脚输入编程脉冲。
2PSEN:
外ROM读选通信号。
3RST/VPD:
复位/备用电源。
①RST(Reset)功能:
复位信号输入端。
②VPD功能:
在Vcc掉电情况下,接备用电源。
4EA/Vpp:
内外ROM选择/片内EPROM编程电源。
①EA功能:
内外ROM选择端。
②Vpp功能:
片内有EPROM的芯片,在EPROM编程期间,施加编程电源Vpp。
4.I/O线
80C51共有4个8位并行I/O端口:
P0、P1、P2、P3口,共32个引脚。
P3口还具有第二功能,用于特殊信号输入输出和控制信号(属控制总线)。
DS1302芯片说明:
1、功能特色:
(1)时钟计数功能,可以对秒、分钟、小时、月、星期、年的计数。
年计数可达到2100年。
(2)有31*8位的额外数据暂存寄存器
(3)最少I/O引脚传输,通过三引脚控制
(4)工作电压:
2.0-5.5V
(5)工作电流小于320纳安(2.0V)
(6)读写时钟寄存器或内部RAM(31*8位的额外数据暂存寄存)可以采用单字节模式和突发模式
(7)8-pinDIP封装或8-pinSOICs
(8)兼容TTL(5.0V)
(9)可选的工业级别,工作温度-40–85摄氏度
(10)兼容DS1202较DS1202增加的功能:
a.可通过Vcc1进行涓流充电
b.双重电源补给
c.备用电源可采用电池或者超级电容(0.1F以上),可以用老式电脑主板上的3.6V充电电池。
如果断电时间较短(几小时或几天)时,就可以用漏电较小的普通电解电容器代替。
100μF就可以保证1小时的正常走时。
DS1302在第一次加电后,必须进行初始化操作。
初始化后就可以按正常方法调整时间。
2、引脚功能:
(1)X1,X2:
32.768KHz晶振引脚;
(2)GND:
接地;
(3)RST:
复位;
(4)I/O:
数据输入/输出;
(5)SCLK:
串行时钟;
(6)Vcc1,Vcc2:
电源供给引脚。
DS1302的结构及转换原理:
移位寄存器,控制逻辑,晶振,时钟和RAM。
在进行任何数据传输时,RST必须被制高电平(注意虽然将它置为高电平,内部时钟还是在晶振作用下走时的,此时,允许外部读写数据),在每个SCLK上升沿时数据被输入,下降沿时数据被输出,一次只能读写一位,适度还是写需要通过串行输入控制指令来实现(也是一个字节),通过8个脉冲便可读取一个字节从而实现串行输入与输出。
最初通过8个时钟周期载入控制字节到移位寄存器。
如果控制指令选择的是单字节模式,连续的8个时钟脉冲可以进行8位数据的写和8位数据的读操作,SCLK时钟的上升沿时,数据被写入DS1302,SCLK脉冲的下降沿读出DS1302的数据。
8个脉冲便可读写一个字节。
在突发模式,通过连续的脉冲一次性读写完7个字节的时钟/日历寄存器(注意时钟/日历寄存器要读写完),也可以一次性读写8~328位RAM数据(可按实际情况读写一定数量的位,不必全部读写,两者的区别)。
图3DS1302管脚图
DS18B20芯片说明:
1、主要特性:
(1)适应电压范围更宽,电压范围:
3.0~5.5V,在寄生电源方式下可由数据线供电;
(2)独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯;
(3)DS18B20支持多点组网功能,多个DS18B20可以并联在唯一的三线上,实现组网多点测温;
(4)DS18B20在使用中不需要任何外围元件,全部传感元件及转换电路集成在形如一只三极管的集成电路内;
(5)温范围-55℃~+125℃,在-10~+85℃时精度为±0.5℃;
(6)可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃,可实现高精度测温;
(7)在9位分辨率时最多在93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字,速度更快;
(8)测量结果直接输出数字温度信号,以"一线总线"串行传送给CPU,同时可传送CRC校验码,具有极强的抗干扰纠错能力;
(9)负压特性:
电源极性接反时,芯片不会因发热而烧毁,但不能正常工作。
2、引脚功能:
(1)DQ:
数字信号输入/输出端;
(2)GND电源地;
(3)VDD外接供电电源输入端(在寄生电源接线方式时接地)。
DS18B20的结构及转换原理:
DS18B20内部结构主要由四部分组成:
64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。
DS18B20的读写时序和测温原理与DS1820相同,只是得到的温度值的位数因分辨率不同而不同,且温度转换时的延时时间由2s减为750ms。
DS18B20测温原理如图4所示。
图中低温度系数晶振的振荡频率受温度影响很小,用于产生固定频率的脉冲信号送给计数器1。
高温度系数晶振随温度变化其振荡率明显改变,所产生的信号作为计数器2的脉冲输入。
计数器1和温度寄存器被预置在-55℃所对应的一个基数值。
计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当计数器1的预置值减到0时,温度寄存器的值将加1,计数器1的预置将重新被装入,计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度。
图4中的斜率累加器用于补偿和修正测温过程中的非线性,其输出用于修正计数器1的预置值。
图4DS18B20测温原理
2、程序设计思路说明:
设计思路:
利用89C51单片来对DS1302时钟芯片以及DS18B20温度采集芯片中的数据进行采集,运算,转化以及通过数码管显示时间和当前温度。
流程图如图5:
图5程序流程图
3、程序代码:
***************************************************************************************
主程序代码:
主程序的功能是,对从DS1302和DS19B20中读取的数据进行处理,和现实,并能实现对时钟芯片内时间的改变。
***************************************************************************************
主程序代码:
#include
#include
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineTF1_VECTOR3/*计数器1中断入口*/
externucharreadds1302(uchar_code);//调用外部子程序,读DS1302
externvoidwriteds1302(ucharfp,uchar_code);//调用外部子程序,写DS1302
externvoiddelay_18B20(unsignedinti);//调用外部子程序,读温度
ucharchg_bcd_secl(uchar_code);
ucharchg_bcd_sech(uchar_code);
ucharchg_bcd_minl(uchar_code);
ucharchg_bcd_minh(uchar_code);
ucharchg_bcd_hrl(uchar_code);
ucharchg_bcd_hrh(uchar_code);
ucharchg_bcd(uchar_code);
ucharadd_time(uchar_code);
uintRead_Temperature();
ucharchg_bcd_teml(uchar_code);
ucharchg_bcd_temh(uchar_code);
voidchg_time(void);
voidaddtime_isr(void);
voiddisplay(void);
staticucharm=4,n=7,temp=0;
sbitP13=P1^3;
sbitP14=P1^4;
sbitP15=P1^5;
sbitP37=P3^7;
voidmain()//主函数
{
uchari,j,k,fp,temp,out[11],hp;//设定变量
TMOD=0x10;//设置计数器工作方式
TL1=0xb0;//计数1初值
TH1=0x3c;
EA=1;//开中断
ET1=1;
TR1=1;//计数器开始工作
P15=0;//键盘送低电平
out[2]=out[5]=out[8]=0xbf;
i=0x20;//初始化DS1302的数值
j=0x12;
k=0x00;
fp=0x80;//fp为写DS1302的地址
writeds1302(fp,i);//向DS1302内写入初值
fp=0x82;
writeds1302(fp,j);
fp=0x84;
writeds1302(fp,k);
fp=0;
for(;;)
{P37=0;
if(P13==0){delay_18B20(100);for(;P13==0;);chg_time();};//扫描键盘
temp=Read_Temperature();//读取当前温度值
k=chg_bcd_teml(temp);
out[0]=chg_bcd(k);//分离出温度的个位,并送入存储数值的数组
k=chg_bcd_temh(temp);
out[1]=chg_bcd(k);//分离温度的十位
i=0x81;
j=readds1302(i);//读取当前时间的秒,并分离个位与十位,并存入数组
k=chg_bcd_secl(j);
out[3]=chg_bcd(k);
k=chg_bcd_sech(j);
out[4]=chg_bcd(k);
i=0x83;//读取当前时间的分,并分离个位与十位,并存入数组
j=readds1302(i);
k=chg_bcd_minl(j);
out[6]=chg_bcd(k);
k=chg_bcd_minh(j);
out[7]=chg_bcd(k);
i=0x85;//读取当前时间的时,并分离个位与十位,并存入数组
j=readds1302(i);
k=chg_bcd_hrl(j);
out[9]=chg_bcd(k);
k=chg_bcd_hrh(j);
out[10]=chg_bcd(k);
hp=0xf0;//hp为第一个数码管的选通地址
for(i=0;i<4;i++)
{
P2=0x60;P0=out[i+n];P2=hp;//锁存相应数据,并选通对应的数码管
hp=hp-0x20;//地址变为下一个数码管的地址
delay_18B20(50);//延时,以免显示时间太短,造成数码管显示特别暗
if(i==3)P2=0x20;//在最后一个数码管显示完毕后,关闭数码管
}
}
}
ucharchg_bcd_secl(uchar_code)//分离秒的个位//
{
_code&=0x0f;
return(_code);
}
ucharchg_bcd_sech(uchar_code)//分离秒的十位//
{uchari=4;
_code&=0xf0;
_code=_cror_(_code,i);
return(_code);
}
ucharchg_bcd_minl(uchar_code)//分离分的个位//
{
_code&=0x0f;
return(_code);
}
ucharchg_bcd_minh(uchar_code)//分离分的十位//
{uchari=4;
_code&=0x70;
_code=_cror_(_code,i);
return(_code);
}
ucharchg_bcd_hrl(uchar_code)//分离时的个位//
{
_code&=0x0f;
return(_code);
}
ucharchg_bcd_hrh(uchar_code)//分离时的十位//
{uchari=4;
_code&=0x30;
_code=_cror_(_code,i);
return(_code);
}
ucharchg_bcd_teml(uchar_code)//调整温度的个位
{
_code&=0x0f;
if(_code>0x09){_code-=0x0a;F0=1;}
elseF0=0;
return(_code);
}
ucharchg_bcd_temh(uchar_code)//调整温度的十位
{
_code&=0xf0;
if(F0==1)_code+=0x10;
_code=_code>>4;
return(_code);
}
ucharchg_bcd(uchar_code)//BCD码转换成LED段码//
{
uchari;
switch(_code)
{case0x00:
i=0xc0;break;
case0x01:
i=0xf9;break;
case0x02:
i=0xa4;break;
case0x03:
i=0xb0;break;
case0x04:
i=0x99;break;
case0x05:
i=0x92;break;
case0x06:
i=0x82;break;
case0x07:
i=0xf8;break;
case0x08:
i=0x80;break;
case0x09:
i=0x90;break;
default:
i=0x00;
}
return(i);
}
voidtimer1_isr(void)interruptTF1_VECTOR
{
if(m==4){TMOD=0x16;
TL1=0xb0;//计数1初值
TH1=0x3c;
PT0=1;//设置优先级,计数器0高优先级,计数器1低优先级
PT1=0;
temp++;//延时计数器加1,在加为10后置0,中断一次为0.1秒,中断十次为1秒,中断一秒后滚动显示下一位
if(temp==10){temp=0;if(n==0)n=8;n=n-1;}
}
}
voidaddtime_isr(void)//加时间子程序
{
ucharfp_r,fp_w,k;
if(m==0){fp_r=0x83;fp_w=0x82;}//如果此时状态存储器m为0,则为调整分位,此时将写入地址和读取时间地址设置为分对应的地址
elseif(m==2){fp_r=0x85;fp_w=0x84;}//如果此时状态存储器m为2,则为调整时位,此时将写入地址和读取时间地址设置为分对应的地址
k=readds1302(fp_r);//读取当前时间
k=add_time(k);//将当前时间加1
writeds1302(fp_w,k);//将加1后的时间再次写入DS1302
}
ucharadd_time(uchar_code)
{
if(m==0){if((_code&0x0f)==0x09){_code&=0xf0;
if(_code==0x50)_code=0x00;
else_code=_code+0x10;
else_code++;}//如果m为0,则调整的是分位,如果此时个位为9,那加1后个位为0,十位加1,如果此时为59,则加1后为00
if(m==2){if(_code==0xa3){_code=0x00;}
elseif((_code&0x0f)==0x09){_code&=0xf0;
if(_code==0x90)_code=0xa0;
else_code=_code+0x10;}
else_code++;}//如果m为2,则调整的是时位,如果此时个位为9,那加1后个位为0,十位加1,如果此时为23,则加1后为00
return(_code);//返回加1后的值
}
voidchg_time(void)//改变时间子程序
{
ucharfp=0,i,j,k,out_[4],hp;
F0=0;TR1=0;//关毕计数器
if(m==4)m=0;//如果改变时间之前为4(正常显示状态),则此时为改变分状态
while(m<4)//如果状态存储器此时为正常显示状态,则返回主程序进行正常显示
{
fp++;
if(fp==0x3f){F0=~F0;fp=0;}//跳动显示累加器,每循环执行3f次,则改变标志位,由亮变为灭,或由灭变为亮
i=0x83;//分钟读取地址
j=readds1302(i);
k=chg_bcd_minl(j);
out_[0]=chg_bcd(k);
k=chg_bcd_minh(j);
out_[1]=chg_bcd(k);
i=0x85;//小时读取地址
j=readds1302(i);
k=chg_bcd_hrl(j);
out_[2]=chg_bcd(k);
k=chg_bcd_hrh(j);
out_[3]=chg_bcd(k);
hp=0xf0;
for(i=0;i<4;i++)/*跳动显示设置位*/
{
if(i==m||i==(m+1))//此时m为0,跳动显示分钟的个位和十位,即out_[0]和out_[1];若为2,则跳动显示小时的个位和十位,即out_[2]和out_[3]
{P2=0x60;P0=out_[i];
if(F0==1)//如果此时标志位为显示状态,则送相应地址;否则,送其他(不会导致数码管显示)的地址
{P2=hp;}
else{P2=0x00;}}
else{P2=0x60;P0=out_[i];//不跳动的位正常显示
P2=hp;}
hp=hp-0x20;
delay_18B20(50);
if(i==3)P2=0x20;
}
if(P13==0){delay_18B20(100);if(m==0){m=2;for(;P13==0;);}
//扫描键盘,如果S2按下,则切换下一状态
elseif(m==2){m=4;for(;P13==0;);}};
if(P14==0){delay_18B20(100);for(;P14==0;);addtime_isr();}
//如果S4按下,则相应位加1
}
TR1=1;TMOD=0x10;TL1=0xb0;TH1=0x3c;//中断返回,定时器T1开始工作,初始化T1
}
***************************************************************************************
DS1302的驱动程序:
此程序的功能为,能进行时间的读取和写入,并设置成子函数,供出程序进行调用。
***************************************************************************************
DS1302的驱动程序:
/*DS1302读写程序(C51)*/
#include
#defineucharunsignedchar
sbitDS13CLK=P1^0;/*