直接上图
(原文件名:TP3.jpg)
(原文件名:TP0.jpg)
(原文件名:TP1.jpg)
(原文件名:TP2.jpg)
程序如下:
/***************************************************************
作品:捕获红外发射脉冲高、低电平时间,送串口显示
单片机:STC12C5410
晶振:12M
编译环境:Keil uVision4 V9.00
***************************************************************/
// 说明:1、适用于:1T系列含有PCA捕获的STC单片机
// 2、捕获引脚PCA2(也就是P2.0),3字节存放一个电平时间数据。
// 3、串口显示脉冲高低电平时间数据(串口:字符 57600bps 校验位N 数据位8 停止位1),
// 4、含NEC、RC5解码,如需其它解码请自己加入。
//
// NEC码:(芯片有 市场上用量最大的HT6121/6122及其兼容的IC芯片等)
// RC5码:(芯片有 SAA3006、SAA3010、SAA3027、PCA8521、PT2210 等)
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#include <STC12C5410AD.h>
#include <CKA.H>
sbit IR = P2^0; //捕获引脚PCA2
uchar xdata v[486];
uchar N[4];
uint t;
ulong nn;
bit VT; //捕获完成标志
bit B_Z; //丢弃第一次捕获标志
void ChuanKou(); //串口发送主程序
void IR_RC5(); //RC5解码
/********************************************
函数:10ms × n 延时程序 STC 1T@12MHz
*********************************************/
void YS10ms(uchar n)
{
uchar i,j,k;
for(i=n;i!=0;i--)
for(j=198;j!=0;j--)
for(k=150;k!=0;k--);
}
/********************************************
函数:接收初始化
*********************************************/
void JS_Init(void)
{
uint i;
B_Z = 1;
t = 0;
for(i=0;i<486;i++)v=0; //存储区清0
EPCA_LVD = 1; //PCA模块中断和低压检测中断允许位
CCAPM2 |= 0x31; //PCA模块2:16位捕获模式,由CCP2的跳变触发。ECCF2=1,使能CCF2中断。
CMOD = 0x01; //ECF=1(CMOD.0=1)使能CF(CCON.7)位产生中断
EA = 1;
P21 = 0; //开始接收,指示灯打开
}
/********************************************
函数:主程序
*********************************************/
void main(void)
{
UartInit(12,1);
JS_Init();
YS10ms(10);
ZIFUC("\r\n\r\n\r\n ****** 开始接收,请按遥控 ******\r\n");
while(1)
{
if(VT)
{
VT = 0;
P21 = 1; //接收完成,指示灯关闭
ChuanKou(); //串口显示
YS10ms(200);
YS10ms(200);
YS10ms(200); //6秒后重新开始
JS_Init();
ZIFUC("\r\n\r\n\r\n ****** 可以重新接收,请按遥控 ******\r\n");
}
}
}
/***************************************************************
函数:PCA中断捕获程序(电位跳变捕获模式)
***************************************************************/
void PCA_isr(void) interrupt 6 using 1
{
if(CF) //是否是PCA定时器溢出
{
CF = 0; //必须软件清0 (PCA 定时器标志)
v[t]++; //PCA定时器溢出计数,保存数据最高字节
if(v[t]>1) //设置允许溢出次数,>131ms 终止捕获
{ CR = 0;
CF = 0;
CCAPM2 = 0;
CCF2=0;
VT=1; //捕获完成标志
v[t]=0;
return;
}
}
if(CCF2) //是否是电位跳变
{
CCF2 = 0; //必须软件清0 (PCA 模块2标志)
CL = 0; //先赋值低位
CH = 0;
if(B_Z){ CR =1; //启动PCA定时器
B_Z=0;
return; } //丢弃第一次捕获数据
t++;
v[t]=CCAP2H; //保存数据高字节
t++;
v[t]=CCAP2L; //保存数据低字节
t++;
}
if(t >= 486) //捕获162个数据(1个电平时间3字节存放)
{
CCAPM2 = 0;
CCF2=0;
CR = 0;
CF = 0;
VT = 1; //捕获完成标志
}
}
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:串口发送主程序
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void ChuanKou()
{
uchar i;
uint j,T;
ZIFUC("\r\n\r\n ****** 接收完成 ******");
ZIFUC("\r\n\r\n ( 以下是遥控器发射脉冲的波形数据 )");
ZIFUC("\r\n\r\n 序号 高电平时间(us) 低电平时间(us)\r\n\r\n");
i=0;
for(j=0;j<486;)
{
((uchar *)&nn)[0] = 0;
((uchar *)&nn)[1] = v[j++];
((uchar *)&nn)[2] = v[j++];
((uchar *)&nn)[3] = v[j++];
ZIFUC(" ");
JZ(i,10,2); //序号
ZIFUC(" ");
JZ(nn,10,8); //高电平时间
((uchar *)&nn)[0] = 0;
((uchar *)&nn)[1] = v[j++];
((uchar *)&nn)[2] = v[j++];
((uchar *)&nn)[3] = v[j++];
ZIFUC(" ");
JZ(nn,10,8); //低电平时间
if( (i%8)==0 )ZIFUC("\r\n\r\n");
else ZIFUC("\r\n");
i++;
}
///////////////// NEC解码 ////////////////
j=9; //引导码丢弃
for(i=0;i<32;i++)
{
j++;
((uchar *)&T)[0] = v[j++];
((uchar *)&T)[1] = v[j++];
j += 3;
N[i/8] >>= 1;
if((T<1900) && (T>1000))N[i/8] |= 0x80;
}
if(N[2] == ~N[3]) //校验NEC操作码。错误则尝试RC5解码
{
ZIFUC("\r\n 【 NEC通用编码格式:引导码 + 32位编码(16位用户码+操作码正反码) 】\r\n");
ZIFUC("\r\n 用户码(高8位):0x");
JZ(N[0],16,1);
ZIFUC("\r\n 用户码(低8位):0x");
JZ(N[1],16,1);
ZIFUC("\r\n\r\n 操作码正码 :0x");
JZ(N[2],16,1);
ZIFUC("\r\n");
if(N[0] == ~N[1])
{
ZIFUC("\r\n\r\n 经对比,16位用户码是正反码,用户码正码:0x");
JZ(N[0],16,1);
}
return;
}
///////////////// 初略分析是否是RC5编码 ////////////////
j=0;
for(i=0;i<20;i++)
{
j++; //最高位丢弃(1个数据3字节);
((uchar *)&T)[0] = v[j++];
((uchar *)&T)[1] = v[j++];
if(T<600 || T>1800) //RC5码前20个脉冲数据600<nn<1800
{
ZIFUC("\r\n 【 解码失败,再试一试或者分析波形数据 】");
return;
}
}
///////////////// 将波形数据绘成图像 ////////////////
ZIFUC("\r\n 【 RC5编码发射波形 】 发射顺序:(低位)<--(高位)\r\n");
ZIFUC("\r\n___");
j=0;
for(i=0;i<26;i++)
{
j++; //最高位丢弃(1个数据3字节);
((uchar *)&T)[0] = v[j++];
((uchar *)&T)[1] = v[j++];
if(T>2000)break;
if(i%2 != 1) //如果i是偶数
{
if(T<1000)ZIFUC("▉");
else ZIFUC("▉▉");
}
else
{
if(T<950)ZIFUC("__");
else ZIFUC("____");
}
}
ZIFUC("_____________");
ZIFUC("\r\n┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊\r\n");
IR_RC5(); //RC5解码
ZIFUC("\r\n┃起始位┃空┃ 系统位 ┃ 数据位 ┃\r\n");
ZIFUC("\r\n\r\n 【 RC5通用编码格式:14位编码 】\r\n");
ZIFUC("\r\n 起始位(2位):0x");
JZ(N[0],16,1);
ZIFUC(" 二进制: ");
JZ(N[0],2,2);
ZIFUC("\r\n 控制位(1位):");
if(N[1])ZIFUC(" 1");
else ZIFUC(" 0");
ZIFUC("\r\n 系统位(5位):0x");
JZ(N[2],16,1);
ZIFUC(" 二进制: ");
JZ(N[2],2,5);
ZIFUC("\r\n 数据位(6位):0x");
JZ(N[3],16,1);
ZIFUC(" 二进制:");
JZ(N[3],2,6);
}
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:根据收集的脉冲数据进行RC5解码
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void IR_RC5()
{
bit B_v,BV;
uchar x;
uchar n;
uint t;
BV = 1; //BV=1时检测(接收端)低电平时间,BV=0时检测(接收端)高电平时间。
x = 0;
t = 0;
N[0]=N[1]=N[2]=N[3]=0;
for(n=0;n<14;n++) //14位位码解码
{
x++; //最高位丢弃(1个数据3字节);
((uchar *)&t)[0] = v[x++];
((uchar *)&t)[1] = v[x++];
/*┈┈┈ 确认位码值 ┈┈┈*/
if(BV){ if(t < 950){B_v=1;x+=3; } //BV=1时,如果t<950uS,下次还是检测(接收端)低电平时间,且跳过高电平时间。
else {B_v=1;BV=0;} } //BV=1时,如果t>950uS,下次检测(接收端)高电平时间
else { if(t < 950){B_v=0;x+=3;}
else {B_v=0;BV=1;} }
/*┈┈┈ 装载位码值 ┈┈┈*/
if(n < 2) { N[0] >>= 1;
if(B_v)N[0] |= 0x02; }
else if(n==2) N[1] = B_v;
else if(n<8) { N[2] >>= 1;
if(B_v)N[2] |= 0x10; }
else if(n<15){ N[3] >>= 1;
if(B_v)N[3] |= 0x20; }
/*┈┈┈ 发射位码值 ┈┈┈*/
ZIFUC(" ");
if(B_v)ZIFUC("1");
else ZIFUC("0");
}
}
|