测控系统设备与仪器应用综合能力训练.docx
《测控系统设备与仪器应用综合能力训练.docx》由会员分享,可在线阅读,更多相关《测控系统设备与仪器应用综合能力训练.docx(21页珍藏版)》请在冰豆网上搜索。
测控系统设备与仪器应用综合能力训练
测控系统、设备与仪器应用
综合能力训练
----红外遥控电子时钟设计说明书
1绪论1
2硬件设计2
2.1DS1302时钟芯片2
2.1.1管脚介绍2
2.1.2读写指令3
2.1.3电路连接4
2.2红外遥控器4
2.31602显示屏5
3程序设计8
3.1程序流程图8
3.2时间显示8
3.2.1读取时间8
3.2.2显示时间9
3.3按键识别11
3.4时间设置12
3.4.1光标位置控制12
3.4.2设置时间14
参考文献16
附录程序清单17
1绪论
电子时钟在我们生活中随处可见,已经不是一个稀奇的东西了。
然而现在的各种电子时钟虽然可能有着各种先进的功能,但普遍存在一个缺点——时钟的控制按键都设置在时钟上,要想完成时间设置这一基本功能,必须拿到时钟才能实现。
尤其是对于那些壁挂式的电子时钟,若每次设置的时候都要将其取下来必然带来很大的不便。
针对这一缺点,本文阐述了一个普通电子时钟的改进方案。
本次课程设计设计的电子时钟,要求能够计时年、月、日、时、分、秒和星期,并可以通过红外遥控器设置时间,非常方便。
计时部分采用DS1302时钟芯片实现。
该芯片有两个电源引脚,在主电源掉电的情况下可由电池供电而继续工作,从而避免了每次开机都需要重新设置时间的麻烦。
显示部分采用的是1602显示屏,可以在一屏上显示出所有时间信息,比数码管显示更加清晰。
2硬件设计
本文设计的是一个电子时钟。
系统的时间从DS1302读取。
用户可以通过红外遥控器设置系统时间。
为了提高遥控器所发射信号的抗干扰能力,遥控器发射的红外信号是经过调制的,所以首先要经过解码器将原始信号从载波信号中分离出来。
然后再由单片机对原始信号进行处理,识别出当前按下的按键并执行相应的命令,实现时间设置。
最终由LCD1602显示屏将时间显示出来。
系统工作原理如图2.1所示。
图2.1电子时钟电路工作原理
2.1DS1302时钟芯片
2.1.1管脚介绍
DS1302时钟芯片是本次设计的电子时钟的时间来源。
他和我们日常接触的电子表差不多,可以对年月日、时分秒和星期计时。
可以用单片机从DS1302中读取时间放在液晶屏上显示,也可以用单片机往DS1302里面写入时间进行时间设置。
这样就可以实现一块电子表的功能了。
DS1302的工作电压为2.0-5.5V,工作电流小于320nA,所以在主电源断开的情况下,仅需一块电池任然能够维持长时间的工作。
芯片能够自动完成大月小月以及闰年的计算,计时时间可到2100年。
DS1302共有8个管脚,管脚图如图2.2所示。
图2.2DS1302管脚图
其中X1,X2脚为32.768KHz晶振管脚,为芯片提供工作频率,该晶振的精度直接影响到芯片的计时精度。
2.1.2读写指令
DS1302的一条指令一个字节8位,其中第七位(即最高位)是固定1,这一位如果是0的话,那写进去是无效的。
第六位是选择RAM还是CLOCK的,我前边说过,我们这里主要讲CLOCK时钟的使用,它的RAM功能我们不用,所以如果选择CLOCK功能,第六位是0,如果要用RAM,那第六位就是1。
从第五到第一位,决定了寄存器的5位地址,而第零位是读写位,如果要写,这一位就是0,如果要读,这一位就是1。
DS1302有8个和时钟有关的寄存器,5位地址分别是00000一直到00111这8个地址,还有一个寄存器的地址是01000,这是涓流充电所用的寄存器,程序中没有用到。
在DS1302的数据手册里的地址,直接把第七位、第六位和第零位值给出来了,所以指令就成了80H、81H那些了,最低位是1,那么表示读,最低位是0表示写,如图2.3所示。
图2.3DS1302时钟寄存器
从图中可以看出,年月日、时分秒和星期都有各自的地址,且读写地址不同,所以只要先向芯片中写入目标地址,就可以从芯片中读取时间或向芯片中写入时间[1]。
2.1.3电路连接
图2.4DS1302外部电路
DS1302外部电路如图2.4所示。
SCLK脚、I/O脚和RST脚分别接单片机的P10、P11和P12脚,时钟脉冲由单片机发出,根据三线之间的电平变化关系,可以实现从芯片中读取时间或向芯片中写入时间[2]。
具体时序关系参见程序设计部分。
2.2红外遥控器
红外遥控器主要作用是设置时间,这里选用的遥控器采用的是TC9012芯片,该芯片可应用于电视机、组合音响设备、录音卡座、VCD、DVD播放机等设备的控制。
由于我们用到的的只是遥控器发出的红外信号,所以这里对芯片的工作原理不做详细介绍。
按下遥控器的不同按键可发出不同的红外编码,通过程序解码后可判断是哪一按键被按下,然后做相应的处理。
解码原理将在程序设计部分介绍。
红外遥控器的接收器与单片机的连接关系如图2.5所示[3]。
图2.5红外接收器电路图
接收器的1脚为信号输出端,连接到单片机的3.2脚做外部中断0的中断源,同时连接到了LED1,通过LED指示接收器是否接收到了信号。
2脚为电源负极,3脚为电源正极,这里接了一个0.1uF的电容,滤除电源中的杂波。
接收器的作用是将接收到的红外信号中的原信号与载波信号分离,得到原始信号。
2.31602显示屏
LCD1602是一种常用的简易显示屏,可以显示阿拉伯数字、英文大小写字母以及一些简单的日文和符号等,但是不能显示汉字。
LCD1602模块上固化了字模存储器(CGROM和CGRAM),内置了192个常用字符的字模,存于字符产生器CGROM(CharacterGeneratorROM)中,还有8个允许用户自定义的字符产生RAM,称为CGRAM(CharacterGeneratorRAM)。
DDRAM(DisplayDataRAM)是显示数据RAM,用来寄存待显示的字符代码。
DDRAM相当于计算机的显存,我们为了在屏幕上显示字符,就把字符代码送入显存,这样该字符就可以显示在屏幕上了。
同理,为了在液晶屏幕上显示字符,把字符代码送入DDRAM即可。
1602的字符代码与字符的ASCII码一致。
字符的显示位置由字符写入的显存地址控制。
1602共有80个字节的显存,但显示屏只有十六位,所以只用到了其中的16个字节,第一行的八个字节的地址为0x80~0x87,第二行的八个位置对应的地址是0xC0~0xC7。
写在这些地址外的内容除非移动屏幕否则不会被显示。
1602有16个引脚,如图2.6所示(图中从左往右依次是16脚到1脚)。
图2.61602引脚图
各个引脚的功能说明见表2-1。
表2-11602引脚说明
引脚号
符号
引脚说明
引脚号
符号
引脚说明
1
VSS
电源地
9
D2
数据端口
2
VDD
电源正极(+5V)
10
D3
数据端口
3
VO
偏压信号
11
D4
数据端口
4
RS
命令/数据
12
D5
数据端口
5
RW
读/写
13
D6
数据端口
6
E
使能
14
D7
数据端口
7
D0
数据端口
15
A
背光正极
8
D1
数据端口
16
K
背光负极
注:
1.VO是液晶显示的偏压信号,可接10K的3296精密电位器。
或同样阻值的RM065/RM063蓝白可调电阻。
2.RS是命令/数据选择引脚,接单片机的一个I/O,当RS为低电平时,选择命令;当RS为高电平时,选择数据。
3.RW是读/写选择引脚,接单片机的一个I/O,当RW为低电平时,向LCD1602写入命令或数据;当RW为高电平时,从LCD1602读取状态或数据。
如果不需要进行读取操作,可以直接将其接VSS。
4.E为执行命令的使能引脚,接单片机的一个I/O。
5.D0—D7,并行数据输入/输出引脚,可接单片机的P0—P3任意的8个I/O口。
如果接P0口,P0口应该接4.7K—10K的上拉电阻。
如果是4线并行驱动,只须接4个I/O口。
6.A背光正极,可接一个10—47欧的限流电阻到VDD。
7.K背光负极,接VSS。
1602的电路连接图如图2.7所示。
图2.7LCD1602电路连接图
数据位DB0~DB7连接的是单片机的P0口,VO接10K的电位器用来调节显示屏的对比度。
3程序设计
3.1程序流程图
图3.1数字时钟流程图
3.2时间显示
3.2.1读取时间
DS1302的读取时序如图3.2所示。
图3.2DS1302读时序
RST引脚(复位引脚)标号上面的一个横杠表示此引脚低电平有效,也即给它低电平后芯片复位,不能正常工作[4]。
所以欲使芯片正常工作,此引脚应该给高电平,从时序图中也可以看出,我们进行写操作的时候RST引脚应该置为高电平。
再看SCLK时钟引脚和IO引脚。
图中的前八位的黑色箭头表示写入的数据在上升沿锁存,后八位的黑色箭头表示下降沿读取数据。
也就是说如果我们要从DS1302里面读出一位二进制数据,首先应该把SCLk引脚拉高,然后把SCLK拉低(在SCLK拉低的一瞬间DS1302的数据送到了IO端口上),再把IO口上的数据存入变量,此时就读到了一位二进制数据。
还有一点需要注意,读数据的时候先读低位,后读高位,且要先写地址,后读数据。
从R/
的符号中可以看出,写地址时,如果最低位写入的是0这说明是要往芯片里写数据,在输入完第一个字节后,芯片会等待输入数据;如果最低位写入的是1,则是从芯片读取数据,在写完地址后芯片会在串行时钟的控制下输出时间数据。
要注意的是,芯片在写完一个字节后的第一个下降沿就开始输出时间,中间没有间隔。
从DS1302直接读取的是时间的8421BCD码,前四位储存的是十位数的二进制值,后四位是给位数的二进制值。
经time=time/16*10+time%16;这步运算后将其转化为十进制数并作为函数的返回值。
3.2.2显示时间
1602显示屏的写操作分为写命令和写数据两种。
写命令包括清屏、光标归位、显示屏开关以及是否显示光标等。
详细指令集可查阅1602元件手册。
写入数据前先写入命令将光标移动到要显示该数据的位置。
写入数据后,根据设置光标自动向左或向右移动一位。
所以如果是写连续显示的几位的话可以不必每次都写入光标移动命令。
执行写操作时RW脚要清零,此时若RS脚也清零则为写命令,否则为写数据,写时序图如图3.3所示。
图3.31602写时序图
先将使能端E电平拉低,然后将R/W脚电平拉低,根据写命令还是写数据设置好RS脚的电平,把要写入的数据放到P0口,这样便做好了写的准备工作。
这时再将E脚电平置1即可将P0的数据写入1602。
1602执行某些指令需要花费较长的时间,当上条指令没有执行完时是无法接收下一条指令的。
所以在写指令之前要进行判忙,以免指令丢失。
利用以上两个函数便可实现显示功能,如以下两个函数分别可以实现在指定位置显示一个字符和字符串。
voidWriteChar(intx,inty,charcharData)//在(x,y)处显示字符charData
{
if(y==0)
WriteCommand(0x80+x);//写入要显示的位置
else
WriteCommand(0xC0+x);
WriteData(charData);//写入显示的内容
}
voidWriteString(intx,inty,char*string)//从(x,y)处显示字符串string
{
//addx=x;
//addy=y;
if(y==0)
WriteCommand(0x80+x);
else
WriteCommand(0xC0+x);
while(*string)//循环发送所有字符,每写完一个字符光标自动右移一位
{
WriteData(*string);
string++;
}
}
3.3按键识别
遥控器按键按下后会发射不同编码,这些编码的结构为:
起始码,两位客户码,数据码和数据码的反码。
如图3.4所示。
图3.4红外遥控器编码结构
对于同一款遥控器,每个按键的起始码和客户码是相同的,数据码不同用以区分不同按键。
该芯片以一个持续4.5ms的高电平和4.5ms的低电平作为起始码,只有收到起始码后才认为有按键按下,这样可以有效的避免外界干扰。
除起始码外,剩下的每一位都以一个0.56ms的高电平开始,根据该高电平与接下来的低电平持续的总时间来区别0和1:
若总时间为1.125ms则为0,若总时间为2.25ms则为1。
如图3.5所示。
图3.50与1的电平持续时间图
因为每个按键的码值都是可以检测出来的,这样在解读到码值时通过对比的方法就可以确定是哪一个按键按下了。
为了增强抗干扰能力,发送的红外信号是经过调制的,在接收端由硬件将原是新号从载波信号中分离出来。
但分离出来的信号的电平高低与原始信号正好相反,这样原始信号中的上升沿在接收后就变成了下降沿,所以信号的每一位开始时都会有一个下降沿。
这里采用了中断处理的方式,保证响应的及时性。
从图3.5中可以看出,起始码的判断没有区分高电平4.5ms和低电平4.5ms,但在程序中可以只确保了起始码的总时间,只要这个总时间在8ms~11ms区间内,只都认为收到了起始码。
这样做放宽了接收条件,可以更好的接收按键信号。
因为客户码加数据码总共32位,而unsignedlong型在单片机中占4个字节,也是32位,正好可以储存下遥控编码。
所以可以定义一个unsignedlong型的变量储存码值。
3.4时间设置
3.4.1光标位置控制
程序启动后默认不显示光标,当检测到设置键按下后才会显示闪烁的光标。
光标有两个作用,一是提示用户当前是在哪一位输入,二是可以帮助用户更快速的完成设置。
如当前的时间年月日、星期以及小时都是对的,只需要对分钟做一下调整,没有光标用户需要把所有的信息输入一次,而有了光标只需要把光标移动到分钟的位置输入分钟的值就可以了。
另外,时间在屏幕上的显示如图3.6所示,在设置时间的时候光标的移动应该跳过“/”“:
”的位置和无字符的位置,所以必须对光标的位置进行控制。
图3.6LCD1602显示时间
光标位置调整用到了读取1602屏幕上显示的内容,所以先对如何获取显示内容做一个介绍。
要用到读取操作首先要将R/W置1,若读取指令,RS置1,若读取数据,RS清零。
1602的读取时序图如图3.7所示。
图3.71602读操作时序图
读操作与写操作的区别是R/W脚置1,P0口的值是有1602控制的而不是有单片机设置。
在E由0变1的t0时间后P0口得到所需的数据。
因为要读P0口,所以在对之前要把P0口置1。
1602中虽然有读数据和读命令的操作,但无法直接读取光标当前位置,所以只能定义两个变量addx、addy来储存当前光标位置(x,y),变量的值随光标位置的改变而改变,这样通过查询addx和addy的值就可以知道光标当前位置了[5]。
因为需要用户设置的内容都是数字,所以光标需要停留的位置必然是数字。
光标每一移动一次都读取一次当前位置显示的内容,若是数字则停留,否则继续向下移动一位,直到找到数字为止。
程序如下:
voidMoveCursor(chardir)//光标移动函数,dir为移动方向,若为0则不动
{
if(!
IsSettingTime)//如果不在设置时间则不移动
return;
if(dir==LEFT)//左方向键按下,光标左移一位
{
addx--;
while(!
(ReadData(addx,addy)>='0'&&ReadData(addx,addy)<='9'))
//当前位置处不是数字
addx--;//继续左移,直到找到数字
}
elseif(dir==RIGHT)//右方向键按下,光标右移一位
{
addx++;
while(!
(ReadData(addx,addy)>='0'&&ReadData(addx,addy)<='9'))
addx++;
}
elseif(dir==UP||dir==DOWN)//上或下键按下,换行
{
addy=~addy;
while(!
(ReadData(addx,addy)>='0'&&ReadData(addx,addy)<='9'))
addx++;//当前位置处不是数字,右移一位
}
if(addx>15)//坐标超过屏幕显示范围,归零,循环移动
addx=0;
elseif(addx<0)
addx=15;
if(addy)//执行移动光标命令,真正将光标移动到(addx,addy)处
WriteCommand(0xC0+addx);//第二行
else
WriteCommand(0x80+addx);//第一行
}
程序先是对坐标位置标识变量进行运算,此时并没有真正改变光标位置,待找到合适的光标位置后再通过光标移动指令一次性移动到该位置。
因为屏幕只有两行,所以上下方向键的行为是一样的,都是换行,没有必要分别处理。
光标每移动一次都调用这个函数进行判断,这样看上去光标就只是在我们想要的位置移动了。
3.4.2设置时间
本次设计中遥控器上共定义了设置键、确认键、退出键、上下左右方向键和0~9十个数字键等几个按键。
在设置键按下之前,系统忽略所有的输入。
用户要想设置时间,首先要按下设置键。
按下设置键后系统进入设置模式,出现闪烁的光标,表示用户当前正在设置哪一位。
用户可以直接键入所有时间位的数值,也可以通过方向键将光标移动到需要修改的地方,然后按下相应的数字键设置该位的值。
用户在输入完时间后若确认想修改时间,可按下遥控器上的确认键,这时程序读取屏幕上当前显示的时间,并将这一新的时间数据写入到DS1302芯片;若想放弃修改,则可按下退出键,这时不会对1302的时间产生任何影响,屏幕上继续显示当前时间。
无论用户按下确认键还是退出键系统都会退出设置模式,隐藏光标,继续显示1302中的时间。
至此,一个可用遥控设置时间的时钟程序已全部完成。
参考文献
[1]陈权昌,李兴富.单片机原理及应用.广州:
华南理工大学出版社,2007.8.
[2]杨志忠.数字电子技术.北京:
高等教育出版社,2003.12.
[3]及力.Protel99SE原理图与PCB设计教程.北京:
电子工业出版社,2007.8.
[4]徐江海.单片机实用教程.北京:
机械工业出版社,2006.12.
[5]李庆亮.C语言程序设计实用教程.北京:
机械工业出版社,2005.3.
附录程序清单
1.DS1302读取时间的程序。
sbittimeClk=P1^0;
sbittimeData=P1^1;
sbittimeRst=P1^2;
UCHARReadTimeByte(UCHARaddr)
{
UCHARi,time=0;
timeRst=timeClk=0;
timeRst=1;
addr|=0x01;//最低位置1,进入读状态(先写地址后读数据)
for(i=0;i<8;i++)//写要读取的地址
{
timeData=addr&0x01;
timeClk=1;//产生上升沿,写入地址
timeClk=0;//为下一次上升沿做准备
addr>>=1;
}
if(timeData&0x01)//读取第一位
time|=0x80;
else
time&=0x7f;
for(i=0;i<8-1;i++)
{
timeClk=1;
timeClk=0;//产生下跳沿,读取数据
time>>=1;
if(timeData&0x01)
time|=0x80;
else
time&=0x7f;
}
timeRst=0;
time=time/16*10+time%16;//8421BCD转常规数字
returntime;
}
2.1602写命令程序:
idWriteCommand(unsignedcharcom)//写命令函数,com为写入的命令
{
while(CheckBusy());//CheckBusy()为判忙函数
WC;//#defineWCRS=0;RW=0写入命令
EN=1;//使能端置1
Data=com;//数据发到P0口
_nop_();//空指令,延时
EN=0;//下降沿写入指令
}
3.1602写数据程序:
voidWriteData(unsignedcharcharData)//写指令函数,com为写入的指令
{
while(CheckBusy());
//addx++;
WD;//#defineWDRS=1;RW=0写入数据
EN=1;
Data=charData;
_nop_();
EN=0;//下降沿写入数据
}
4.红外遥控器按键识别的程序:
voidinfrafedSignal()interrupt0
{
//判断起始码
if(counter>30&&counter<60)//30=8000us/256us,60=11000us/256us
{
flag=1;
num=0;
counter=0;
}
elseif(num==0)
{
ET1=1;
TR1=1;
counter=0;
}
if(flag)
{
num++;
signal<<=1;//左移一位
if(counter>7)
signal|=1;
if(num>32)
{
num=0;
flag=0;
ET1=0;
TR1=0;
keyFlag=1;
}
}
counter=0;
}
5.1602读一个字节的程序:
UCHARReadData(charx,bity)//读取(x,y)位置当前显示的值
{
//addx=x;
//addy=y;
//MoveCursor();
EN=0;
P0=0xff;//P0口置1,为读数据做准备
while(CheckBusy());//判忙
RD;//#defineRDRS=1;RW=1读数据
EN=1;
//while(CheckBusy());
delay1ms
(1);//等待P0口数据变化
retu