嵌入式系统试验报告
1.红外遥控解码实验
1.1 实验目的
了解红外遥控编码并用单片机捕捉信号及解码
熟悉LCD1602的驱动
1.2 实验设备
T1838一体化红外接收头
DT9122D芯片制作
89S51
1.3 实验内容
红外一体化接收头接收到红外遥控发射器所发射的信号,并将此信号进行整形和反相送入单片机端口。经过软件译码,将译码结果(按键代码)昂数码管显示。
1.4 实验预习要求
遥控编码知识
ME850单片机开发实验仪集成有一路一体化红外接收头,并配有红外发射器,能够做红外接收与解码实验
了解简单的单片机的开发的环境
要有一定的C语言基础
1.5 实验原理
所谓解码就是能用单片机把以不同宽度的脉冲区别开来,一种比较好思路就是计算两次下降沿间隔时间,当单片机外部中断1口有下降沿时中断一次,并启动定时器,定时器定50us,当下次下降沿到来时我们计算定时器中断的次数,这样我们就能很好的区分不同宽度的脉冲了。
1.6 实验步骤
将JP21的8个短接子全部用短接帽短接,使DG0-DG7与P2端口接通
将JP22的9个短接子全部用短睫毛短接,使A-DP与P0端口接通,VCC向数码管模块供电
将JP10的短接子用短接帽短接,使红外接头U16的数据线与P3.2端口接通。
将JP24的短接子用短接帽短接,禁止LCD1602显示功能,否则数码管将不能正常显示。
第一次使用遥控器要去下电池盖下的隔离胶片。
1.7 实验电路原理分析
ME850选用T1838一体化红外接收头,接受来自红外遥控器的红外遥控信号。T1838集成红外接收二极管、放大、解调、整形等电路在同一封装上。T1838负责红外遥控信号的解调,将调制在38KHZ上的红外脉冲信号解调并倒相输入到单片机的P3.2引脚,由单片机进行高电平与低电平宽度的测量
T1838的输出端通过JP10与AT89S52的P3.2连接,既可以受用中断的方式也可以使用查询方式来编程
1.8 实验参考程序分析
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit ir=P3^3;//红外端口
sbit dm=P1^4;//数码管段码控制位
sbit wm=P1^5;//数码管位码控制位
sbit led_cs=P1^6;//LED控制位
sbit rs=P3^5;//1602数据命令选择端
sbit en=P3^4;//1602使能信号
uchar num;
uchar key_code=0;//遥控键值
uchar new_code=0;//有无新按键
uint buf_key_code=0;//键值暂存
uchar key_bit_count=0;//键编码脉冲计数
uint count=0;//定时中断次数计数
uint buf_count=0;//定时中断计数暂存
uchar common_code_count=0;//前导码脉冲计数
uchar ir_status=0;//脉冲接收器所处的状态,0:无信号,1:系统码接收区,2:数据编码接收区
uchar code table[]="EE01 DEMO:IR";
uchar code table1[]="code:";
uchar code table2[]={'0','1','2','3','4','5','6','7','8','9',};
void delay_10us(unsigned char y)///延时子程序10us
{
unsigned char x;
for(x=y;x>0;x--);
}
void delay_ms(uint z)//延时子程序1ms
{
uint x,y;
for(x=z;x>0;x--)
for(y=113;y>0;y--);
}
void init(void)/////初始化
{
ir=1; //红外端口写1
led_cs=0; //关闭LED
EA=1; //开总中断
TMOD=0x02; //定时器0,模式2,8位自动装载模式
TH0=0Xd1; //定时50us
TL0=0Xd1;
IT1=1; //INT1下降沿触发
ET0=1; //允许定时器中断
EX1=1; //允许外部中断
}
/***********************************************
定时器中断
***********************************************/
void time0() interrupt 1///定时器中断
{
count++;//定时器中断次数累加
}
/**********************************************
外部中断,红外解码程序
**********************************************/
void int1() interrupt 2///外部中断
{
TR0=1;//开定时器中断
if(count>12&&count<270)//如果信号合法,则放入buf_count,count清0,对下一个脉冲信号计时
{
buf_count=count;
count=0;
}
delay_10us(10);//延时100us以消除下降沿跳变抖动
if(ir==0)//INT1引脚稳定为低电平,则表法确实是信号,count重新计时,因上面延时了50us,故要补偿1次TO中断
{
count=2;
}
if(buf_count>12&&buf_count<270)//若收到的信号合法,则再进行信号分析
{
if(ir_status==0)//如果之前未收到引导码
{
if(buf_count>210&&buf_count<270)//判断是否引导码13.5ms
{
ir_status=1;//系统标记
buf_count=0;//
}
}
else if(ir_status==1)///收到引导码
{
if(common_code_count>=25)//若收完26个脉冲
{
ir_status=2;//数据解码标记
common_code_count=0;//系统码计算清零
buf_count=0;//中断计数暂存清0
}
else if((buf_count>40&&buf_count<70)||(buf_count>12&&buf_count<32))
{
buf_count=0;
common_code_count++;//每收到一个信号自加1
}
}
else if(ir_status==2)//进入数据编码接收
{
if(key_bit_count<8)//收到数据少于8位,则将收到的数据写入buf_key_code
{
if(buf_count>40&&buf_count<70)
{
buf_count=0;
buf_key_code>>=1;
buf_key_code|=0x80;//收到1
key_bit_count++;//数据脉冲累加
}
else if(buf_count>12&&buf_count<32)//收到0
{
buf_count=0;
buf_key_code>>=1;//收到0
key_bit_count++;
}
}
else //若收完8位数据则做以下处理
{
ir_status=0;//接收状态返回到空闲
key_code=buf_key_code;
key_bit_count=0;
buf_key_code=0;
buf_count=0;
TR0=0;
new_code=1;
}
}
}
}
1.9 实验结论和分析
将上面的程序写入89S51单片机中,通电后,按压遥控器上0-9按键,则实验板上的数码管就显示出对应的按键值,同时解码成功后发出声音指示
第二篇:红外遥控解码程序
1. /**************************************************************
***********
2. ** 红外遥控器解码程序(采用中断)----基于SM0038接收
芯片
3. **说明:采用P2.0口中断,可通过修改IR_IN和P2来切换中断口的选
择.
4. **使用方法: 当IR_FLAG==1时,表示有键按下,全局变量IR_KeyValue是
键号.
5. ** IR_KeyValueN--按键非码;IR_KeyValueSB--遥控器识别
码
6. ** IR_UK--用户自定义的键号
7. ** 使用此模块时应先执行 IR_Init()
8. **使用示例: if(IR_FLAG==1)
9. ** {
10.** IR_FLAG=0;//每次使用时须将标志位清零.
11.** Display_Int(IR_KeyValue,0x90);
12.** }
13.***************************************************************
**********/
14.
15.
16.#include "ir_key.h"
17.#include "delay.h"
18./**********************以下是本程序中使用到的全局变量
********************/
19.unsigned char IR_BitCnt=0;
20.unsigned char IR_KeyValue=10; //按键码(始值不能为按键号中包
含的值)
21.unsigned char IR_UK=0; //用户定义的键号
22.unsigned char IR_KeyValueN=0; //按键非码;按键码+按键非码
=0xff
23.long int IR_KeyValueSB=0; //遥控器识别码.
24.unsigned char IR_FLAG = 0; //有键按下时此标志为1 25.
26./**************************************************************
***************
27.**此结构休是为键号转换用,IR_KV为遥控器本身的键号,IR_UK为用户自
定义的按键号
28.***************************************************************
**************/
29. struct IR_KEY
30.{
31. unsigned char IR_KV;//遥控器自身键码
32. unsigned char IR_UV;//user's value
33.};
34./**************************************************************
***************
35.**通过修改结构体数组中的值来设定遥控器的键号.
36.***************************************************************
****************/
37.struct IR_KEY IR_UserKEY[IR_NUM]=
38.{
39. {68,1},{71,2},{14,3},{72,4},{73,5},{81,6},{10,7},{80,8},{74,9
},{83,10},
40. {18,11},{84,12},{78,13},{75,14},{3,15},{21,16},{86,17},{67,18
},{2,19},{76,20},
41. {82,21},{79,22},{70,23},{77,24},{69,25},{6,26},{66,27},{65,28
},{64,29},{22,30},
42. {85,31},{23,32},{9,33},{13,34},{87,35},{15,36},{8,37},{25,38}
,{24,39},{11,40},
43. {0,41},{4,42},{16,43},{19,44},{5,45},{1,46},{17,47},{95,48},{
94,49},{30,50},{26,51}
44.};
45.
46.
47./**************************************************************
***********
48.**函数名称: IR_DELAY
49.**功能描述: 用于延时.
50.**调用模块: delay.h
51.**全局变量: 无
52.***************************************************************
*************/
53.void IR_DELAY(unsigned int delayTime)
54.{
55. DELAY(delayTime);//延时8MS
56.}
57.
58.
59./**************************************************************
***********
60.**函数名称: IR_Init
61.**功能描述: 端口初始化设置,在main函数里面应先执行此函数
62.**输入变量:无
63.**返回值:无
64.**调用模块:无
65.**全局变量: IR_IN
66.***************************************************************
*************/
67.void IR_Init(void)
68.{
69. P2DIR &=~IR_IN; //端口设置为输入方向
70. P2IE |= IR_IN; //使能中断
71. P2IES |= IR_IN; //下降沿中断
72. P2IFG &=~IR_IN; //为避免程序运行后直接进中断,此处需先将中
断标志位清零
73. _EINT();
74.}
75.
76.
77./**************************************************************
***********
78.**函数名称: IR_getkey
79.**功能描述: 读取遥控器键值,包括识别码,非码
80.**输入变量: 无
81.**返回值: 无
82.**调用模块: IR_DELAY();
83.**全局变量: IR_Delay_8MS,IR_Delay8MS,IR_IN
84.***************************************************************
*************/
85.void IR_getkey(void)
86.{
87. P2IFG &=~IR_IN;
88. P2IE &=~IR_IN;
89. /**********以下是判断中断是由按键引起的***************/
90. IR_DELAY(IR_Delay_8MS); //延时0.8MS
91. if(P2IN & IR_IN) goto IR_NXT;
92. IR_DELAY(IR_Delay8MS); //延时8MS
93. if(!(P2IN & BIT0)) goto IR_NXT;
94. while(!(P2IN & IR_IN));//等待变高
95. IR_DELAY(8900); //延时5MS左右
96. if(P2IN & IR_IN) goto IR_NXT;
97. IR_FLAG = 0;
98. /********以下是读取16位识别码*******************/
99. IR_KeyValueSB=0;
100. for(IR_BitCnt=0;IR_BitCnt<16;IR_BitCnt++)
101. {
102. while(!(P2IN & IR_IN));//WAIT HIGH
103. IR_KeyValueSB >>=1;
104. IR_DELAY(IR_Delay_8MS);
105. if(P2IN & IR_IN)
106. IR_KeyValueSB |=0x80;
107. else
108. IR_KeyValueSB &=0x7f;
109. while(P2IN & IR_IN);//WAIT LOW
110. }
111. /***********以下是读取8位的键码*******************/ 112. IR_KeyValue=0;
113. for(IR_BitCnt=0;IR_BitCnt<8;IR_BitCnt++)
114. {
115. while(!(P2IN & IR_IN));//WAIT HIGH
116. IR_KeyValue >>=1;
117. IR_DELAY(IR_Delay_8MS);
118. if(P2IN & IR_IN)
119. IR_KeyValue |=0x80;
120. else
121. IR_KeyValue &=0x7f;
122. while(P2IN & IR_IN);//WAIT LOW
123.
124. }
125. /************以下是读取8位的非码****************/ 126. IR_KeyValueN=0;
127. for(IR_BitCnt=0;IR_BitCnt<8;IR_BitCnt++)
128. {
129. while(!(P2IN & IR_IN));//WAIT HIGH
130. IR_KeyValueN >>=1;
131. IR_DELAY(IR_Delay_8MS);
132. if(P2IN & IR_IN)
133. IR_KeyValueN |=0x80;
134. else
135. IR_KeyValueN &=0x7f;
136. while(P2IN & IR_IN);//WAIT LOW
137.
138. }
139. for(unsigned char i=0;i<20;i++)
140. IR_DELAY(IR_Delay8MS);
141. IR_NXT:P2IFG &=~IR_IN;
142. P2IE |=IR_IN;
143.
144. IR_FLAG=1;
145. }
146.
147.
148. /*********************************************************
****************
149. **函数名称: IR_getUK
150. **功能描述: 根据得到的IR_KeyValue从IR_UserKEY表中查出对应
的用户自定义的键值
151. **输入变量: 无
152. **返回值: 无
153. **调用模块: 无
154. **全局变
量: IR_BitCnt,IR_NUM,IR_UserKEY,IR_KeyValue,IR_UK
155. **********************************************************
******************/
156. void IR_getUK(void)
157. {
158.
159. for(IR_BitCnt=0;IR_BitCnt<IR_NUM;IR_BITCNT++) pre < ****
************************************************************************* **以下是SM0038输入信号引脚的中断函
数. **************************************************************************** } IR_UK="IR_UserKEY[IR_BitCnt].IR_UV;" if(IR_BitCnt="=IR_NUM)" return; { if(IR_KeyValue="=IR_UserKEY[IR_BitCnt].IR_KV)">
160. <SCRIPT src="/inc/gg_read2.js"></SCRIPT>