西安交大可报温报时电子钟设计报告docx.docx
《西安交大可报温报时电子钟设计报告docx.docx》由会员分享,可在线阅读,更多相关《西安交大可报温报时电子钟设计报告docx.docx(42页珍藏版)》请在冰豆网上搜索。
![西安交大可报温报时电子钟设计报告docx.docx](https://file1.bdocx.com/fileroot1/2023-3/30/08766d07-e113-489d-8578-505fef9eab70/08766d07-e113-489d-8578-505fef9eab701.gif)
西安交大可报温报时电子钟设计报告docx
电子系统设计报告
电气43陈振斌孙鹏程
西安交通大学
2017-5-20
1、整体系统框图
2、系统工作原理
基于单片机STC89C52与开发平台KEIL软件,利用C语言设计相关程序。
期间配合使用DS1302时钟芯片实现走时功能,使用温度传感器件DS18B20实现室温测量功能,使用ISD1760语音芯片实现录放音功能以及配合动态显示数码将相关功能以可视形式呈现,并通过按键配合实现切换显示、校时、定闹等额外功能。
3、软件框图
4、系统使用介绍:
电路板上电后,初始状态数码管显示时钟;
S1键切换模式,模式0为正常显示模式,模式1为校正模式,并且取决于按下按键之前显示部分依次进入:
时钟校正、日历校正、闹钟定时模块;
S2键切换显示,依次为:
时钟、日历、温度;
S3键在进入校正模式有效,用于选择校正位;
S4键在进入校正模式有效,用于对当前校正位进行数值改变,即“加1”功能;
S5键在校正模式时,用于确认校正,在闹钟闪烁时,按下可关闭闹钟;
S6为电路板重置键,终止程序;
RST键为语音芯片重置键,中断语音芯片工作。
5、已知部分缺陷及非完美解决方案:
问题描述:
进入校正模式时,会出现数据读取错乱,使得数码显示0~9以外的数字,如A、B、C、D等;在确认校正时同样会有几率出现该问题。
推测原因:
DS1302走时程序中数据会有过渡性变化,使得display_buffer[]数组的数据在读取和置入时产生问题。
或置数时有数据错误。
解决方案:
对显示错乱部分重新进行校时,该处将置零。
此后可正常校正。
6、软件编写与调试时所遇到的问题及解决方案:
●按键按下时程序多次执行:
利用“miaomiao”系列变量作为判定条件保证只执行一次程序;
●对显示变量display_buffer直接进行加一操作进位产生错乱:
引入buffer_temp[]数组,替代校正;
●语音芯片不能连续播放多段语音:
每段播放后延时适当时间;
●为使得”on”、”off”的右下角显示小数点时对SEGMENT直接进行“位与”操作只能显示"o8.”、”of8”.等:
引入变量s过渡;
●整点报时会连续两次播放语音:
只在分钟显示为“59”时使得miaomiao_play变量为一,播放后置为零,保证只播放一次;
●报温时可能读取到设定工作温度上限(39摄氏度)的温度值且实际此时温度在上限之内:
在tmread()函数里增加循环读取部分直至读到正常数值;
●其他组组员(于晨曦同学)提出的建议与提示:
温度读取时间较长不宜加入定时中断显示;每次显示前对位码或段码(取决于置数顺序)先置零,以解决数码管残影问题。
7、PCB板原理图及接线图
见验收文件夹PPT,由于打印问题在此不作展示。
8、源程序代码
#include
#include
#include
#include
#defineSEGMENTXBYTE[0xdfff]
#defineBIT_LEDXBYTE[0xbfff]
#definefosc11.0592
#definetime02500
#defineuintunsignedint
#defineSEGMENTXBYTE[0xdfff]
#defineBIT_LEDXBYTE[0xbfff]
//语音部分定义开始
unsignedcharbdataSR0_L;
unsignedcharbdataSR0_H;
unsignedcharbdataSR1;
unsignedcharAPCL=0,APCH=0;
unsignedcharPlayAddL=0,PlayAddH=0;
unsignedcharRecAddL=0,RedAddH=0;
sbitCMD=SR0_L^0;
sbitFULL=SR0_L^1;
sbitPU=SR0_L^2;
sbitEOM=SR0_L^3;
sbitINTT=SR0_L^4;
sbitRDY=SR1^0;
sbitERASE=SR1^1;
sbitPLAY=SR1^2;
sbitREC=SR1^3;
unsignedcharISD_SendData(unsignedchardat);
voidISD_PU(void);
voidISD_Rd_Status(void);
voidISD_WR_APC2(unsignedcharapcdatl,apcdath);
voidISD_SET_PLAY(unsignedcharSaddl,Saddh,Eaddl,Eaddh);
sbitSS=P1^4;
sbitSCK=P1^7;
sbitMOSI=P1^5;
sbitMISO=P1^6;
voidISD_Init(void);
voiddelay(unsignedintt);
unsignedcharget_address(unsignedchark);//快速获取部分语音地址函数
//语音部分定义结束
//温度部分定义开始
sbitTMDAT=P3^4;
voiddmsec(unsignedintcount);
voidtmreset(void);
voidtmstart(void);
voidtmdisplay(void);
voidtmread(void);//温度读取函数
unsignedchartmrtemp(void);
unsignedcharcodeseg_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x67,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
unsignedcharcodetran_code[]={0,1,2,3,4,5,6,7,8,9};//类型转换数组
unsignedcharlast;
intlast_shi=2,last_ge=6;
//温度部分定义结束
//时间部分定义开始
unsignedchardatadisplay_bit,display_buffer[8],display_buffer1[8],ring[8]={1,5,0,0,0,1,0,0};
unsignedchardatatime0_h,time0_1,TEMP;
unsignedintidatatime0_times;
unsignedcharget_code(unsignedchari);
voiddisplay(void);
voidinitial_ds1302();
unsignedcharread_ds1302(charcommand);
voidopen_write_bit();
voidclose_write_bit();
voidread_time();
voidset_time();
voidreset_time();//校正确认功能函数
voidread_date();
sbitSCL_DS1302=P2^0;
sbitIO_DS1302=P2^1;
sbitRST_DS1302=P2^2;
unsignedcharbdatadata_ds1302;
sbitbit_data0=data_ds1302^0;
sbitbit_data7=data_ds1302^7;
unsignedcharbdatax;
sbitx0=x^0;
sbitx7=x^7;
//时间部分定义结束
//功能部分定义开始
sbitkey1=P1^0;//切换功能
unsignedcharmodecg;//工作模式指示变量
sbitkey2=P1^1;//切换显示
unsignedchardisplaycg;//切换显示指示变量
sbitkey3=P1^2;//切换校正位
unsignedchartime_ajflag;//时钟校正位指示变量
unsignedchartime_bitadjust;//时钟校正位显示变量
unsignedchardate_ajflag;//日历校正位指示变量
unsignedchardate_bitadjust;//日历校正位显示变量
unsignedcharring_ajflag;//闹钟校正位指示变量
unsignedcharring_bitadjust;//闹钟校正位显示变量
sbitkey4=P1^3;//加位键
sbitkey5=P3^2;//确认或关闭闹钟键
unsignedcharmiaomiao_1,miaomiao_2,miaomiao_3,miaomiao_4,miaomiao_5,miaomiao_play;//防止多次执行步骤指示变量
unsignedcharj,s;//j为部分程序循环指示变量,s为为解决onoff的加小数点显示问题而定义的SEGMENT过渡变量
inttime_t=400;//数码管闪烁计数变量
unsignedcharbuffer_temp[8],play_adr[8],wendu_shi,wendu_ge;//分别为校正功能过渡变量数组、语音播报地址变量、温度十位类型过渡变量及温度个位类型过渡变量
//功能部分定义结束
main()
{
modecg=0;
displaycg=0;
BIT_LED=0;
date_ajflag=0;
ring_ajflag=0;
time_ajflag=0;
miaomiao_1=1;
miaomiao_2=1;
miaomiao_3=1;
miaomiao_4=1;
miaomiao_5=1;
miaomiao_play=1;//以上为各新定义变量的初始化
TEMP=TMOD;
TEMP=TEMP&0XF0;
TMOD=TEMP|0X01;
time0_times=-time0*fosc/12;
time0_h=(time0_times/256);
time0_1=(time0_times%256);
TH0=time0_h;TL0=time0_1;
initial_ds1302();
display_bit=0x01;
display_buffer[5]=0x05;
display_buffer[4]=0x03;
display_buffer[3]=0x09;
display_buffer[2]=0x05;
display_buffer[1]=0x01;
display_buffer[0]=0x02;
display_buffer1[7]=0x06;
display_buffer1[6]=0x00;
display_buffer1[5]=0x05;
display_buffer1[4]=0x00;
display_buffer1[3]=0x07;
display_buffer1[2]=0x01;
display_buffer1[1]=0x00;
display_buffer1[0]=0x02;
set_time();
ISD_Init();
dmsec
(1);
tmread();
TR0=EA=ET0=1;
do{
if(key1==0)
{
if(miaomiao_1){
modecg++;
modecg=modecg%2;//切换工作模式:
0:
显示模式;1:
校正、定闹模式
miaomiao_1=0;
if(displaycg==0&&modecg==1){
for(j=0;j<8;j++)
buffer_temp[j]=display_buffer[j];
}
if(displaycg==2&&modecg==1){
for(j=0;j<8;j++)
buffer_temp[j]=display_buffer1[j];
}
if(displaycg==1&&modecg==1){
ET0=1;//从主程序的温度显示进入定时中断
for(j=0;j<8;j++)
buffer_temp[j]=ring[j];
}
}
}
else
miaomiao_1=1;
if(key2==0)
{
if(miaomiao_2){
displaycg++;
displaycg=displaycg%3;//切换显示部分:
0:
时钟;1:
温度/定闹;2:
日历
miaomiao_2=0;
if(displaycg==0&&modecg==1){
for(j=0;j<8;j++)
buffer_temp[j]=display_buffer[j];//每次切换对buffer_temp[]赋予当前的变量值
}
if(displaycg==2&&modecg==1){
for(j=0;j<8;j++)
buffer_temp[j]=display_buffer1[j];
}
if(displaycg==1&&modecg==1){
for(j=0;j<8;j++)
buffer_temp[j]=ring[j];
}
}
}
else
miaomiao_2=1;
//温度显示时需关闭定时器
if(displaycg==1&&modecg==0){
ET0=0;//进入温度显示时应关闭定时中断
tmdisplay();
}
else
ET0=1;
if(key5==0)
{
if(miaomiao_5){
if((ring[0]==display_buffer[0]&&ring[1]==display_buffer[1]&&ring[2]==display_buffer[2]&&ring[3]==display_buffer[3]&&ring[5]==1)&&modecg==0&&displaycg==0)
ring[5]=0;//关闭闹钟
else
reset_time();//校正确认
miaomiao_5=0;
}
}
else
miaomiao_5=1;
//整点报温报时功能;
if((display_buffer[2]==0&&display_buffer[3]==0&&display_buffer[4]==0&&display_buffer[5]==0)&&modecg==0&&displaycg==0){
if(miaomiao_play==1){
tmread();
miaomiao_play=0;
//报时部分
ISD_SET_PLAY(73,0,95,0);
if(display_buffer[0]==0){
dmsec(500);
play_adr[1]=get_address(display_buffer[1]);
ISD_SET_PLAY(play_adr[1],0,play_adr[1]+5,0);
dmsec(800);
ISD_SET_PLAY(96,0,104,0);
}
if(display_buffer[0]==1&&display_buffer[1]==0){
dmsec(500);
ISD_SET_PLAY(61,0,66,0);
dmsec(800);
ISD_SET_PLAY(96,0,104,0);
}
if(display_buffer[0]==2&&display_buffer[1]==0){
dmsec(500);
ISD_SET_PLAY(159,0,164,0);
dmsec(800);
ISD_SET_PLAY(96,0,104,0);
}
if(display_buffer[0]==1&&display_buffer[1]!
=0){
dmsec(500);
ISD_SET_PLAY(61,0,66,0);
dmsec(700);
play_adr[1]=get_address(display_buffer[1]);
ISD_SET_PLAY(play_adr[1],0,play_adr[1]+5,0);
dmsec(600);
ISD_SET_PLAY(96,0,104,0);
}
if(display_buffer[0]==2&&display_buffer[1]!
=0){
dmsec(500);
ISD_SET_PLAY(159,0,164,0);
dmsec(700);
play_adr[1]=get_address(display_buffer[1]);
ISD_SET_PLAY(play_adr[1],0,play_adr[1]+5,0);
dmsec(600);
ISD_SET_PLAY(96,0,104,0);
}
//报温部分
dmsec(1400);
ISD_SET_PLAY(125,0,144,0);
if(wendu_shi==0){
dmsec(800);
play_adr[1]=get_address(wendu_ge);
ISD_SET_PLAY(play_adr[1],0,play_adr[1]+5,0);
dmsec(700);
ISD_SET_PLAY(119,0,124,0);
}
if(wendu_shi==1&&wendu_ge==0){
dmsec(800);
ISD_SET_PLAY(61,0,66,0);
dmsec(700);
ISD_SET_PLAY(119,0,124,0);
}
if(wendu_shi==2&&wendu_ge==0){
dmsec(800);
ISD_SET_PLAY(159,0,164,0);
dmsec(700);
ISD_SET_PLAY(119,0,124,0);
}
if(wendu_shi==3&&wendu_ge==0){
dmsec(800);
ISD_SET_PLAY(165,0,170,0);
dmsec(700);
ISD_SET_PLAY(119,0,124,0);
}
if(wendu_shi==1&&wendu_ge!
=0){
dmsec(800);
ISD_SET_PLAY(61,0,66,0);
dmsec(600);
play_adr[1]=get_address(wendu_ge);
ISD_SET_PLAY(play_adr[1],0,play_adr[1]+5,0);
dmsec(500);
ISD_SET_PLAY(119,0,124,0);
}
if(wendu_shi==2&&wendu_ge!
=0){
dmsec(800);
ISD_SET_PLAY(159,0,164,0);
dmsec(600);
play_adr[1]=get_address(wendu_ge);
ISD_SET_PLAY(play_adr[1],0,play_adr[1]+5,0);
dmsec(500);
ISD_SET_PLAY(119,0,124,0);
}
if(wendu_shi==3&&wendu_ge!
=0){
dmsec(800);
ISD_SET_PLAY(165,0,170,0);
dmsec(600);
play_adr[1]=get_address(wendu_ge);
ISD_SET_PLAY(play_adr[1],0,play_adr[1]+5,0);
dmsec(500);
ISD_SET_PLAY(119,0,124,0);
}
}
}
else{
if(display_buffer[2]==5&&display_buffer[3]==9)//增加此判定条件是为了解决语音重复播报问题
miaomiao_play=1;
}
}while
(1);
}
voidtime0_int(void)interrupt1
{
TH0=time0_h;
TL0=time0_1;
read_time();
if(displaycg==2&&modecg==0)
read_date();
//闪烁功能
if(ring[0]==display_buffer[0]&&ring[1]==display_buffer[1]&&ring[2]==display_buffer[2]&&ring[3]==display_buffer[3]&&ring[5]==1)
{
if(time_t>200){
BIT_LED=0x00;
SEGMENT=0x00;
time_t--;
}
else{
display();
time_t--;
if(time_t==0)
time_t=400;
}
}
else{
display();
}
}
//时间部分开始
unsignedcharget_code(unsignedchari)
{
unsignedcharp;
switch(i){
case0:
p=0x3F;break;
case1:
p=0x06;break;
case2:
p=0x5B;break;
case3:
p=0x4F;break;
case4:
p=0x66;break;
case5:
p=0x6D;break;
case6:
p=0x7D;break;
case7:
p=0x07;break;
case8:
p=0x7F;break;
case9:
p=0x67;break;
case10:
p=0x77;break;
case11:
p=0x7C;break;
case12:
p=0x39;break;
case13:
p=0x5E;break;
case14:
p=0x79;break;
case15:
p=0x71;break;
default:
break;
}
return(p);
}
unsignedcharget_address(unsignedchark)
{
unsignedcharp;
switch(k){
case0x00:
p=1;break;
case0x01:
p=7;break;
ca