51单片机课程设计Word下载.docx
《51单片机课程设计Word下载.docx》由会员分享,可在线阅读,更多相关《51单片机课程设计Word下载.docx(41页珍藏版)》请在冰点文库上搜索。
4)用万用表检查是否有虚焊,引脚短路现象
5)查询器件的DATASHEET,分析一下时序是否一致,同时分析一下命令字是否正确
6)通过示波器对芯片各个引脚进行检查,检查地址线是否有信号的
7)飞线。
用别的的口线进行控制,看看能不能对其进行正常操作,多试验,才能找到问题出现在什么地方。
四、任务设计
由于开发板功能有限,所以基本把可以实现的功能都用上了。
设计的功能大体上分为5个模块:
18B20的温度测量模块、红外遥控器的解码模块、蜂鸣器音乐播放模块、数码管定时器模块、1602显示模块。
另外由于跑马灯的Port口与1602显示Port口复用,且该功能较为简单,所以并未实现该功能。
且12864模块和1602模块类似,同为液晶显示模块,该功能也未实现。
其它模块功能都已实现。
下面将分别介绍各个模块功能的实现。
五、模块介绍
1、18B20的温度测量
DS18B20是温度测量器件,有三个引脚,类似于三极管,分别是地线GND、数据线I/O、电源线VDD。
由于DS18B20采用的是1-Wire总线协议方式,即在一根数据线上实现数据的双向传输,而对AT89S51单片机来说,硬件上并不支持单总线协议,因此,须采用软件的方法来模拟单总线的协议时序来完成对DS18B20芯片的访问。
由于DS18B20是在一根I/O线上读写数据,因此,对读写的数据位有着严格的时序要求。
DS18B20有严格的通信协议来保证各位数据传输的正确性和完整性。
该协议定义了几种信号的时序:
初始化时序、读时序、写时序。
所有时序都是将主机作为主设备,单总线器件作为从设备。
而每一次命令和数据的传输都是从主机主动启动写时序开始,如果要求单总线器件回送数据,在进行写命令后,主机需启动读时序完成数据接收。
数据和命令的传输都是低位在先。
ds18b20时序说明
根据官方数据手册,我们可以对其时序进行如下分析:
初始化时序:
上图是DS18B20初始化时序,从图中我们可以得知,黑线代表的是主设备,也就是单片机被要求的操作,灰线代表的是从设备,也就是18B20的电平变化。
首先由单片机拉低信号线480us,使它复位,然后释放总线15-60us,18b20会拉低总线60-240us,然后它释放总线。
所以初始化成功的一个标志就是能否读到18b20这个先低后高的操作时序。
如检测到,则代表初始化成功。
注意,每次读取都要初始化,否则18b20处于待机状态,无法成功读取。
写时序:
该过程是写1bit数据过程。
而该过程又分为写0和写1操作。
当要写0时序时,单总线要被拉低至少60us,保证18B20在15us到60us之间能正确的采样到“0”电平。
当写1时序时,单总线被拉低后,在15us之内就需要释放单总线,保证18B20在15us到60us之间能正确的采样到“1”电平。
读操作:
该过程是读1bit数据过程。
单总线被单片机拉低后,需在15us内释放才能保证主设备可以采样到18B20传入的数据。
在15us到60us之间单片机采样到一位数据,则18B20完成一个读时序至少要60us才能完成。
完成了最基本的三个时序操作之后,便可以对照着官方数据手册,使用相关指令,实现自己需要的功能。
2、红外遥控解码模块
如左图所示,红外接收管收三个引脚,一个数据口,一个电源和一个地。
使用38kHz载波频率
头码间隔为9ms+4.5ms
使用16位客户代码
使用8位数据代码和8位取反的数据代码
数据格式包括引导码、用户码、数据码及数据码反码,编码一共是32位。
红外遥控信号从引导码开始,接下来是16位客户代码,然后是8位数据代码和取反的二进制8位代码,最后的是1位结束位。
此种编码方式可以使用MCU的捕获功能实现,通过比较两次捕获的时间,来判断发射码,按照如下图的时序,便能实现红外解码。
3、蜂鸣器音乐播放模块
蜂鸣器分为无源和有源两种,这里的“源”不是指电源。
而是指震荡源。
也就是说,有源蜂鸣器内部带震荡源,所以只要一通电就会叫。
而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。
必须用2K~5K的方波去驱动它。
有源蜂鸣器往往比无源的贵,就是因为里面多个震荡电路。
无源蜂鸣器的优点是:
便宜、声音频率可控,可以做出“多来米发索拉西”的效果、在一些特例中,可以和LED复用一个控制口。
而有源蜂鸣器的优点是:
程序控制方便。
本实验板中用的是无源蜂鸣器,则可以通过单片机发出不同频率的波来改变声音的频率,达到不同的音调,通过不同音调的组合,可以实现简单的音乐播放。
本模块主要是定时器的应用,通过计算,配置相应的寄存器参数,就可以实现频率的精准控制,产生不同评论的方波,然后再用音乐频率取模软件,就可以得到一首歌的频率和时隙的变化。
然后再通过单片机产生相应的PWM波,送入如图所示的Port口,蜂鸣器便可以产生不同的音乐。
4、数码管定时器模块
该模块涉及到两个方面的知识,一个是定时器的精准控制,另一个是数码管的动态扫描。
定时器的精准控制在上面蜂鸣器中已经说了,这里就不再赘述。
这里主要讲的是动态扫描,由于本实验板给的是四位一体数码管。
未用到锁存器,就可以直接用单片机来控制位选,由于数码管的每位不能单独写数据,所以必须利用动态扫描来显示。
动态扫描的原理主要是利用人眼的视觉暂留,因为不能单独写数据,所以要想让数码管显示不同的值,必须每位单独分开显示,每次只开一个位选,选中一个数码管,送入相应的数据,然后开第二个位选端,写入相应位的数据,然后循环控制位选,然后利用单片机调整切换速率到合适的大小,根据人眼的视觉暂留,看上去就像是4位数据是同时显示的,这就是数码管的动态显示原理。
然后通过计算,严格控制定时器,然后每秒更改一次数码管显示的值,那么定时器就算是完成了。
5、1602显示模块
中间的Valid
Data即有效数据区,我们进行读或写,无非都是想进行数据的传送,在时序图中,
进行读操作的时候,RW置于1,RS则根据读的内容(状态或数据)置为1或0,经过td时间后,可以在数据口读到正确的数据,由于td的时间极短(ns级),单片机操作一般是us级,所以可以不考虑这个时间差,在将E置为1之后,接着写指令去读取数据,在读到数据后,再将E置为0,经过THD2时间后,数据口上的数据失效。
在进行写操作的时候,RW要置为0,RS根据写的内容不同(指令或数据)置为1或0,同时,在将E置为1之前,要先将数据送到数据口上,然后,在C位置,将E置为1,经过tPW延时后,再将E置为0,在这个时间段内必须保证数据口上的数据稳定不变,为有效的数据。
同理,由于tPW这些延时相对较短(ns级),所以在单片里也不必考虑延时问题。
基本的读写操作实现之后,就可以根据数据手册,根据相关指令,就可以实现相应的需要的功能。
六、模块整合:
七、程序实现:
#include<
reg52.h>
intrins.h>
#defineucharunsignedchar
#defineuintunsignedint
#definejump_ROM0xCC
#definestart0x44
#defineread_EEROM0xBE
#defineROW4
ucharidatanotQuit=1;
constucharcodetable[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
constucharcodetable1[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
constucharcodeLED_W[4]={0xef,0xdf,0xbf,0x7f};
ucharidatajishi[4]={0,0,0,0};
uintidatajishuqi=0;
ucharidatai=0;
ucharidatanotChange=0;
ucharidatastart1=0;
ucharidatastop=0;
ucharidataID=0;
constucharcodeLCD_ID[ROW+1][16]={
{"
RedDecoding"
},
TempDisplay"
Timer"
Music"
"
}
};
constucharcodemusic[2][14]={{"
WishYouSafe"
},{"
LBDYHBYC"
}};
constucharcodetimer[2][6]={{"
start"
stop"
constucharcodeIr[12]={"
IRCODE:
--H"
constucharcodetem[15]={"
Nowtempis--"
sbitSpeak=P3^4;
//蜂鸣器
sbitIRIN=P3^3;
//红外接收
sbitD18B20=P3^5;
//DS18B20数据口
sbitE=P1^2;
sbitRW=P1^1;
sbitRS=P1^0;
sbitUP=P2^3;
sbitDOWN=P2^2;
sbitENTER=P2^1;
sbitEXIT=P2^0;
ucharidataIRCOM[7];
ucharidataTMPH,TMPL;
ucharidataCount;
ucharidataplay=0;
bitflag;
constucharcodeSONG[]={//祝你平安
0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20,
0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,
0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,
0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20,
0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20,
0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,
0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10,
0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80,
0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20,
0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,
0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10,
0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00,
//路边的野华不要采
0x30,0x1C,0x10,0x20,0x40,0x1C,0x10,0x18,0x10,0x20,0x10,0x1C,0x10,0x18,0x40,0x1C,
0x20,0x20,0x20,0x1C,0x20,0x18,0x20,0x20,0x80,0xFF,0x20,0x30,0x1C,0x10,0x18,0x20,
0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20,
0x30,0x80,0xFF,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,
0x20,0x2B,0x40,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,
0x20,0x2B,0x40,0x20,0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,
0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20,0x30,0x80,0x20,0x30,0x1C,0x10,0x20,
0x10,0x1C,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,0x15,0x1F,
0x05,0x20,0x10,0x1C,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,
0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,
0x20,0x26,0x20,0x20,0x20,0x30,0x30,0x20,0x30,0x1C,0x10,0x18,0x40,0x1C,0x20,0x20,
0x20,0x26,0x40,0x13,0x60,0x18,0x20,0x15,0x40,0x13,0x40,0x18,0x80,0x00,0x00
/*****延时******/
voiddelay(unsignedcharx)//x*0.14MS
{
unsignedchari;
while(x--)
{
for(i=0;
i<
13;
i++){}
}
voiddelay1(intms)//1ms
unsignedchary;
while(ms--)
for(y=0;
y<
134;
y++)
;
voiddelay2()
inti,j;
for(i=0;
=5;
i++)
for(j=0;
j<
=2;
j++);
voiddelay3()
=150;
=100;
voidjishi_Disp();
/*******数码管显示延时******/
voiddelay4()
uchari=200;
for(;
i>
0;
i--)
jishi_Disp();
/*******蜂鸣器延时*******/
voidDelay_xMs(uintx)
uinti,j;
x;
1;
//3
/********温度延时********/
voidTempDelay(ucharus)
while(us--);
/******LCD命令******/
voidenable(uchardel)
P0=del;
RS=0;
RW=0;
E=0;
delay2();
E=1;
/******LCD数据******/
voidwrite(uchardel)
RS=1;
/******LCD初始化******/
voidL1602_init(void)
enable(0x01);
enable(0x38);
enable(0x0e);
enable(0x06);
enable(0xd0);
/******LCD写字符******/
voidL1602_char(ucharhang,ucharlie,charsign)
uchara;
if(hang==1)a=0x80;
if(hang==2)a=0xc0;
a=a+lie-1;
enable(a);
write(sign);
/******LCD写字符串*****/
voidL1602_string(ucharhang,ucharlie,uchar*p)
while
(1)
if(*p=='
\0'
)break;
write(*p);
p++;
/*******初始化18B20*****/
voidInit18b20(void)
D18B20=1;
_nop_();
D18B20=0;
TempDelay(80);
//delay530uS//80
TempDelay(14);
//delay100uS//14
if(D18B20==0)
flag=1;
//detect1820success!
else
flag=0;
//detect1820fail!
TempDelay(20);
//20
D18B20=1;
/*******18B20读字节**********/
unsignedcharReadByte(void)//读取单字节
unsignedcharidatai,u=0;
i<
8;
i++)
D18B20=0;
u>
>
=1;
D18B20=1;
if(D18B20==1)
u|=0x80;
TempDelay
(2);
_nop_();
return(u);
/*********写字节**********/
voidWriteByte(ucharwr)//单字节写入
unsignedcharidatai;
for(i=0;
D18B20=wr&
0x01;
TempDelay(3);
//delay45uS//5
D18B20=1;
wr>
/*********读数据**********/
/*
voidread_bytes(ucharj)
j;
*p=ReadByte();
*/
/*********显示温度********/
voidTemp_Disp()
ucharshi=0,ge=0;
uinttemp;
Init18b20();
WriteByte(0xcc);
//skiprom
WriteByte(0x44);
//Temperatureconvert
WriteByte(0xbe);
//readTemperature
TMPL=ReadByte();
TMPH=ReadByte();
L1602_string(1,3,LCD_ID[ID]);
L1602_string(2,1,tem);
//if(TMPH&
0xfc==0xfc)
//{
//temp=(~(TMPL/16+(TMPH|0xfc)*16))+1;
//L1602_char(2,12,'
-'
);
//}
//else
temp=TMPL/16+TMPH*16;
shi=temp/10%10+0x30;
ge=temp%10+0x30;
L1602_char(2,13,shi);
L1602_char(2,14,ge);
L1602