自动打铃控制器.docx

上传人:b****7 文档编号:26351558 上传时间:2023-06-18 格式:DOCX 页数:38 大小:328.24KB
下载 相关 举报
自动打铃控制器.docx_第1页
第1页 / 共38页
自动打铃控制器.docx_第2页
第2页 / 共38页
自动打铃控制器.docx_第3页
第3页 / 共38页
自动打铃控制器.docx_第4页
第4页 / 共38页
自动打铃控制器.docx_第5页
第5页 / 共38页
点击查看更多>>
下载资源
资源描述

自动打铃控制器.docx

《自动打铃控制器.docx》由会员分享,可在线阅读,更多相关《自动打铃控制器.docx(38页珍藏版)》请在冰豆网上搜索。

自动打铃控制器.docx

自动打铃控制器

课程设计

课程单片机原理及应用课程设计

题目自动打铃控制器

院系电子科学学院

专业班级

学生姓名

学生学号

指导教师

2011年3月18日

1引言2

2设计要求3

2.1总体设计思想

3.硬件电路设计思想.

3.1PCB图

4.程序流程图

5.

3

3

5

5

程序清单6

6元器件明细表26

7.调试过程27

8.参考文献27

1引言

单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把

一个计算机系统集成到一个芯片上。

相当于一个微型的计算机,和计算机相比,单片机只缺少了I/O设备。

概括的讲:

一块芯片就成了一台计算机。

它的体积小、质量轻、价格便宜、为学习、应用和开发提供了便利条件。

同时,学习使用单片机是了解计算机原理与结构的最佳选择。

单片机内部也用和电脑功能类似的模块,比如CPU内存,并行总线,

还有和硬盘作用相同的存储器件,不同的是它的这些部件性能都相对我们的家用电脑弱很多,不过价钱也是低的,一般不超过10元即可用它来做一些

控制电器一类不是很复杂的工作足矣了。

我们现在用的全自动滚筒洗衣机、排烟罩、VCD等等的家电里面都可以看到它的身影!

它主要是作为控制部分的核心部件。

可以说,二十世纪跨越了三个“电”的时代,即电气时代、电子时代和

现已进入的电脑时代。

不过,这种电脑,通常是指个人计算机,简称PC机。

它由主机、键盘、显示器等组成。

还有一类计算机,大多数人却不怎么熟悉。

这种计算机就是把智能赋予各种机械的单片机(亦称微控制器)。

顾名思义,

这种计算机的最小系统只用了一片集成电路,即可进行简单运算和控制。

因为它体积小,通常都藏在被控机械的“肚子”里。

它在整个装置中,起着有如人类头脑的作用,它出了毛病,整个装置就瘫痪了。

现在,这种单片机的使用领域已十分广泛,如产品未使用单片机或其它可编程逻辑器件上智能控制、实时工控、通讯设备、导航系统、家用电器等。

各种产品一旦用上了单片机,就能起到使产品升级换代的功效,常在产品名称前冠以形容词——“智能型”,如智能型洗衣机等。

今天我利用单片机控制学校的打铃系统,下面是我的设计思路

2设计要求

用单片机、数字温度传感器、实时时钟芯片、点阵液晶模块设计一个简易的

自动打铃系统,系统工作时,在LCD显示器的第一行用16X16点阵的汉字显示“自动打铃系统”,第二行显示当前时间,第三行显示当前温度值,在随后的四行显示一页最近的打铃时间,即将要打铃的时间用黑底白字显示,如果该页的最后一个时间打过铃后,自动翻页,将下一页的4个打铃时间显示出来;用户可以通过按键修改当前时间或打铃时间;用户可以通过按指定键获知各键的功能。

2.1总体设计思想

用TG12864B®晶模拟块设计一个简易的自动打铃系统,系统正常工作是,在LCD显示器的第一行用16*16的点阵的汉字显示“自动打铃系统”,第二行显示当前时间,第三行显示当前温度,在随后的四行显示一页的最近的打铃时间,即将要打铃的时间用黑底白字显示,如果该页的最后一个时间打过铃后,自动翻页,将下一个的4个打铃时间显示出来;用户可以通过按键修改当前时间或打铃时间。

利用KDOW键进入HELP功能;打铃时用音乐声代替。

3.硬件电路设计思想

分析:

自动打铃系统的本质就是电子钟,如果当前的时间与打铃时间相同,就控制蜂鸣器发出打铃声。

虽然利用单片机本身的定时器也能够实现走时功能,但精度不够高,程序也比较复杂,而实时时钟芯片PCF8563能够轻松的解决以上问题。

由于打铃时间可能多达数十个,如果用户设置完打铃时间后将其保存在片内

RAM中,一旦断电或重新启动,打铃时间又必须重新设置,为此可利用串行E2PROM器件24C02来保存打铃时间。

另外用4个按键来设置当前时间和打铃时间。

系统正常工作时,按KDOW键进入帮助菜单;按KSET键进入当前时间的设置,长按KSET键则进入打铃时间的设置;进入设置方式后,按KSET键移动光标,用黑底白字指示当前正在修改的时、分、秒,KINC,KDEC键分别对当前的修改对象加、减1如果是修改的打铃时间,用KDOW/键对下一个打铃时间进行设置,长按KSET键退出当前时间或打铃时间的设置方式,回到正常状态。

电子钟是一个以“分”,“秒”显示于人的视觉器官的计时装置。

它的计时周期为24小时,显示满刻度为23时59分59秒,另外应有校时功能和一些显示星期、报时、停电查看时间等附加功能。

因此,一个基本的数字钟电路主要由译码显示器、“时”,“分”,“秒”,“星期”计数器、校时电路、报时电路和振荡器组成。

干电路系统由秒信号发生器、“时、分、秒、星期”计数器、译码器及显示器、校时电路、整点报时电路组成。

秒信号产生器是整个系统的时基信号,它直接决定计时系统的精度,一般用石英晶体振荡器加分频器来实现。

将标准秒信号送入“秒计数器”,“秒计数器”采用60进制计数器,每累计60秒发出一个“分脉冲”信号,该信号将作为“分计数器”的时钟脉冲。

“分计数器”也采用60进制计数器,每累计60分钟,发出一个“时脉冲”信号,该信号将被送到“时计数器”。

“时计数器”采用24进制计时器,可实现对一天24小时的累计。

每累计24小时,发出一个“星期脉冲”信号,该信号将被送到“星期计数器”,“星期计数器”采用7进制计时器,可实现对一周7天的累计。

译码显示电路将“时”、“分”、“秒”、“星期”计数器的输出状态送到七段显示译码器译码,通过七位LED七段显示器显示出来。

整点报时电路时根据计时系统的输出状态产生一脉冲信号,然后去触发一音频发生器实现报时。

校时电路时用来对“时”、“分”、“秒”、“星期”显示数字进行校对调整的。

晶振用一种能把电能和机械能相互转化的晶体在共振的状态下工作,以提供稳定,精确的单频振荡。

在通常工作条件下,普通的晶振频率绝对精度可达百万分之五十。

高级的精度更高。

有些晶振还可以由外加电压在一定范围内调整频率,称为压控振荡器(VCO)

晶体振荡器电路给数字钟提供一个频率稳定准确的32768Hz的方波信号,此外还有一校正电容可以对温度进行补偿,以提高频率准确度和稳定度,使稳定度优于10-4,可保证数字

钟的走时准确及稳定,下面我画出硬件电路图,见附录1。

3.1PCB图

见附录2。

4.程序流程图

(开始)

 

初始化PCF8563

允许定是、报警中断

写入当前时间显示当前温度显示1页最近打铃时间确定下一个要打铃的时间将其设为PCF8563的报警时间

将其以黑—

是否结束?

文件I2C.C的清单如下:

#inelude

#ineludevintrins.h>

#defineucharunsignedchar

#definedelay1us()_nop_()

#definedelay5us()_nop_();_nop_();_nop_();_nop_();_nop_()

sbitSDA=PM7;//P1.1模拟I2C总线的SDA

sbitSCL=P1A6;//P1.0模拟I2C总线的SCL

bitack_mk;//应答标志位,有应答为1,无应答为0

voidStart()/始信号/产生起

起始条件建立时间大于4.7us,故延时5us

//SCL为高时,SDA由高变低,发送起始信号延时5us

//SCL变低,准备发送或接收数据

voidStop()//产生停止信号

{

SDA=0;//将SDA青0,SCL置1

SCL=1;

delay5us();//结束条件建立时间大于4.7us,所以延时5us

SDA=1;//当SCL为高电平时,SDA由低变高,产生结束信号

delay5us();//延时5us

SCL=0;

}

voidAck(void)//产生应答信号

{

SDA=0;//SDA先清0,发应答信号

SCL=1;//SCL由低变高,产生一个时钟

delay5us();//延时5us

SCL=0;//时钟线SCL恢复到低电平,以便继续接收

}

voidNAck(void)

{

SDA=1;//SDASCL=1;//SCLdelay5us();

//产生非应答信号

先置1,发非应答信号

由低变高,产生一个时钟//延时5us

SCL=0;//时钟线SCL清恢复到低电平,以便继续接收

voidSendByte(ucharc)//{

向I2C总线发送一个字节

ucharn;

//一字节为8位,循环8次

//根据发送位将数据线SDA置为1或清0

置SCL为高,通知被控从机开始接收数据位延时5us

变低电平,准备发送下一位数据将下一位要发送的数据移到最高位,先高后低

延时5us一字节发送完后释放数据线,准备接收应答位

由低变高,产生一个时钟,读取SDA的状态延时5us

//如果SDA=1则发送失败,将ack_mk清0

否则发送成功,将ack_mk置1

SCL=0;//SCL变低

}

ucharRcvByte(){

ucharc;

//接收一个字节

ucharn;

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

{SDA=1;//

//一字节为8位,循环8次

置数据线SDA为输入方式,进入接收方式

SCL=1;//SCL由低变高,产生一个时钟

 

if(SDA==0)

c=c&0x7f;

//根据数据线SDA勺状态,将c的最高位清0或置1

else

 

c=c|0x80;

c=_crol_(c,1);//SCL=0;//

将c循环左移一位,先接收高位,后接收低位

时钟线SCL清0

}return(c);

/*从指定器的的子地址开始写入多个字节*/bitISendStr(ucharsla,ucharsuba,uchar*s,ucharno)

{

uchari;

 

for(i=0;i

{

SendByte(*s);/*发送数据*/if(ack_mk==0)return(0);

s++;

}

Stop();/*结束总线*/

return

(1);

}

/*从指定器的的子地址开始读取多个字节*/

bitIRcvStr(ucharsla,ucharsuba,uchar*s,ucharno){

uchari;

 

发送数据*/发送就答位*/

发送非应位*/

结束总线*/

for(i=0;i

{

*s=RcvByte();/*

Ack();/*s++;

}

*s=RcvByte();

NAck();/*

Stop();/*

return

(1);

文件LCD12864IO.C的清单如下:

#inelude

#ineludevintrins.h>

#include

#defineucharunsignedchar#defineuintunsignedint

sbitLCD_RST=P3A7;//液晶屏复位脚定义

sbitDI=P3A4;//DI引脚定义

sbitRW=P3A5;〃RW引脚定义

sbitCS=P3A3;//片选信号定义

sbitEN=P3A6;//使能信号定义

sbitRDY=P0A7;//对应状态信息中的BF位

sfr_LCD=0x80;〃P0口作为数据口

#defineLCD_DISPON0x3f//打开LCD显示

#defineLCD_STARTROW0xc0

//设置起始行,可用LCD_STARTROW+置起始行(x<64)

#defineLCD_ADDRSTRYxb8

//页起始地址,可用LCD_ADDRSTRX设置当前页(x<8)

#defineLCD_ADDRSTRXx40

//列起始地址,可用LCD_ADDRSTRY设置当前列(x<64)#defineCS10//左半屏选择

#defineCS21//右半屏选择

//命令字emd送左半屏(port=0)/右半屏(port=1)命令口voidLCD_WrCmd(bitport,ucharcmd)

{EN=0;

CS=port;

DI=0;//选择命令寄存器

RW=0;

EN=1;

LCD=cmd;//命令码送总线

EN=0;

}

//数据wrdata送左半屏(port=0)/右半屏(port=1)数据口voidLCD_WrDat(bitport,ucharwrdata)

{EN=0;

CS=port;

DI=1;//选择命令寄存器

RW=0;

EN=1;

LCD=wrdata;//命令码送总线

EN=0;

}

//以filldata充填液晶屏

voidLCD_DispFill(ucharfilldata){ucharx,y;

LCD_WrCmd(CS1丄CD_STARTROW)设置左半屏显示起始行为0

循环充填8页

设置左半屏页地址

设置左半屏列地址

设置右半屏页地址设置右半屏列地址

LCD_WrCmd(CS2,LCD_STARTR0W)设置右半屏显示起始行为0

for(y=0;y<8;y++)//

{LCD_WrCmd(CS1,LCD_ADDRSTRY+y);//LCD_WrCmd(CS1,LCD_ADDRSTRX);//LCD_WrCmd(CS2,LCD_ADDRSTRY+y);//LCD_WrCmd(CS2,LCD_ADDRSTRX);//

for(x=0;x<64;x++)//充填每页的64个单元(列)

{LCD_WrDat(CS1,filldata);

LCD_WrDat(CS2,filldata);

}

}

}

//液晶模块初始化

voidLCD_DispIni(void)

{uinti;

LCD_RST=0;//复位驱动芯片

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

LCD_RST=1;

LCD_WrCmd(CS1,LCD_DISPON);//打开显示

LCD_WrCmd(CS1,LCD_STARTROW);//设置显示起始行为0

LCD_WrCmd(CS2,LCD_DISPON);

LCD_WrCmd(CS2,LCD_STARTROW);

LCD_DispFill(00);//清屏

LCD_WrCmd(CS1,LCD_ADDRSTRY+0)/;/设置页(字符行)地址

LCD_WrCmd(CS1,LCD_ADDRSTRX+0)/;/设置列地址

LCD_WrCmd(CS2,LCD_ADDRSTRY+0);

LCD_WrCmd(CS2,LCD_ADDRSTRX+0);

}

//在液晶屏的cy(0-7)行、cx(0-15)列显示字符dispdata

voidLCD_DispChar(bitcolor,ucharcy,ucharcx,chardispdata)

{ucharcode*pch;

uchari;

bitport;

cy=cy&0x07;//参数过滤

cx=cx&0x0f;

pch=&ASCII_TAB[(dispdata-0X20)*5];//指向字符起始列的点阵码

if((cx&0x08)==0)//列号cx<8,在左半屏显示

{port=CS1;

i=cx<<3;

}

else

{port=CS2;

i=(cx&0x07)<<3;

}

LCD_WrCmd(port,LCD_ADDRSTRX+i);//设置当前列地址LCD_WrCmd(port,LCD_ADDRSTRY+cy);//设置当前页地址

//显示一列空格

//显示一列空格

//显示一列空格

//显示一列空格

{if(color==0)

LCD_WrDat(port,*pch);

else

LCD_WrDat(port,~*pch);

pch++;

}

if(color==0)

LCD_WrDat(port,0x00);else

LCD_WrDat(port,0xff);

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

if(color==0)

LCD_WrDat(port,0x00);

else

LCD_WrDat(port,0xff);

}

//在液晶屏的cy(0-7)行、cx(0-15)列显示字符disp_str

voidLCD_DispStr(bitcolor,ucharcy,ucharcx,char*disp_str)

{while(*disp_str!

='\0')

{cy=cy&0x07;//参数过滤

cx=cx&0x0f;

LCD_DispChar(color,cy,cx,*disp_str);//显示字符

disp_str++;//指向下一字符数据

cx++;

if(cx>15)cy++;//指向下一显示行

}

}

//在液晶屏的cy(0-3)行、cx(0-7)列显示汉字字符dispdatavoidLCD_DispHZ(ucharcy,ucharcx,uchardispdata)

{ucharcode*pdat;

uchari,s,page;

bitport;

cy=cy&0x03;//参数过滤

cx=cx&0x07;

//如果在左半屏显示

if((cx&0x04)==0){port=0;

s=cx<<4;

pdat=&HZTAB[dispdata*32];

{port=1;

s=(cx<<4)-64;

//求出该汉字在屏幕上的起始列

}

else

//求出该汉字在屏幕上的起始列

//在右半屏上显示

}for(page=0;page<2;page++)//每个汉字2页

{LCD_WrCmd(port,LCD_ADDRSTRX+s);//设置当前列地址LCD_WrCmd(port,LCD_ADDRSTRY+(cy<<1)+page);//设置当前页地址for(i=0;i<5;i++);

for(i=0;i<16;i++)//每个汉字16列

{LCD_WrDat(port,*pdat);//发送数据

pdat++;

for(i=0;i<5;i++);}

}

//在液晶屏的cy(0-3)行、cx(0-7)列显示汉字字符串disp_strvoidLCD_DispHZStr(ucharcy,ucharcx,uchar*disp_str){while(*disp_str!

=0xff)

{cy=cy&0x03;//参数过滤

cx=cx&0x07;

LCD_DispHZ(cy,cx,*disp_str);//显示汉字disp_str++;//指向下一汉字cx++;//列号加1if(cx>7)

{cy++;//指向下一显示行

cx=0;

}

}

}

voidHelp(void)

{

Help2();

while

(1)

{k=GetKey();if(k==KINC){

m++;

if(m%2==0){

Help2();}else

{

Help1();

}

}

elseif(k==KDOWN)

{

break;

}

}

}

bitreset(void)//初始化DS18B20

{biterr;

DQ=0;//在数据线上产生600us的低电平

delay15(40);

DQ=1;//数据线拉高

delay15(4);//延时60us

err=DQ;//读取数据线状态,err=0:

复位成功

delay15(18);//err=1:

复位失败return(err);

voidwrbyte(uchard)//{uchari;

dat=d;

for(i=8;i>0;i--)

{DQ=0;delay15

(1);

DQ=dat0;dat=dat>>1;delay15

(1);

DQ=1;

}

}

向DS18B2C写入一个字节

//循环写8位(先低位,后高位)//产生15us的负脉冲

//将当前数据位送数据线

//将下一位要写入的数据移到最低位

//延时15us

//数据线拉高,为写入下一位做准备

ucharrdbyte(void)//

{uchari;

dat=0;

for(i=8;i>0;i--)

{dat=dat>>1;

DQ=0;//

_nop_();

DQ=1;delay15

(1);//dat7=DQ;delay15(4);//}return(dat);

从DS18B20读取一个字节

//读出数据初值为0

//循环读8位(先低位,后高位)

//读出数据先右移一位

产生1us的负脉冲

//数据总线拉高

延时15us

//读取数据

延时,为读下一位做准备

voidlate()//延时700ms

{uchari;

for(i=0;i<200;i++)delay15(200);

}

voidgettemp(void)

{inttemp;ucharzf;ucharh,l;reset();wrbyte(0xcc);wrbyte(0x44);

//复位所有DS18B20//跳过ROM

//启动所有DS18B20专换

 

zf=0;

if(temp<0)

{zf=1;

temp=-temp;

求出温度的小数

//求出百位

//求出十位

//求出个位

late();reset();wrbyte(0xcc);wrbyte(0xbe);l=rdbyte();h=rdbyte();temp=h*256+l;

//延时750ms

//复位

//发跳过ROM命令

//发读暂存器命令

//读取温度低字节、高字节

//如果温度在0度以下//置负数标志//求补

}

dbuf[4]=dp[temp&0x0f]+0x30;//temp=temp>>4;

dbuf[0]=temp/100+0x30;

temp=temp%100;dbuf[1]=temp

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

当前位置:首页 > 总结汇报 > 其它

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

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