初B 何文涛Word格式文档下载.docx
《初B 何文涛Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《初B 何文涛Word格式文档下载.docx(41页珍藏版)》请在冰点文库上搜索。
3.2遥控调时模块程序14
3.3显示模块程序17
3.4其他模块程序及主程序22
第四章.系统测试、结果及分析25
4.1基本功能25
4.2发挥部分功能25
4.3操作说明26
心得体会27
参考文献27
附录、完整的系统原理图28
摘要
本系统主要由AVR单片机主控制模块、时钟模块、遥控调时及模式切换模块、显示模块、电机驱动模块,共5个模块组成。
通过电机驱动,使带有一列(25个)LED的旋转板快速旋转,然后通过编写程序控制Mega16芯片的输出来控制各个LED的亮灭,得到想要的显示内容。
红外遥控接收头收到的信号,接到Mega16的外部中断INT0,然后通过编写程序对收到的信号进行解码,用来调整时间和切换显示模式。
时间的调整是模拟真实时钟的方式,即秒针停,分针、时针转动。
显示模式有两种:
一种是模拟真实时钟的钟盘,显示时针、分针、秒针,另一种是用数字来显示当前的年月日。
本系统功能齐全,不仅实现了所有基本要求,而且实现了全部的拓展要求,使用方便、显示美观,可以作为家庭的实用时钟和精美摆设。
Abstract
Thissystemconsistsoffiveunits:
AVRMCUunit,clockunit,remotecontrollerunit.displayunitandmotordeviceunit.WegetthedisplaywewantfromthespinningboarddrivedbythemotorwithLEDscontrolledbytheMega16.
ThereceiverwhoreceivesthesignalisconnectedtotheportINT0,andthentheMCUwillchangethetimeoftheclockorthedisplaymodeaccordingtothesignal.
Thesystemhasperfectfuntions.Itrealizesalltheexpandingfuntionsbesiderealizingallthebasicones.What’smore,usingthecommonremotecontrollermakesitmoreeasyandconvenientforaverageuserstocontroltheclock.Itisnotonlyapracticalclockbutalsoabeautifuldecoration.
第一章.系统方案选择与论证
1.1设计要求
1.基本要求:
1)可以显示时针、分针、秒针,以及相应的刻度。
时钟可以正常工作。
2)时钟显示稳定清晰。
3)时间可以调整。
2.扩展要求:
1)增设定时指针,时针与定时指针重合则发声提示。
2)调节时间的时候,模拟真实时钟(秒针停,分针、时针动)
3)可以显示年月日(数字式或者模拟小表盘)
4)其他
1.2系统基本方案
根据题目要求,系统可以划分为电源模块、时钟模块、遥控调时模块、电机驱动模块、显示模块。
模块框图如图1.2所示。
为了实现各模块的功能,分别作了几种不同的设计方案,并进行了比较论证。
图1.2模块框图
1.2.1各个模块方案选择和论证
1.2.1.1时钟模块
根据设计要求,时钟模块必须实现年、月、日,时、分、秒的计算和记录,且可以从外部对时间的记录进行修改。
方案一:
采用ATMega16的定时/计数器中断做时钟,每隔一秒,秒的记录加一,当秒的记录达到60时,分加一,以此类推。
方案二:
采用时钟芯片DS1302,其为低功耗实时时钟,除了可以对年、月、日、周、日、时、分、秒进行计时,且具有闰年补偿等多种功能。
因为本系统主要是实现一个时钟的功能,对时钟的准度、年份的计算等要求较高,而且DS1302也较为便宜,因此,我们决定算用方案二。
1.2.1.2遥控调时及切换模式模块
根据设计要求,设计出来的作品应该可以对模拟时钟的时间进行调整并且可以切换显示模式。
这就必须与要旋转的带有LED的板上的控制芯片进行通信,要达到这一要求,我们想出了一下两个方案。
利用单片机之间的串口通信,在旋转板以外再用单片机做一个带有按键的调试模块,用串口通信把调时或切换显示模式信号传到旋转板上的单片机。
利用红外遥控器对时间进行调整。
这样只需在旋转板上安装一个接收器,然后利用旋转板上的单片机的外部中断,编写程序,对遥控信号进行解码,即可实现遥控调时及切换显示模式功能。
方案一需要额外多耗费一个单片机,而且其硬件的实现较为麻烦,方案二更加充分地利用了旋转板上的单片机,因此我们选用方案二。
1.2.1.3电机驱动模块
自备电池方式。
这种方式,就是在旋转板上安装电池,由电池供电。
一般是用两到三节7号电池。
这种方式的优点是:
(1)不用担心电压波动。
(2)也不存在机械磨损,不用担心接触不良之类问题的困扰。
这种方式的缺点是:
(1)很费电池,可能要经常更换电池。
(2)电池很重,一般的电机带不动,因此必须用很大很大的电机。
这也意味
了成本的上升。
机械传导供电方式,也就是采用滑环和电刷,通过机械接触传导电流。
(1)能够提供比较大的工作电流。
(1)有机械摩擦,会产生磨损。
因此要求滑环和电刷材料要耐磨,经得起
折腾。
另外,还得有足够的弹性,并且要耐锈,否则会导致接触不良。
(2)有机械阻力,因此要求电机有比较大一点的功率。
综合考虑各项因素之后,我们最终采用的是方案二,电机用的是恒速电机。
第二章.系统的硬件设计与实现
2.1系统硬件的基本部分
本系统要实现的是一个能稳定清晰显示时针、分针、秒针以及相应刻度,时钟可以正常工作而且时间可以调整,可以切换模式到显示年、月、日,模拟真实时钟调时情景的模拟时钟功能。
系统可以分为以下几个模块:
时钟模块、遥控调时及切换模式模块、显示模块、主控制模块。
2.2主要单元电路的设计
2.2.1时钟模块
本模块通过时钟芯片DS1302实现年、月、日,时、分、秒的计算和记录,除了可以对年、月、日、周、日、时、分、秒进行计时,且具有闰年补偿等多种功能。
该模块电路图如下:
DS1302是DALLAS公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31字节静态RAM,通过简单的串行接口与单片机进行通信,实时时钟/日历电路提供秒分时日日期月年的信息,每月的天数和闰年的天数可自动调整,时钟操作可通过AM/PM指示决定采用24或12小时格式,DS1302与单片机之间能简单地采用同步串行的方式进行通信仅需用到三个口线通信,DS1302工作时功耗很低,保持数据和时钟信息时功率小于1mW,D,,双电源管脚用于主电源和备份电源供应,Vcc2为可编程涓流充电电源附加七个字节存储器,它广泛应用于电话、传真、便携式仪器以及电池供电的仪器仪表等。
2.2.2遥控调时及切换模式模块
本模块红外遥控器发射信号,利用旋转板上的单片机的外部中断,编写程序对接收头接收到的信号进行解码和做出相应的调时或者切换显示模式的反应,实现对模拟时钟的时间进行调整和切换显示的模式。
R35与C10用于减少电刷供电对接受头的影响。
因为电刷供电的噪声较大,此设计非常重要。
2.2.3显示模块
本模块通过用恒速电机驱动带有一列(25个)贴片LED的旋转板快速旋转,并通过板上的单片机控制各个LED的亮灭,利用人肉眼的视觉暂留原理,做出一种模拟时钟钟盘的效果,并且可以通过遥控切换模式,使钟盘从显示时针、分针、秒针的位置到显示年月日。
本模块电路图如下:
LED2-9为IO口独立连接,分别由PA0-PA7连接,用于显示8*8点阵字形。
与其他的红色LED不同,LED1&
25为绿色的LED,自启动后就会一直亮着,起到钟面的边框作用。
剩下的LED用作指针显示。
2.2.4主控制模块
本模块的核心是旋转板上的ATMega16单片机,其主要功能为控制并协调各个模块的工作。
指针板上有一个霍尔传感器,在外壳的对应位置安装了一个磁钢。
指针板每旋转一周,霍尔传感器就会经过一次磁钢位置,并感应到信号。
这个信号被称为“过零信号”。
有了这个信号,CPU就可以在旋转的过程中实时检测计算指针板的角度位置。
并根据指针板所处的不同位置,点亮相应的LED,利用人眼的视觉暂留效应,形成完整的显示画面。
通过检测两次过零信号的时间间隔,就可以计算出电机转速,或者指针旋转一周的时间。
把该时间等分为180份,即可求得每个显示列的位置。
这样,就不必再去对电机进行匀速控制了。
为了实现主控单元的快速反应及减少旋转板的重量,控制芯片选用贴片ATMAL16。
为了指针显示的方便,实行了某些IO口对多盏LED的控制。
但此举将只能显示8*8的字模,不过设计时考虑到,越到旋转板的圆心字模的变形会越厉害。
因此我们实行了某些IO口对多盏LED的控制方案。
2.2.5电机及供电模块
电机及供电模块可谓此作品的重难点,我们选择了机械式电刷供电。
电机方面,我们选择了既便宜又好用的录音机电机,录音机电机为恒速电机,只要供电稳定,就可实现转速稳定。
虽然电机不恒速与本作品也能正常显示,但是如果电机恒速可以极大地减少画面的抖动。
下图为电路图及实物图:
D4用于将LED与主控模块供电的隔离,三个电容用于应对电刷供电不稳。
第3章.系统的软件设计
3.1时钟模块程序
由于设计选用的是强大的ds1302时钟芯片,因而在此模块的算法所费的功夫不多。
只要理解ALMEL16如何通过三个io口对其进行控制并灵活应用即可。
最终通过调用ds1302_read_time()子函数进行读当前时间,调用ds1302_write_time()子函数进行修改当前时间。
所有的时间值记录于
unsignedcharyear=10,month=5,day=15,week=6,hour=10,minute=55,second=20
这七个变量当中。
//========1302函数============================
#defineucharunsignedchar
#defineuintunsignedint
//=============定义接口=========================//
#defineds1302_rstPB4
#defineds1302_ioPB3
#defineds1302_sclkPB2
//====================配置端口的输入、输出和高低电平==================//
#defineset_ds1302_rst_ddr()DDRB|=1<
<
ds1302_rst
#defineset_ds1302_rst()PORTB|=1<
#defineclr_ds1302_rst()PORTB&
=~(1<
ds1302_rst)
#defineset_ds1302_io_ddr()DDRB|=1<
ds1302_io
#defineclr_ds1302_io_ddr()DDRB&
ds1302_io)
#defineset_ds1302_io()PORTB|=1<
#defineclr_ds1302_io()PORTB&
#definein_ds1302_io()PINB&
(1<
#defineset_ds1302_sclk_ddr()DDRB|=1<
ds1302_sclk
#defineset_ds1302_sclk()PORTB|=1<
#defineclr_ds1302_sclk()PORTB&
ds1302_sclk)
//========寄存器地址宏定义========================//
#defineds1302_sec_reg0x80
#defineds1302_min_reg0x82
#defineds1302_hr_reg0x04
#defineds1302_date_reg0x86
#defineds1302_month_reg0x88
#defineds1302_day_reg0x8a
#defineds1302_year_reg0x8c
#defineds1302_control_reg0x8e
#defineds1302_charger_reg0x90
#defineds1302_clkburst_reg0xbe
unsignedcharyear=10,month=5,day=15,week=6,hour=10,minute=55,second=20;
//这7个变量缓存所有时间信息,读取时间后,访问之即获得时间;
修改时间前,要先把时间缓存进这几个变量
//================向指定地址的寄存器写入数据==================//
voidds1302_write(ucharreg,uchardata)
{
uchari=0;
ucharl,h;
l=data%10;
h=data/10;
data=h*16+l;
//预处理
set_ds1302_io_ddr();
asm("
nop"
);
//插入延时、保证电平宽度
clr_ds1302_rst();
asm("
clr_ds1302_sclk();
//拉低时钟
set_ds1302_rst();
for(i=8;
i>
0;
i--)//写地址
{
if(reg&
0x01)set_ds1302_io();
//写高电平
elseclr_ds1302_io();
//写入低电平
asm("
set_ds1302_sclk();
//拉高时钟
clr_ds1302_sclk();
reg>
>
=1;
//移位
}
i--)//写数据
if(data&
data>
clr_ds1302_rst();
clr_ds1302_io_ddr();
}
//=================读出指定地址寄存器的数据==========//
uchards1302_read(ucharreg)
uchardata=0;
reg+=1;
//读标志
elseclr_ds1302_io();
set_ds1302_sclk();
clr_ds1302_sclk();
reg>
i--)//读出数据
data>
if(in_ds1302_io())data|=0x80;
}
l=data&
0x0f;
//l存放time的低4位,即个位
h=(data>
4)&
//h存放time的高4位,即十位
data=h*10+l;
return(data);
}
//****************查忙*************************
ucharcheck_ds1302(void)
ds1302_write(ds1302_control_reg,0x80);
if(ds1302_read(ds1302_control_reg)==0x80)return1;
return0;
//****************读出当前时间****************
voidds1302_read_time(void)
a[0]=year=ds1302_read(ds1302_year_reg);
//年
a[1]=month=ds1302_read(ds1302_month_reg);
//月
a[2]=day=ds1302_read(ds1302_date_reg);
//日
a[3]=week=ds1302_read(ds1302_day_reg);
//周
a[4]=hour=ds1302_read(ds1302_hr_reg);
//时
a[5]=minute=ds1302_read(ds1302_min_reg);
//分
a[6]=second=ds1302_read(ds1302_sec_reg);
//秒
//****************修改时间*********************
voidds1302_write_time(void)
ds1302_write(ds1302_control_reg,0x00);
//关闭写保护
ds1302_write(ds1302_sec_reg,0x80);
//暂停
ds1302_write(ds1302_charger_reg,0xa9);
//涓流充电
ds1302_write(ds1302_year_reg,year);
ds1302_write(ds1302_month_reg,month);
//月
ds1302_write(ds1302_date_reg,day);
ds1302_write(ds1302_day_reg,week);
ds1302_write(ds1302_hr_reg,hour);
ds1302_write(ds1302_min_reg,minute);
ds1302_write(ds1302_sec_reg,second);
ds1302_write(ds1302_control_reg,0x80);
//打开写保护
3.2遥控调试模块程序
遥控采用普通遥控器发射编码,并用hs0038接收。
系统采用单片机进行解码,将接收到的信号接到单片机的INT1中断接口。
遥控器发的信号分为三部分:
前导码,16位用户码,16位操作码。
当检测到前导码后,进入INT1中断,然后进行解码,分别检测高低电平的持续时间,从而判断是0还是1,然后记入一个变量。
我们只取用第三个8位码,就是控制码的原码,然后退出中断。
送给系统进行相应的操作。
注意的是,在退出中断之前必须自己进行软件对中断标志位进行清零(GIFR|=BIT(6);
)。
//=======================TC1遥控计数========================//
voidTC1_init()
{
TCCR1B=0X02;
TCNT1=0;
unsignedintcode[4],receive=0,p,c;
//===================遥控解码=========================//
voidjiema()
unsignedintt,data,i,data3;
for(t=0;
t<
4;
t++)
{
for(i=0;
i<
8;
i++)
data=data>
1;
while((PIND&
0x04)==0X00);
TC1_init();
while((PIND&
0x04)==0X04);
TCCR1B=0;
data3=TCNT1;
if(data3>
500&
&
data3<
1200){data|=0x00;
if