STM8单片机课程设计报告闹钟+定时器解析.docx

上传人:b****6 文档编号:5103703 上传时间:2022-12-13 格式:DOCX 页数:22 大小:310.69KB
下载 相关 举报
STM8单片机课程设计报告闹钟+定时器解析.docx_第1页
第1页 / 共22页
STM8单片机课程设计报告闹钟+定时器解析.docx_第2页
第2页 / 共22页
STM8单片机课程设计报告闹钟+定时器解析.docx_第3页
第3页 / 共22页
STM8单片机课程设计报告闹钟+定时器解析.docx_第4页
第4页 / 共22页
STM8单片机课程设计报告闹钟+定时器解析.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

STM8单片机课程设计报告闹钟+定时器解析.docx

《STM8单片机课程设计报告闹钟+定时器解析.docx》由会员分享,可在线阅读,更多相关《STM8单片机课程设计报告闹钟+定时器解析.docx(22页珍藏版)》请在冰豆网上搜索。

STM8单片机课程设计报告闹钟+定时器解析.docx

STM8单片机课程设计报告闹钟+定时器解析

课程设计内容与要求

课程设计目的:

1、巩固和加深对单片机原理知识的理解和运用。

2、进一步提高学生综合运用所学知识的能力。

3、培养学生综合分析问题、发现问题和解决问题的能力

基本要求:

1)显示时间和日期

2)可设置多个闹钟

3)可以调整时间

扩展功能:

1)按键复用共有六个按键,每个按键在不同模式下有不同的功能。

2)秒表功能进入秒表界面后,再按一下就秒表开始计时,再按一下秒表停止。

3)省电模式在每天00:

00会自动进入省电模式,8个数码管会自动关闭,到5:

00时会自动退出省电模式;也可以手动进入和退出省电模式。

4)查看/删除闹钟查看闹钟时间为五秒,五秒内按键无动作则自动退出。

器件介绍

本次设计主要用到的硬件有:

1、51实验板1块

2、stm8s105c6开发板1快

51实验板:

主要用到实验板上的硬件有:

1)两个四位一体的共阴LED数码管,电路图如下:

 

2)两个74HC573的锁存芯片:

3)8个独立按键,用了其中6个

 

5)一个蜂鸣器:

Stm8s105c6开发板:

总共有48个引脚,本设计共用引脚20个引脚。

PB0~PB7和PE6~PE7用于数码管显示控制,PD0~PD5用于键盘输入,PD6、PE0、PE3用于LED指示灯控制。

PD7用于蜂鸣器控制。

 

设计方案

本次设计采用51实验板和stm8s105c6开发板来完成,没有做实物。

显示电路采用8个共阳数码管显示;控制按键采用六个独立按键,每一个按键都有复用功能;闹钟提醒采用蜂鸣器;外加四个不同颜色的LED发光二极管,当进入相应功能模式时对应的指示灯就会亮。

1、键盘设计:

在键盘电路中,使用的是6个独立键盘。

键盘在源程序中的功能安排如下:

1)当扫描到有键盘按下时,设置相应标志位,然后延时一定时间消抖。

2)键盘的设置键盘表面如图:

 

 

其中各键设置为:

(待机状态:

正常的时间显示模式)

待机状态下是“设置闹钟”,在其他模式下是“递增功能”

待机状态下是“调整时间”,在其他模式下是“递减功能”。

待机状态下是“秒表功能”,在其他模式下是“左移功能”。

待机状态下是“查看/删除闹钟”,在其他模式下是“右移功能”

OK待机状态下是“切换显示”,在省电模式下是“退出功能”,在其他模式下是“确认功能”

Esc待机状态下是“省电模式”,在查看/删除闹钟模式下是“删除功能”,在其他模式下是“退出功能”

2、数码管显示:

采用按位扫描的动态显示方式。

3、其他设计:

定时器使用stm8s105c6中的Tim2定时器,每1ms产生一次溢出中断。

闹铃响的时间为15秒。

查看/删除闹钟模式下,5s内键盘无动作则自动退出。

每次按键按下后,会延时240ms,此时间内不会再对键盘进行扫描。

在每天00:

00会自动进入省电模式,8个数码管会自动关闭,到5:

00时会自动退出省电模式;也可以手动进入和退出省电模式。

4、设计思路:

 

 

 

是是

 

5、以下是部分程序:

//**************标志位************//

_Booloff;//省电模式

_Booltab;//切换显示模式

_Boolrun;//控制秒表

_Boolleft;//左移

_Boolright;//右移

_Boolset;//设置闹钟

_Booladjust;//调整时间

_Boolok;//确定

_Boolesc;//取消或删除

_Boolduan@PE_ODR:

7;//PE6作为段锁存

_Boolwei@PE_ODR:

6;//PE7作为位锁存

_Boolset_c@PE_ODR:

3;

_Booladjust_t@PE_ODR:

0;

_Boolcheck_clock@PD_ODR:

6;

_Boolc_alarm@PD_ODR:

7;

//*****************相关变量*******************//

unsignedcharmonth_day[]={31,28,31,30,31,30,31,31,30,31,30,31};

unsignedcharwei_ma[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//显示位码

unsignedcharduan_ma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共阴极显示段码

unsignedcharsec_duan_ma[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};

unsignedcharhour_[5],minute_[5],second_[5]={1,2,3,4,5};//用于秒表

unsignedcharsec_time[8];//用于秒表

unsignedcharclocks[5][8];//可存5个闹钟信息

unsignedchartimes[8];//存放当前时间

unsignedchardays[8];//存放当前日期

unsignedintT1=1000;//200x10ms=1s秒计算

unsignedintT2=0;//20x10ms=200ms

unsignedcharc=0;//用于记录闹钟个数

unsignedcharhour=8,minute=55,second;

unsignedcharmonth=12,day=12;intyear=2011;

unsignedchar*ud;//ud加减指针

unsignedcharlr;//记录指针所指位

charA,B,C,D,E,F,G,H,I,J,K,L;

intT3=0,T4=0;//其他定时,闹钟显示和蜂鸣器

intsec1,sec2;//用于秒表的变量

//********************函数声明************************//

unsignedcharleapyear(intb);//闰年判断

voidTIM2_initial(void);//初始化定时器

voidGPIO_initial(void);//初始化I/O引脚

voiddisplay(unsignedcharx[8]);//时间显示函数

voidtime_process(void);//时间处理函数

voidtimes_bi_duan_ma(unsignedchar,unsignedchar,unsignedchar);

voiddays_bi_duan_ma(int,unsignedchar,unsignedchar);

voidkeyscan(void);//键盘扫描函数

voidset_clock(void);//设置闹钟

voidadjust_times(void);//

voidclock_display(void);//闹钟显示函数

voidalarm(void);

voidsecond_clock(void);

//*************主函数*****************//

main()

{

GPIO_initial();

TIM2_initial();

leapyear(year);

while

(1)

{

time_process();

alarm();

if(T2==0)//消抖,延时100ms

keyscan();

if(hour==0&minute==0&second==0)

off=1;

if(hour==5&minute==0&second==0)

off=0;

if(set==0&adjust==0&left==0&right==0&ok==0&off==1)

{

PB_ODR=0xff;//不显示时间,省电模式

wei=1;

wei=0;

}

elseif(set==1&adjust==0)//设置闹钟模式

{

set_c=0;

set_clock();

}

elseif(set==0&adjust==1)//调整时间模式

{

adjust_t=0;

adjust_times();

}

elseif(left==1)//秒表模式

second_clock();

elseif(right==1)//查看/删除闹钟模式

{

check_clock=0;

clock_display();

}

elseif(tab==0)

{

times_bi_duan_ma(hour,minute,second);

display(times);//时间显示

}

elseif(tab==1)

{

days_bi_duan_ma(year,month,day);

display(days);

}

}

}

//**********************秒表函数***************************//

voidsecond_clock(void)

{

if(sec1==999)sec1=999;

sec_time[0]=0x00;

sec_time[1]=0x00;

sec_time[2]=0x00;

sec_time[3]=duan_ma[sec1/100];

sec_time[4]=duan_ma[sec1%100/10];

sec_time[5]=sec_duan_ma[sec1%10];

sec_time[6]=duan_ma[sec2/10];//小数位

sec_time[7]=duan_ma[sec2%10];//小数位

display(sec_time);

if(esc==1)

{

left=0;

run=0;

sec1=0;

sec2=0;

esc=0;

}

}

//**********************闹钟设置****************************//

voidset_clock(void)

{

unsignedchari,j;

display(times);

if(lr==0)ud=&G;//指针指向G

if(lr==1)ud=&H;

if(lr==3)ud=&I;

if(lr==4)ud=&J;

if(lr==6)ud=&K;

if(lr==7)ud=&L;

times[lr]=duan_ma[*ud];//*ud即是ud所指变量的当前值

if(ok==1)

{

hour_[c]=G*10+H;

minute_[c]=I*10+J;

second_[c]=K*10+L;

if(c==4)c=0;

elsec++;

set=0;

ud=0;

lr=0;

right=0;

left=0;

ok=0;

set_c=1;

}

}

//**********************校时函数****************************//

voidadjust_times(void)

{

if(ok==0)

{

display(days);

if(lr==0)ud=&A;

if(lr==1)ud=&B;

if(lr==3)ud=&C;

if(lr==4)ud=&D;

if(lr==6)ud=&E;

if(lr==7)ud=&F;

days[lr]=duan_ma[*ud];

}

if(ok==1)

{

display(times);

if(lr==0)ud=&G;

if(lr==1)ud=&H;

if(lr==3)ud=&I;

if(lr==4)ud=&J;

if(lr==6)ud=&K;

if(lr==7)ud=&L;

times[lr]=duan_ma[*ud];

}

if(esc==1&ok==1)

{

year=2000+A*10+B;

month=C*10+D;

day=E*10+F;

hour=G*10+H;

minute=I*10+J;

second=K*10+L;

ok=0;

esc=0;

lr=0;

ud=0;

adjust=0;

T1=100;

adjust_t=1;

}

}

//********************时间处理函数**************************//

voidtime_process(void)

{

if(second>=60)//秒到60,分钟加1

{

second=0;

minute++;

if(minute>=60)//分钟到60,小时加1

{

minute=0;

hour++;

if(hour>=24)//小时到24,回零

{hour=0;

leapyear(year);//闰、平年计算

if(day>=month_day[month-1])//是否到了每月的最后一天

{

day=1;

if(month>=12)

{

month=1;

year++;

}

elsemonth++;

}

elseday++;

}

}

}

}

//*******************时间数据的转换*************************//

voidtimes_bi_duan_ma(unsignedcharhour,unsignedcharminute,unsignedcharsecond)

{

G=hour/10;H=hour%10;

I=minute/10;J=minute%10;

K=second/10;L=second%10;

times[0]=duan_ma[G];//时//数据的转换,因我们采用数码管0~9的显示,将数据分开

times[1]=duan_ma[H];

times[2]=0x40;//加入"-"

times[3]=duan_ma[I];//分

times[4]=duan_ma[J];

times[5]=0x40;

times[6]=duan_ma[K];//秒

times[7]=duan_ma[L];

}

//*******************日期数据的转换************************///

voiddays_bi_duan_ma(intyear,unsignedcharmonth,unsignedcharday)

{

A=((year%100)/10);B=((year%100)%10);

C=month/10;D=month%10;

E=day/10;F=day%10;

days[0]=duan_ma[A];//年

days[1]=duan_ma[B];

days[2]=0x40;

days[3]=duan_ma[C];//月

days[4]=duan_ma[D];

days[5]=0x40;

days[6]=duan_ma[E];//日

days[7]=duan_ma[F];

}

//******************时间显示函数*******************************//

voiddisplay(unsignedchartime[8])

{

unsignedchara=0,i;

while(a<8)

{

PB_ODR=0x00;//确保清除之前的数据,防止重影

duan=1;

duan=0;

if((set==1|adjust==1)&a==lr&T1<=50)

PB_ODR=0xff;//指针所指的位闪烁

else

PB_ODR=wei_ma[a];

wei=1;

wei=0;

PB_ODR=time[a++];

duan=1;

duan=0;

for(i=100;i>0;i--);//延时

}

a=0;

}

//*********************查看/删除闹钟函数***************************//

voidclock_display(void)

{

unsignedchara=0,i;

times_bi_duan_ma(hour_[lr],minute_[lr],second_[lr]);

display(times);

if(esc==1)

{

esc=0;

for(i=0;i<8;i++)

hour_[lr]=0;

minute_[lr]=0;

second_[lr]=lr+1;

}

if(T3==0)right=0;//5s内键盘无输入,切换到原来的显示模式

}

//*******************键盘扫描函数***************************//

voidkeyscan(void)

{

T2=241;//延时241ms,消抖

if((PD_IDR&0x01)==0x00)//加或设置闹钟按键

{

if(set==1|adjust==1)//闹钟或校时模式下

{

if(*ud==9)

*ud=0;

else

(*ud)++;//ud所指的变量加1

}

else//正常显示模式下

{

set=1;

esc=0;

ok=0;

}

}

elseif((PD_IDR&0x02)==0x00)//减或调整时间

{

if(set==1|adjust==1)//闹钟或校时模式下

{

if(*ud==0)

*ud=9;

else

(*ud)--;//ud所指的变量减1

}

else//正常显示模式下

{

adjust=1;

esc=0;

ok=0;

}

}

elseif((PD_IDR&0x04)==0x00)//左移/查看闹钟

{

if(set==1|adjust==1)//闹钟或校时模式下

{

lr--;

if(lr==255)lr=7;

elseif(lr==5)lr=4;//跳过第3和6个数码管

elseif(lr==2)lr=1;

}

elseif(right==1)//查看闹钟模式下

{

T3=5000;

if(lr==0)

lr=4;

else

lr--;

}

elseif(left==1)run=run^1;//为1时秒表开始计时

else

{

left=1;

esc=0;

ok=0;

}

}

elseif((PD_IDR&0x08)==0x00)//右移/查看闹钟

{

if(set==1|adjust==1)//闹钟或校时模式下

{

lr++;

if(lr==8)lr=0;//跳过第3和6个数码管

elseif(lr==2)lr=3;

elseif(lr==5)lr=6;

}

elseif(right==1)//查看闹钟模式下

{

T3=5000;

if(lr==4)

lr=0;

else

lr++;

}

else

{

right=1;

T3=5000;

esc=0;

ok=0;

}

}

elseif((PD_IDR&0x10)==0x00)//确定

{

off=0;//退出省电模式

tab=tab^1;

if(ok==0)ok=1;

elseif(ok==1&adjust==1)esc=1;

}

elseif((PD_IDR&0x20)==0x00)//取消删除或进入省电模式

{

if(adjust==1|set==1)

{

set=0;

ok=0;

lr=0;

ud=0;

adjust=0;

set_c=1;

adjust_t=1;

check_clock=1;

}

elseif(set==0&adjust==0&left==0&right==0)

{

off=1;

ok=0;

}

elseesc=1;

}

else1;

}

调试过程

因为此次程序比较大,实现的功能比较多,所以从一开始我便一个功能一个功能的做,边做边调试,做完一个功能之后才做下一个。

第一次做数码管显示的时候就出现问题,8个数码管一直显示乱码。

当时我就把程序用原来的动态显示改为静态显示,可是还是不行。

于是我就再把8个数码管同时显示改为一个数码管显示,这下就可以了。

然后我又再把显示的位数慢慢增加,当增加到第5位的时候发现,乱码又来了,之后我又改用其他引脚,发现原来之前写的程序时没有错的,是因为芯片的一个引脚出问题了,不知道为什么,那个引脚总是高电平。

所以才导致了之前的乱码一直出来。

数码管调试好之后,其他的程序调试起来就顺利多了,在用到蜂鸣器的时候还遇到了一个问题。

因为之前课程设计做蜂鸣器电路的时候都是做成有源蜂鸣器,所以,给个电平就可以控制蜂鸣器的开和关。

但这次我在实验板上做,上面的蜂鸣器是无源的,要给一定1KHz以上频率的方波才可以响。

这个问题当时拖了很久都没解决,如果要产生1KHz的频率,那我必须修改内部时钟,这样会导致定时器无法正常工作,最后经过一番苦思终于想出了一个办法,就是把定时中断改为1ms一次,然后在定时中断中修改引脚的输出,这样就可以产生1KHz的方波信号了。

还有在控制功能指示灯的时候,一开始没注意选用了PE0~PE3引脚,结果出现两个指示灯总是不亮,刚开始还以为灯坏了,但换了其他灯还是一样,所以我就怀疑是引脚出问题了,但最后才发现不是引脚问题,而是PE1和PE2这两个引脚不可以初始化为推挽输出。

最后我

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 其它模板

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1