单片机课设红外遥控及点阵显示应用.docx
《单片机课设红外遥控及点阵显示应用.docx》由会员分享,可在线阅读,更多相关《单片机课设红外遥控及点阵显示应用.docx(27页珍藏版)》请在冰豆网上搜索。
单片机课设红外遥控及点阵显示应用
1.主要元器件介绍
1.1AT89C51单片机
1.1.1AT89C51单片机的硬件结构
AT89C52单片机的内部结构与MCS-51系列单片机的构成基本相同。
CPU是由运算器和控制器所构成的。
运算器主要用来对操作数进行算术、逻辑运算和位操作的。
控制器是单片机的指挥控制部件,主要任务的识别指令,并根据指令的性质控制单片机各功能部件,从而保证单片机各部分能自动而协调地工作。
它的程序存储器为8K字节可重擦写Flash闪速存储器,闪烁存储器允许在线+5V电擦除、电写入或使用编程器对其重复编程。
数据存储器比51系列的单片机相比大了许多为256字节RAM。
AT89C52单片机的指令系统和引脚功能与MCS-51的完全兼容。
CPU
串行通讯口
RAM
输入输出接口
计数器
定时器
时钟
FLASH
图18单片机89C52结构框图
1.1.2AT89C52管脚说明
VCC:
电源
GND:
接地
P0口:
P0口是一个8位漏级开路的双向I/O口。
作为输出口,每位能驱动8个TTL逻辑电平。
对P0口端口写“1”时,引脚作高阻抗输入。
当访问外部程序和数据存储器时,P0口也被作为低8位地址/数据复用。
在这种模式下,P0具有内部上拉电阻。
在flash编程时,P0口也用来接受指令字节:
在程序效验时,输出指令字节。
程序效验时,需要外部上拉电阻。
P1口:
P1口是一个具有内部上拉电阻的
8位是双向I/O口,P1的输出缓冲级可驱动(
吸收或输出电流)4个TTL逻辑电平。
对P1
口写“1”时,内部上拉电阻的原因,将输出
电流ILL。
此外,与AT89C51不同之处是,P1.0和
P1.1还可分别作为定时/计数器2的外部计数
输入(P1.0/T2)和输出(P1.1/T2EX),具体图2AT89C52外部引脚
如下表所示
表1P1.0和P1.1的第二功能
引脚号
功能特性
P1.0
T2(定时/计数器2外部计数脉冲输入),时钟输出
P1.1
T2EX定时/计数2捕获/重装载触发和方向控制
在Flash编程和校验时,P1口接收低8位地址字节。
P2口:
P2口是一个具有内部上拉电阻的8位双向I/O口,P2输出缓冲级可驱动吸收或输出电流4个TTL逻辑电平。
对P2口写“1”时,通过内部上拉电阻把端口拉高,此时可以作为输入口使用。
作为输入使用时,被外部拉低的引脚由于内部电阻的原因,将输出电流ILL。
在访问外部好曾许存储器或用16位地址读取外部数据存储器时,P2口送出高8位地址。
在这种应用中,P2口使用很强的内部上拉发送1。
在使用8位地址访问外部数据存储器时,P2口输出P2锁存器的内容。
在Flash编程和校验时,P2口接收低8位地址字节和一些控制信号。
P3口:
P3口是一个具有内部上拉电阻的8位双向I/O口,P3输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑电平。
对P3口写“1”时,内部上拉电阻把端口拉高,此时可以作为输入端口使用。
作为输入使用时,被外部拉低的引脚由于内部电阻的原因,将输出电流ILL。
P3口除了作为一般、的I/O口线外,更重要的是它的第二功能,如下表所示。
表2P3口引脚第二功能
引脚号
第二功能
P3.0
RXD(串行输入)
P3.1
TXD(串行输出)
P3.2
INT0(外部中断0)
P3.3
INT1(外部中断1)
P3.4
T0(定时器0外部输入)
P3.5
T1(定时器1外部输入)
P3.6
WR(外部数据存储器写选通)
P3.7
RD(外部数据存储器读选通)
在Flash编程和校验时,P3口也接收一些控制信号。
RST:
复位输入。
晶振工作时,RST脚持续2个机器周期以高电平将使用单片机复位。
ALE/
:
地址锁存器控制信号(ALE)是访问外部程序存储器时,锁存低8位地址的输出脉冲。
在Flash编程时,此引脚(
)也使用作编程输入脉冲。
在一般情况下,ALE以晶振六分之一的固定频率输出脉冲,可用来作为外部定时器或时钟使用。
然而,特别强调,在每次访问外部数据存储器时,ALE脉冲将会跳过。
如果需要,通过将地址为8EH的SFR的第0位置“1”,ALE操作无效。
这一位置“1”,ALE仅在执行MOVX或MOVC指令时有效。
否则,ALE将被微弱拉高。
这个ALE使能标志位的设置对微控制器处于外部执行模式下无效。
:
外部程序储存器选通信号(
)是外部程序存储器选通信号。
当AT89C52从外部程序存储器执行外部代码时,
在每个机器周期被激活两次,而在访问外部数据储存器时,
将不被激活。
:
访问外部程序存储器控制信号。
为使能从0000H—FFFFH的外部程序存储器读取指令,
端必须保持低电平(接地)。
为了执行内部程序指令,
应该接VCC。
在flash编程期间,
也接受12伏VPP电压。
XTAL1:
振荡器反相放大器及内部时钟发生器的输入端。
XTAL2:
振荡器反相放大器的输出端。
1.1.3存储器结构
MCS-51器件有单独的程序存储器和数据存储器。
外部程序存储器和数据存储器都可以64K寻址。
1.程序存储器
如果EA引脚接地,程序读取只从外部存储器开始。
对于89C52,如果EA接VCC,程序先从内部存储器(地址为0000H~1FFFFH)开始,接着从外部寻址,寻址范围为:
2000H~FFFFH。
2.数据存储器
AT89C52有256字节RAM。
高128字节与特殊功能寄存器重叠。
也就是说高128字节与特殊功能寄存器有相同的地址,而物理上是分开的。
当一条指令访问高于7FH的地址时,寻址方式决定CPU访问高字节RAM还是特殊功能寄存器空间。
直接寻址方式访问特殊功能寄存器(SFR)。
1.1.4定时器
1.定时器0和定时器1
在AT89C52中,定时器0和定时器1都是16位加法计数结构,分别由TH0(地址8CH)和TL0(地址8AH)及TH1(地址8DH)和TL1(地址8BH)两个8位计数器组成。
这4个计数器均属于专用寄存器之列。
每个定时器/计数器都有定时和计数两种功能。
2.计数功能
所谓的计数功能是指对外部事件进行计数。
外部事件的发生以输入脉冲表示,因此计数功能的实质就是对外脉冲进行计数。
MCS-51系列的芯片有T0(P3.4)和T1(P3.5)两个信号引脚,分别就是这两个计数器的计数输入端。
外部输入的脉冲在负跳变时有效,进行计数器加1。
计数方式下,单片机在每个机器周期的S5P2拍节对外部计数脉冲进行采样。
如果前一个机器周期采样为高电平,后一个机器周期采样为低电平,即为一个有效计数脉冲。
在下一个机器周期的S3P1进行计数。
可见采样计数脉冲是在2个机器周期进行的。
鉴于此,计数脉冲的频率不能高于振荡脉冲的频率不能高于振荡脉冲频率的1/24。
3.定时功能
定时器也是通过计数器的计数来实现的,不过此时的计数脉冲来自单片机的内部,即每个机器周期产生一个计数脉冲。
也就是每个机器周期计数加1。
由于一个机器周期等于12个振荡脉冲周期,因此计数频率为振荡频率的1/12。
如果单片机采用12MHz晶体,则计数频率为1MHz。
即每微秒计数器加1。
这样不但可以根据计数值计算出定时时间,也可以反过来按定时时间的要求计算出计数器的预置值。
4.定时器2
定时器2是一个16位定时器/计数器,它既可以作定时器,又可以做事件计数器。
其工作方式由特殊寄存器T2CON中的C/T2位选择(如表2所示)。
定时器2有三种工作模式:
捕捉方式、自动重载(向上或向下计数)和波特率发生器。
如表3.3所示,工作模式由T2CON中的相关为选择。
定时器2有2个8位寄存器:
TH2和TL2。
在定时工作方式中,每个机器周期,TL2寄存器都会加1。
由于一个机器周期由12个晶振周期构成,因此,计数频率就是晶振频率的1/12。
表3.3定时器2工作模式
RCLK+TCLK
CP/RL2
TR2
MODE
0
0
1
16位自动重载
0
1
1
16位捕捉
1
×
1
波特率发生器
×
×
0
不用
在计数工作方式下,寄存器在相关外部输入角T2发生1至0的下降沿时增加1。
在这种方式下,每个机器周期的S5P2期间采样外部输入。
一个周期采样到高电平,而下一个周期采样到低电平,计数器加1。
在检测到跳变的这个周期的S3P1期间,新的计数值出现在寄存器中。
因为识别1—0的跳变需要2个机器周期(24个晶振周期),所以,最大的计数频率不高于晶振频率的1/24。
为了确保给定的电平在采样前采样到一次,电平应该至少在一个完整的机器周期内保持不变。
表4T2MOD-定时器2控制寄存器
T2MOD地址:
0C9H复位值:
×××××00B
-
-
-
-
-
-
T2OE
DCEN
7
6
5
4
3
2
1
0
符号
功能
—
无定义,预留扩展
T2OE
定时器2输出允许位
DCEN
置1后,定时器2可配置向上或向下计数
1.1.5中断
AT89C52有6个中断源:
两个外部中断(INT0和INT1),三个定时中断定时器0、1、2和一个串行中断。
每个中断源都可以通过置位或清除特殊寄存器IE中的相关中断允许控制位分别使得中断源有效或无效。
IE还包括一个中断总控制位EA,它能禁止所有中断。
如表3.5所示,IE.6位是不可用的。
对于AT89S52,IE.5位也是不能用的。
用户软件不应给这些位写1。
它们为AT89系列新产品预留。
定时器2可以被寄存器T2CON中的TF2和EXF2的或逻辑触发。
程序进入中断服务后,这些标志位都可以由硬件清0。
实际上,中断服务程序必须判定是否是TF2或EXF2激活中断。
标志位也必须由软件清0。
定时器0和定时器1标志位TF0和TF1在计数溢出的那个周期的S5P2被置位。
它们的值一直到下一个周期被电路捕捉下来。
然而,定时器2的标志位TF2在计数溢出的那个周期被置位,在同一个周期被电路捕捉下来。
表3中断允许控制位
符号
位地址
功能
EA
IE.7
中断允许控制位,EA=0,中断总禁止;EA=1,各中断由各自的控制位设定
-
IE.6
预留
ET2
IE.5
定时器2中断允许控制位
ES
IE.4
串行口中断允许控制位
ET1
IE.3
定时器1中断允许控制位
EX1
IE.2
外部中断1允许控制位
ET0
IE.1
定时器0中断允许控制位
EX0
IE.0
外部中断0允许控制位
1.216*16点阵LED
8×8单色点阵共需要64个发光二极管组成,且每个二极管是放置在行线与列线的叉点上。
下图为8×8点阵LED外观及引脚图,其等效电路如下图所示,只要其对应的X、Y轴顺向偏压,即可使LED发亮。
图48×8点阵外观及引脚图
proteus中用8×8点阵组成的16×16点阵,如下图:
图516×16点阵
点阵LED一般采用扫描式显示,实际运用分为三种方式:
(1)点扫描;
(2)行扫描;
(3)列扫描。
若使用第一种方式,其扫描频率必须大于16×64=1024Hz,周期小于1ms即可。
若使用第二和第三种方式,则频率必须大于16×8=128Hz,周期小于7.8ms即可符合视觉暂留要求。
此外一次驱动一列或一行(8颗LED)时需外加驱动电路提高电流,否则LED亮度会不足。
1.3红外控制相关介绍
红外遥控系统由发射和接收两大部份组成,应用编/解码专用集成电路芯片来进行控制操作,如图1所示。
发射部份包括键盘矩阵、编码调制、LED红外发送器;接收部份包括光、电转换放大器、解调、解码电路。
光/电放大
解调
解码
图6红外遥控系统框图
HT6221键码的形成:
当发射器按键按下后,即有遥控码发出,所按的键不同遥控编码也不同。
这种遥控码具有以下特征:
采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”。
2设计原理或方法
2.1设计总体思路
本次课程设计的要求是利用红外遥控器控制,在16×16点阵的显示器件上循显示“武汉理工大学”6个汉字,控制项目:
循环显示的速度可调,循环显示进入方向(从左至右、从右至左、从上到下、从下往上)。
由于要用16*16点阵显示汉字,而80C51的I/O接口是8位的,我们可以用4个8*8点阵来组成。
由于80C51的I/O口不多(只有4组,32个),为了节约I/O口,我们用4线-16译码器作为点阵的列驱动,P2口和P0口作为数据线。
改变汉字移动的速度,可以通过用按键改变汉字在LED上的显示时间来改变,通过改变的数值大小就可以改变汉字的移动速度。
题目所要求的用红外控制我们可以先用开关模拟达到要求,再将开关的功能用红外来实现,这样就可以基本上达到要求。
通过红外接收器所解出来的码将其送到89C51的一个I/O口以达到开关的效果。
这样就可以基本达到要求了。
2.2与题目相关的具体设计
汉字的显示:
可以采用扫描的方式,先使一个I/O口产生一个选行(列)信号,先选中一行,对选中的行进行扫描,然后用另外2组I/O口输送数据,这样一个字的1/16就送到LED点阵上了,接着选下一行,这样经过16次就可以显示一个字了,再适当延时使显示的字清晰。
汉字的移动:
在LED上显示一个汉字并延时后,可以通过增加所取表的地址(加2);这样下一次LED上显示的字就移动了一个点阵,可以通过适当的设计来控制汉字移动循环的的次数。
汉字的左右上下移动:
可以通过建立不同的表,来实现汉字的各种移动,或者改变查表的方式来实现。
3.系统硬件线路设计图
图7仿真电路图
4.程序框图
开始
系统初始化
赋初值(控制移动速度)
P3.2=0?
P3.7=0?
移动速度增加
移动速度减慢
下移动
上移动
右移动
左移动
否
是
否
是
图8系统主程序流程图
5.资源分配
P1.0到P1.3接4-16译码器给16*16点阵提列信号。
P0.0到P0.7接16*16点阵的上半块作为数据线,给16*16点阵上部提供数据,点亮相应的LED,P2.0到P2.7接16*16点阵的下半块作为数据线,给16*16点阵下部提供数据,点亮相应的LED。
P3.2接开关,用于控制移动速度,P3.7接开关,用于控制汉字的显示的移动方向。
表5资源分配表
P1.0-P1.3
接4-16译码器
P0.0-P0.7
接16*16点阵的上半块作为数据线
P2.0-P2.7
接16*16点阵的下半块作为数据线
P3.2
接开关控制移动速度
P3.7
接开关控制显示的移动方向
6.源程序
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitkey0=P3^7;
sbitkey1=P3^2;
ucharzt,z,speed,flag;
ucharcodehanzi[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//"",
0x20,0x40,0x20,0xC0,0x24,0x7E,0x24,0x40,0x24,0x40,0xA4,0x3F,0x24,0x22,0x24,0x22,
0x20,0x20,0xFF,0x03,0x20,0x0C,0x22,0x10,0x2C,0x20,0x20,0x40,0x20,0xF8,0x00,0x00,//"武",
0x10,0x04,0x60,0x04,0x02,0x7C,0x0C,0x03,0xC0,0x80,0x02,0x80,0x1E,0x40,0xE2,0x20,
0x02,0x13,0x02,0x0C,0x02,0x13,0xE2,0x20,0x1E,0x40,0x00,0x80,0x00,0x80,0x00,0x00,//"汉",
0x04,0x20,0x84,0x60,0x84,0x20,0xFC,0x1F,0x84,0x10,0x84,0x10,0x00,0x40,0xFE,0x44,
0x92,0x44,0x92,0x44,0xFE,0x7F,0x92,0x44,0x92,0x44,0xFE,0x44,0x00,0x40,0x00,0x00,//"理",
0x00,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0xFC,0x3F,
0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x00,0x20,0x00,0x00,//"工",
0x20,0x80,0x20,0x80,0x20,0x40,0x20,0x20,0x20,0x10,0x20,0x0C,0x20,0x03,0xFF,0x00,
0x20,0x03,0x20,0x0C,0x20,0x10,0x20,0x20,0x20,0x40,0x20,0x80,0x20,0x80,0x00,0x00,//"大",
0x40,0x04,0x30,0x04,0x11,0x04,0x96,0x04,0x90,0x04,0x90,0x44,0x91,0x84,0x96,0x7E,
0x90,0x06,0x90,0x05,0x98,0x04,0x14,0x04,0x13,0x04,0x50,0x04,0x30,0x04,0x00,0x00,//"学",
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00//"",
};
ucharcodelie[]={0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff};
voiddelay(ucharx)//延时函数
{
uchari,j;
for(i=0;ifor(j=0;j<120;j++);
}
voidscanf_dir()//判断按键
{
if(key0==0)
{
delay(3);
if(key0==0)
{
zt++;
while(!
key0);
if(zt==4)
zt=0;
}
}
}
voidleft()//左移动
{
uchari,zishu,x;
P1=0xff;
for(zishu=0;zishu<6;zishu++)//6个字
{
P0=0xff;
P2=0xff;
for(x=0;x<16;x++)//从左向右移动16次,(第一屏、第二屏。
。
。
。
)
{
if(zt!
=0)
break;
for(z=0;zfor(i=0;i<16;i++)//16列循环显示
{
scanf_dir();
if(zt!
=0)
break;
P1=lie[i];
P0=~hanzi[2*i+zishu*32+x*2];
P2=~hanzi[2*i+zishu*32+x*2+1];
delay(3);
P0=0xff;
P2=0xff;
}
}
}
}
voidshowc(ucharc,ucharb,ucharn,ucharl)//右移动辅助函数
{
uchari;
for(i=0;i{
scanf_dir();
if(zt!
=1)
break;
P1=lie[i+l];
P0=~hanzi[c*32+i*2+b*2];
P2=~hanzi[c*32+i*2+1+b*2];
delay(3);
P0=0xff;
P2=0xff;
}
}
voidright()//右移动
{
uchari,zishu;
P1=0x00;
for(zishu=0;zishu<6;zishu++)
{
for(i=0;i<16;i++)
{
if(zt!
=1)
break;
for(z=0;z{
showc(zishu,0,16-i,i);
showc(zishu+1,15-i,i,0);
}
}
}
}
voidup()//上移动
{
uchari,zishu,y,n;
uchart1,t2,t3;
P1=0x00;
for(zishu=0;zishu<6;zishu++)
{
P0=0xff;P2=0xff;
for(n=0;n<2;n++)
for(y=0;y<8;y++)
{
if(zt!
=2)
break;
for(z=0;zfor(i=0;i<16;i++)
{
scanf_dir();
if(zt!
=2)
break;
if(n==0)
{
t1=~hanzi[2*i+zishu*32];
t2=~hanzi[2*i+1+zishu*32];
t3=~hanzi[2*i+zishu*32+32];
}
else
{
t1=~hanzi[2*i+1+zishu*32];
t2=~hanzi[2*i+zishu*32+32];
t3=~hanzi[2*i+1+zishu*32+32];
}
P1=lie[i];
P0=(t1>>y)|(t2<<(7-y));
P2=(t2>>y)|(t3<<(7-y));
delay
(1);
P0=0xff;
P2=0xff;
}
}
}
}
voiddown()//下移动
{
uchari,zishu,y,n;
uchart1,t2,t3;
P1=0x00;
for(zishu=0;zishu<6