【Proteus仿真】51单片机红外无线通信实验

【Proteus仿真】51单片机红外无线通信实验


  • Proteus仿真
    在这里插入图片描述
  • 使用说明

接收端的单片机加载接收端的Hex文件,发射端加载发射端的Hex文件,仿真过程中,接收端响应有点慢,当长时间无数据发送时,接收端LCD12864屏幕会不显示的bug问题,基本可以实现功能的仿真,但是不是很完美。

接收端主程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#include<reg52.h>
#include"12864.h"
#include<intrins.h> //包含\_nop\_()函数定义的头文件
sbit IR=P3^2; //将IR位定义为P3.2引脚,必须带外部中断的引脚
unsigned char a[4]; //储存用户码、用户反码与键数据码、键数据反码
unsigned char zai=0,om,pm,qm;

unsigned int LowTime,HighTime; //储存高、低电平的宽度
void fenjie()
{
if(a[2]==0x80)
zai=0;
else if(a[2]==0xc0)
zai=1;
else
{
om=a[2]/100;
pm=a[2]/10%10;
qm=a[2]%100%10;
}

}
bit DeCode(void)
{

unsigned char i,j;
unsigned char temp; //储存解码出的数据
for(i=0;i<4;i++) //连续读取4个用户码和键数据码
{
for(j=0;j<8;j++) //每个码有8位数字
{
temp=temp>>1; //temp中的各数据位右移一位,因为先读出的是高位数据
TH0=0; //定时器清0
TL0=0; //定时器清0
TR0=1; //开启定时器T0
while(IR==0) //如果是低电平就等待
; //低电平计时
TR0=0; //关闭定时器T0
LowTime=TH0\*256+TL0; //保存低电平宽度
TH0=0; //定时器清0
TL0=0; //定时器清0
TR0=1; //开启定时器T0
while(IR==1) //如果是高电平就等待
;
TR0=0; //关闭定时器T0
HighTime=TH0\*256+TL0; //保存高电平宽度
if((LowTime<360)||(LowTime>680))
return 0; //如果低电平长度不在合理范围,则认为出错,停止解码
if((HighTime>400)&&(HighTime<680)) //如果高电平时间在560微秒左右,即计数560/1.085=516次
temp=temp&0x7f; //(520-100=420, 520+100=620),则该位是0
if((HighTime>1400)&&(HighTime<1850)) //如果高电平时间在1680微秒左右,即计数1680/1.085=1548次
temp=temp|0x80; //(1550-250=1300,1550+250=1800),则该位是1
}
a[i]=temp; //将解码出的字节值储存在a[i]
}
if(a[2]=~a[3]) //验证键数据码和其反码是否相等,一般情况下不必验证用户码
return 1; //解码正确,返回1
return 0;
}
void init(void)
{
E=1;
CS1=0;CS2=0;
lcd\_clear();
lcd\_init();
EA=1; //开启总中断

ET0=1; //定时器T0中断允许
IT0=1; //外中断的下降沿触发
TMOD=0x01; //使用定时器T0的模式1
TR0=0; //定时器T0关闭
EX0=1; //开外中断0

}
void display()
{
CS1=0;
CS2=1;
lcd\_mwc(0xb8); // 无线环境监测
lcd\_mwc(0x50);
dispm\_zi\_up(&WUYOU[0][0]);
dispm\_zi\_up(&XIAN);
dispm\_zi\_up(&HUAN);



lcd\_mwc(0xb9);
lcd\_mwc(0x50);
dispm\_zi\_down(&WUYOU[0][0]);
dispm\_zi\_down(&XIAN);
dispm\_zi\_down(&HUAN);


lcd\_mwc(0xba); // 温度
lcd\_mwc(0x40);
dispm\_zi\_up(&WEN);
dispm\_zi\_up(&DU);
dispm\_zi\_up(&MAOHAO);
dispm\_zi\_up(&SHUZI[om][0]);

lcd\_mwc(0xbb);
lcd\_mwc(0x40);
dispm\_zi\_down(&WEN);
dispm\_zi\_down(&DU);
dispm\_zi\_down(&MAOHAO);
dispm\_zi\_down(&SHUZI[om][0]);

lcd\_mwc(0xbc); //亮度
lcd\_mwc(0x40);
dispm\_zi\_up(&LIANG);
dispm\_zi\_up(&DU);
dispm\_zi\_up(&MAOHAO);

lcd\_mwc(0xbd);
lcd\_mwc(0x40);
dispm\_zi\_down(&LIANG);
dispm\_zi\_down(&DU);
dispm\_zi\_down(&MAOHAO);

CS1=1;
CS2=0;
lcd\_mwc(0xb8); // 无线环境监测
lcd\_mwc(0x40);
dispm\_zi\_up(&JING);
dispm\_zi\_up(&JIAN);
dispm\_zi\_up(&CE);

lcd\_mwc(0xb9);
lcd\_mwc(0x40);
dispm\_zi\_down(&JING);
dispm\_zi\_down(&JIAN);
dispm\_zi\_down(&CE);

lcd\_mwc(0xba); // 温度
lcd\_mwc(0x40);
dispm\_zi\_up(&SHUZI[pm][0]);
dispm\_zi\_up(&SHUZI[qm][0]);
dispm\_zi\_up(&DUHAO);

lcd\_mwc(0xbb);
lcd\_mwc(0x40);
dispm\_zi\_down(&SHUZI[pm][0]);
dispm\_zi\_down(&SHUZI[qm][0]);
dispm\_zi\_down(&DUHAO);

lcd\_mwc(0xbc); //亮度
lcd\_mwc(0x40);
dispm\_zi\_up(&WUYOU[zai][0]);

lcd\_mwc(0xbd);
lcd\_mwc(0x40);
dispm\_zi\_down(&WUYOU[zai][0]);

}
void main(void)
{
init();
while(1)
{
// fenjie();
display();
}

}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
函数功能:红外线触发的外中断处理函数
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void Int0(void) interrupt 0
{
EX0=0; //关闭外中断0,不再接收二次红外信号的中断,只解码当前红外信号
TH0=0; //定时器T0的高8位清0
TL0=0; //定时器T0的低8位清0
TR0=1; //开启定时器T0
while(IR==0); //如果是低电平就等待,给引导码低电平计时
TR0=0; //关闭定时器T0
LowTime=TH0\*256+TL0; //保存低电平时间
if(((LowTime>8500)&&(LowTime<9500))!=1) {EX0=1;return;}
TH0=0; //定时器T0的高8位清0
TL0=0; //定时器T0的低8位清0
fenjie(); TR0=1; //开启定时器T0
while(IR==1); //如果是高电平就等待,给引导码高电平计时


TR0=0; //关闭定时器T0
HighTime=TH0\*256+TL0; //保存引导码的高电平长度
if((HighTime>4000)&&(HighTime<5000))
{
DeCode();
fenjie();
}
EX0=1;

}

发射端主程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<reg51.h> //包含单片机寄存器的头文件
#include"18b20.h"
#include"lamp.h"
#include "hongwaifashe.h"
#define uchar unsigned char
#define uint unsigned int
uchar setdata[2];
void main(void)
{
while(1)
{
setdata[0]=ds18b2o\_s();
setdata[1]=lamp();
hongwaifashe();
}
}

程序源码和仿真资源

1
2
3
链接:https://pan.baidu.com/s/1BlRccMQaNfeW2xAkrJZ\_fg 
提取码:9y60