forked from hanshuaipeng/Infrared-remote-control-cc2530
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIR.c
405 lines (334 loc) · 12.3 KB
/
IR.c
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
#include"IR.H"
/*******************************************************************************
红外结构体覆初值
********************************************************************************/
IR_T __xdata ir_packet={0xAA,0x55};//赋值数据头
unsigned int IR_hl[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//分析载波
/*******************************************************************************
红外接受数据
********************************************************************************/
unsigned char End_Flag=1;//;//用于标识结束红外数据接受
unsigned int previous=0;//前一个下降沿时间
unsigned int current=0;//当前下降沿时间
unsigned int time_fall=0; //高电平总时间
unsigned int time_X=0; // 两次时间差
unsigned char IR_Study;//标示红外学习还是发送阶段
unsigned char Cap_H=0;//捕获到的高字节
unsigned char Cap_L=0;//捕获到的低字节
unsigned char IR_Study_Num=0;//标示红外学习时间计数
unsigned char IR_Study_Flag=0;//标示红外采集到电平,采集到中断中置1,处理完成清零
unsigned char IR_Study_OVNum=0;//标示红外学习期间溢出次数
unsigned int IR_Study_FallNum=0;//标示红外从学习到结束的总时间
unsigned char hl_num=0;
/*******************************************************************************
红外发送需要变量
********************************************************************************/
unsigned int time_Tmp=0;//计算电平时间
/******************************************************************************
学习发送计数
********************************************************************************/
unsigned char signle=0;//计算红外数据个数
/*****************************************************************************
函数功能:定时器产生固定时间初始化设置
入口参数:无
出口参数:无
函数说明:本定时器在初始化中使用系统时钟,系统时钟为16M非晶振32M,32M只是用于无线使用
******************************************************************************/
void IR_Output_Init_T1()//运行于上下计数模式用于产生调制周期
{
time_Tmp=(ir_packet.ir_hl[signle++]);
//T1CC0H=time_Tmp/256;
// T1CC0L=time_Tmp%256;
T1CTL =0x04;//暂停运行
T1_Clear();//清除定时器1计数器
T1CTL =0x07; // 8分频4M,上下运行模式
T1IF =0; // 中断未挂起
T1CC0H=time_Tmp/256;
T1CC0L=time_Tmp%256;
TIMIF |= 0x40;
T1IE = 1; //关闭定时器1中断,使用查询方式
EA =1; //总中断开启
}
/*****************************************************************************
函数说明:定时器载波设置
注意:本定时器在初始化中使用系统时钟,系统时钟32M.
******************************************************************************/
void IR_Output_Init_T3(unsigned char carrier)//用于产生38K载波P17
{
T3CTL=0x3A;
T3CC0=2*carrier;//比较计数的装载数据,211产生38K方波
T3CCTL0 |=0x54;//使能中断, 切换输出、比较模式
T3IE = 1; //开启中断
EA = 1;
}
void IR_Output_Init_Var()//发送阶段初始化变量
{
IR_Study=0;//1标示学习阶段,0标示发送阶段.
}
/*******************************************************************************
函数功能:红外发送初始化
入口参数:无
出口参数:无
函数说明:定时器运行16M、自由运行模式、计数周期4.096ms。定时器1通道2上升下降沿都捕获。定时器备用位置2
采用P1.0作为采集通道,
********************************************************************************/
void IR_Output_Init(unsigned char num)//发送阶段初始化
{
IR_Output_Init_Var();//发送阶段初始化变量
IR_Output_Init_T3(num);//定时器载波,先开启
IR_Output_Init_T1();//输出初始化。后开启
}
/*******************************************************************************
函数说明:红外发送阶段
********************************************************************************/
unsigned char IR_Output_Send(unsigned char num_carrier)
{
P0DIR |= (1<<1); //P0_1 P0_0定义为输出
P0INP &= ~0x02;//P0_1定义为普通I/O
IR_OUT=0;//初始化为0.不输出红外
// PICTL |= 0x80;//最大驱动能力
signle=1;//从1开始发送
IR_Output_Init(num_carrier);
while(ir_packet.len-1>signle);
//P0INP |= 0x02;//P0_1定义为三态,减少输出杂波
IR_OUT=0;
T3_Stop();//关闭载波定时器
T1IE=0;//关闭T1定时器
return SUCCESS;
}
/****************************
延时函数
*****************************/
void Delayms(unsigned int xms) //i=xms 即延时i毫秒 (32M晶振时候大约数,32M需要修改,系统不修改默认使用内部16M)
{
unsigned int i,j;
for(i=xms;i>0;i--)
for(j=1560;j>0;j--);
}
/*******************************************************************************
函数功能:红外学习初始化指示灯
入口参数:无
出口参数:无
函数说明:
********************************************************************************/
void IR_Study_Init_Led()//习阶段初始化指示灯
{
P1DIR |= 1<<2;
P1DIR |= 1<<3;
P1DIR |= 1<<6;
P0DIR |= (1<<1); //P0_1 P0_0定义为输出
P0INP &= ~0x02;//P0_1定义为普通I/O
IR_OUT=0;//初始化为0.不输出红外
}
/*******************************************************************************
函数功能:红外学习初始化
入口参数:无
出口参数:无
函数说明:初始化变量、初始化定时器、
********************************************************************************/
void IR_Study_Init()
{
IR_Study_Init_Led();//初始化指示灯
IR_Study_Init_Var();//学习阶段初始化变量
IR_Study_Init_T1();//学习阶段初始化定时器T1
}
/*******************************************************************************
函数功能:红外学习初始化定时器1,用于捕获
入口参数:无
出口参数:无
函数说明:定时器运行16M、自由运行模式、计数周期4.096ms。定时器1通道2上升下降沿都捕获。定时器备用位置2
采用P1.0作为采集通道,
********************************************************************************/
void IR_Study_Init_T1()
{
T1IE = 0; //定时器中断暂时关闭
T1CTL = 0x00;//32M 暂停运行
PERCFG |= (1<<6);//采用备用位置2
P1SEL |= (1<<0); //P10作为捕获通道
T1CNTH=0;//清零定时器
T1CNTL=0;//清零定时器
T1CTL =0x05; // 32M 8分频,自由运行 计数周期65536/32M/8=2.048ms*8=16ms
T1IF =0; //定时器中断标志清零
T1CCTL2=0x42;//上升沿下降沿铺货
TIMIF |= 0x40;//其实我不是太了解该位设置
T1IE = 1; //中断启动
EA =1; //EA enable
}
/*******************************************************************************
函数功能:红外学习初始化系统变量
入口参数:无
出口参数:无
函数说明:实现采集功能
********************************************************************************/
void IR_Study_Init_Var()
{
unsigned char i;
previous=0;//前一个下降沿时间
current=0;//当前下降沿时间
End_Flag=0;//0标示不结束
hl_num=0;
time_fall=0;
signle=0;//从零计数
IR_Study=1;//1标示学习阶段,0标示发送阶段
IR_Study_Flag=0;//捕获到了电平
IR_Study_Num=0;//用于红外总学习时间计数
IR_Study_OVNum=0;//开始没有溢出
IR_Study_FallNum=0;//红外学习总时间
ir_packet.len=0;//清除上次采集到的数据长度
for(i=0;i<80;i++)
ir_packet.ir_hl[i]=0;
for(i=0;i<16;i++)//记录载波电平清零
IR_hl[i]=0x00;
}
/*******************************************************************************
函数功能:红外学习阶段学习载波
入口参数:无
出口参数:成功返回 SUCCESS,失败返回ERROR
函数说明:实现红外采集功能
********************************************************************************/
void IR_Study_HL()
{
IR_Study_Init();
}
/*******************************************************************************
函数功能:红外学习阶段
入口参数:无
出口参数:成功返回 SUCCESS,失败返回ERROR
函数说明:实现采集功能
********************************************************************************/
unsigned char IR_Study_Pro(void)
{
unsigned char i=0;
IR_Study_Init();
ir_packet.ir_hl[signle++]=0xEEEE;// 赋起始值头
BLED=0;//亮
while(End_Flag==0)
{
if(IR_Study_Flag)//从第二次捕获到数据开始进入该函数处理数据
{
current=Cap_H<<8 | Cap_L; //本次时间减去上一次铺货的时间
if(IR_Study_OVNum)//说明有溢出
{
time_X=65536-previous+current;//就是当前值,有可能短暂溢出/ 例如 |
if(IR_Study_OVNum>=2)//溢出两次,只会发生在开始和结束 /
{
if(signle<MINNUM)//说明溢出发生在开始不处理
;
else //明溢出发生在结束位置
{
End_Flag=1;//标示要结束了
if(time_fall>0)//说明还有一个数据呢,记得存
{
ir_packet.ir_hl[signle++]=(time_fall+52);//((time_fall+26) | 0x0001);//存储 上一次的时间值,并且表示高电平 减掉半波周期
time_fall=0;
}
}
}
IR_Study_OVNum=0;//溢出计数清零
}
else
time_X=current-previous;//在这捕捉的都是短时间
////200 60
if((time_X < MAXPERIOD )&&(time_X> MINPERIOD )) //25us为最小载波的周期,12.5us为最大载波的周
{
time_fall += time_X;//累计电平时间
if(hl_num < 16)// 没有执行?
{
IR_hl[hl_num++]=time_X;
}
}
else if(time_X > DATATIME )//150us作为区分载波的高电平还是正常的高电平,
{
ir_packet.ir_hl[signle++]=time_fall+52;//+53);//((time_fall+52) | 0x0001);//存储 上一次的时间值,并且表示高电平 减掉半波周期
time_fall =0x0000;
if((time_X>0x2EE0)&&(signle > MINNUM))//0x2EE0是3m说明是在结尾处出现低电平
End_Flag=1;//标示要结束了
ir_packet.ir_hl[signle++]=time_X-52;//((time_X-26) & 0xFFFE);//存储本次采集的低电平、并且表示成低电平 加半波周期
}
previous=current;// 把当前时间赋给前一个时间
IR_Study_Flag =0;//清除捕获标志位
}
else
{
if(IR_Study_FallNum>650)//10s 内未学到码制讲退出学习过程
End_Flag=2;
}
}
T1IE=0;//如果学习完成,等待再次学习。
BLED=1;//恢复亮
if(End_Flag==1)
{
ir_packet.ir_hl[signle++]=0x2323;
ir_packet.len=signle;
time_Tmp=0;//已经使用完了的数据可以重新利用了
for(i=0;i<16;i++)
time_Tmp += IR_hl[i];
ir_packet.hl= time_Tmp >> 4;
if(signle<MINNUM)
return Pro_ERROR;
else
{
// flag=1;
return SUCCESS;
}
}
else if(End_Flag==2)
return TIME_OVERFLOW;
else
return Pro_ERROR;
}
/*******************************************************************************
定时器3 中断
********************************************************************************/
#pragma vector = T3_VECTOR //定时器T3
__interrupt void T3_ISR(void)
{
T3IF =0; //清中断标志, 也可由硬件自动完成
if(signle%2==0)
IR_OUT=~IR_OUT;//载波电平 50%占空比
else
IR_OUT=0;
}
/********************************************************************
定时器中断
*********************************************************************/
#pragma vector=T1_VECTOR
__interrupt void T1_IRQ(void)
{
T1IF=0;
T1IE=0;
if(T1STAT & 0x20)//溢出中断
{
if(IR_Study==1)//学习阶段
{
IR_Study_FallNum++;
if(IR_Study_Num != 0)
{
IR_Study_Num++;//溢出总计数
IR_Study_OVNum++;//溢出短暂计数
T1STAT &= ~0x20;//清除中断标志位
}
}
else//发送阶段
{
time_Tmp=ir_packet.ir_hl[signle++];
T1CC0H=time_Tmp/256;
T1CC0L=time_Tmp%256;
T1STAT &= ~0X20;//清除通道一的标志位
}
}
if(T1STAT & 0x04)//第一次下降沿触发标志着学习的开始
{
Cap_H = T1CC2H;
Cap_L = T1CC2L;
IR_Study_Flag=1;//标示捕获到了电平
if(IR_Study_Num==0)//第一次下降沿之前该变量为0;,第一次下降沿到来,该变量+1 开始计数记录红外
{
IR_Study_Num=1;
previous= Cap_H<<8 | Cap_L ;
IR_Study_Flag=0;//第一次不需要处理数据
}
T1STAT &= ~0x04; //清除捕获标志位
}
T1IE=1;
}