自学习型的红外发射与读取之C51篇

[复制链接]
57|18
 楼主 | 2017-12-13 13:27 | 显示全部楼层 |阅读模式
自学习型的红外发射与读取之C51篇

最近帮朋友设计一个产品,用的是一个NEC型的遥控器,要进行一下改造。。。
所以在这里就在搜索一些网上的例程

考虑到成本方面,还是 C51 NUVOTON的N76
 楼主 | 2017-12-13 13:27 | 显示全部楼层
声明:以下资料来源于 技新电子!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 楼主 | 2017-12-13 13:28 | 显示全部楼层
#include "STC15W.h"
#include "intrins.h"
#include "Uart_1.h"
#include "T4_Key.h"
#include "IRM3638T.h"
#include "IAP_EEPROM.h"

#define                User_Data_LEY1                 EEPROM[0]        //
#define                User_Data_LEY2                 EEPROM[1]        //
#define                User_Data_LEY3                 EEPROM[2]        //
#define                User_ID_KEY1                         EEPROM[3]        //
#define                User_ID_KEY2                         EEPROM[4]        //
#define                User_ID_KEY3                         EEPROM[5]        //

extern bit Key_1,Key_2,Key_3;//Èý¸ö°´¼üµÄ״̬£¬È«¾Ö±äÁ¿ 1±íʾ°´Ï£¬Ã¿´ÎÓùýÖ®ºóÐèÒªÊÖ¶¯ÖÃÁã
extern bit Key_Long_1,Key_Long_2,Key_Long_3;//Èý¸ö°´¼ü£¬È«¾Ö±äÁ¿£¬1±íʾ³¤°´£¬Ã¿´ÎÓùýÖ®ºóÒªÇåÁã

extern  unsigned int Read_User_ID;//NECЭÒéµÄÓû§Âë
extern  unsigned char Read_User_Data;//NECЭÒéµÄÊý¾ÝÂë

unsigned long  EEPROM[10];
 楼主 | 2017-12-13 13:30 | 显示全部楼层
void main(void)
{
        P0M1=0;P0M0=0;P1M1=0;P1M0=0;
        P2M1=0;P2M0=0;P3M1=0;P3M0=0;
        P4M1=0;P4M0=0;P5M1=0;P5M0=0;//Éϵç³õʼ»¯ËùÓÐIO¿ÚΪÆÕͨIO
       
        P5M1=0;P5M0=0XFF;//·¢ÉäÒý½ÅÇ¿ÍÆÍì
       
        Init_Uart1();//³õʼ»¯´®¿Ú1£¬9600bps
        Init_T4();//³õʼ»¯¶¨Ê±Æ÷T4
        Init_CCP0();//³õʼ»¯CCP0ÓÃÓÚ½ÓÊÕºìÍ⣬˳±ã³õʼ»¯P55£¬ÓÃÓÚ·¢ÉäºìÍâ
        EA = 1;//´ò¿ªµ¥Æ¬»úÈ«¾ÖÖжÏ
        Delay1ms(10);
        Read_Str(EEPROM,10);
        Send_Str1("OK");
        while(1)
        {
                if(Key_Long_1)//¼ì²âµ½ KEY1 ³£°´
                {
                        Key_Long_1 = 0;
                        LED2 = 0;//LED2ÁÁÆð£¬Ö¤Ã÷¿ÉÒÔѧϰÁË
                        while(1)
                        {
                                if((Get_NEC_Message()) == 0)//Èç¹ûÕýÈ·½ÓÊÕÁËÒ»Ö¡ÐÅÏ¢²¢½âÂë³É¹¦
                                {
                                        User_ID_KEY1 = Read_User_ID;//½ÓÊÕѧϰµ½µÄNEC´úÂë
                                        User_Data_LEY1 = Read_User_Data;
                                        Save_Str(EEPROM,10);//±£´æËùÓÐÊý¾Ýµ½EEPROM
                                        Read_User_ID = 0;
                                        Read_User_Data = 0;
                                        break;
                                }
                                if(Key_1)//¼ì²âµ½µ¥´Î°´Ï£¬ÔòÍ˳öѧϰ
                                {
                                        Key_1 = 0;
                                        break;
                                }
                        }
                        LED2 = 1;//LED2¹Ø±Õ£¬Ö¤Ã÷ѧϰÍê±Ï
                }
               
                if(Key_Long_2)//¼ì²âµ½ KEY2 ³£°´
                {
                        Key_Long_2 = 0;
                        LED2 = 0;//LED2ÁÁÆð£¬Ö¤Ã÷¿ÉÒÔѧϰÁË
                        while(1)
                        {
                                if((Get_NEC_Message()) == 0)//Èç¹ûÕýÈ·½ÓÊÕÁËÒ»Ö¡ÐÅÏ¢²¢½âÂë³É¹¦
                                {
                                        User_ID_KEY2 = Read_User_ID;//½ÓÊÕѧϰµ½µÄNEC´úÂë
                                        User_Data_LEY2 = Read_User_Data;
                                        Save_Str(EEPROM,10);//±£´æËùÓÐÊý¾Ýµ½EEPROM
                                        Read_User_ID = 0;
                                        Read_User_Data = 0;
                                        break;
                                }
                                if(Key_2)//¼ì²âµ½µ¥´Î°´Ï£¬ÔòÍ˳öѧϰ
                                {
                                        Key_2 = 0;
                                        break;
                                }
                        }
                        LED2 = 1;//LED2¹Ø±Õ£¬Ö¤Ã÷ѧϰÍê±Ï
                }
               
                if(Key_Long_3)//¼ì²âµ½ KEY3 ³£°´
                {
                        Key_Long_3 = 0;
                        LED2 = 0;//LED2ÁÁÆð£¬Ö¤Ã÷¿ÉÒÔѧϰÁË
                        while(1)
                        {
                                if((Get_NEC_Message()) == 0)//Èç¹ûÕýÈ·½ÓÊÕÁËÒ»Ö¡ÐÅÏ¢²¢½âÂë³É¹¦
                                {
                                        User_ID_KEY3 = Read_User_ID;//½ÓÊÕѧϰµ½µÄNEC´úÂë
                                        User_Data_LEY3 = Read_User_Data;
                                        Save_Str(EEPROM,10);//±£´æËùÓÐÊý¾Ýµ½EEPROM
                                        Read_User_ID = 0;
                                        Read_User_Data = 0;
                                        break;
                                }
                                if(Key_3)//¼ì²âµ½µ¥´Î°´Ï£¬ÔòÍ˳öѧϰ
                                {
                                        Key_3 = 0;
                                        break;
                                }
                        }
                        LED2 = 1;//LED2¹Ø±Õ£¬Ö¤Ã÷ѧϰÍê±Ï
                }
               
                if(Key_1)//¼ì²âµ½ KEY1 °´Ï  
                {
                        Key_1 = 0;
                        Send_NEC_Message(User_ID_KEY1,User_Data_LEY1);
                       
                        Send_Data1(User_ID_KEY1>>8);
                        Send_Data1(User_ID_KEY1);
                        Send_Data1(User_Data_LEY1);
                }
               
                if(Key_2)//¼ì²âµ½ KEY2 °´Ï  
                {
                        Key_2 = 0;
                        Send_NEC_Message(User_ID_KEY2,User_Data_LEY2);
                       
                        Send_Data1(User_ID_KEY2>>8);
                        Send_Data1(User_ID_KEY2);
                        Send_Data1(User_Data_LEY2);
                }
               
                if(Key_3)//¼ì²âµ½ KEY3 °´ÏÂ
                {
                        Key_3 = 0;
                        Send_NEC_Message(User_ID_KEY3,User_Data_LEY3);
                       
                        Send_Data1(User_ID_KEY3>>8);
                        Send_Data1(User_ID_KEY3);
                        Send_Data1(User_Data_LEY3);
                }
        }
}
 楼主 | 2017-12-13 13:31 | 显示全部楼层
奥………………
乱码了!

重新纠正一下!
 楼主 | 2017-12-13 13:31 | 显示全部楼层
//作者网址:WWW.JIXIN.PRO
//内部时钟 30MHZ
#include "STC15W.h"
#include "intrins.h"
#include "Uart_1.h"
#include "T4_Key.h"
#include "IRM3638T.h"
#include "IAP_EEPROM.h"

#define                User_Data_LEY1                 EEPROM[0]        //
#define                User_Data_LEY2                 EEPROM[1]        //
#define                User_Data_LEY3                 EEPROM[2]        //
#define                User_ID_KEY1                         EEPROM[3]        //
#define                User_ID_KEY2                         EEPROM[4]        //
#define                User_ID_KEY3                         EEPROM[5]        //

extern bit Key_1,Key_2,Key_3;//三个按键的状态,全局变量 1表示按下,每次用过之后需要手动置零
extern bit Key_Long_1,Key_Long_2,Key_Long_3;//三个按键,全局变量,1表示长按,每次用过之后要清零

extern  unsigned int Read_User_ID;//NEC协议的用户码
extern  unsigned char Read_User_Data;//NEC协议的数据码

unsigned long  EEPROM[10];
 楼主 | 2017-12-13 13:32 | 显示全部楼层
void main(void)
{
        P0M1=0;P0M0=0;P1M1=0;P1M0=0;
        P2M1=0;P2M0=0;P3M1=0;P3M0=0;
        P4M1=0;P4M0=0;P5M1=0;P5M0=0;//上电初始化所有IO口为普通IO
       
        P5M1=0;P5M0=0XFF;//发射引脚强推挽
       
        Init_Uart1();//初始化串口1,9600bps
        Init_T4();//初始化定时器T4
        Init_CCP0();//初始化CCP0用于接收红外,顺便初始化P55,用于发射红外
        EA = 1;//打开单片机全局中断
        Delay1ms(10);
        Read_Str(EEPROM,10);
        Send_Str1("OK");
        while(1)
        {
                if(Key_Long_1)//检测到 KEY1 常按
                {
                        Key_Long_1 = 0;
                        LED2 = 0;//LED2亮起,证明可以学习了
                        while(1)
                        {
                                if((Get_NEC_Message()) == 0)//如果正确接收了一帧信息并解码成功
                                {
                                        User_ID_KEY1 = Read_User_ID;//接收学习到的NEC代码
                                        User_Data_LEY1 = Read_User_Data;
                                        Save_Str(EEPROM,10);//保存所有数据到EEPROM
                                        Read_User_ID = 0;
                                        Read_User_Data = 0;
                                        break;
                                }
                                if(Key_1)//检测到单次按下,则退出学习
                                {
                                        Key_1 = 0;
                                        break;
                                }
                        }
                        LED2 = 1;//LED2关闭,证明学习完毕
                }
               
                if(Key_Long_2)//检测到 KEY2 常按
                {
                        Key_Long_2 = 0;
                        LED2 = 0;//LED2亮起,证明可以学习了
                        while(1)
                        {
                                if((Get_NEC_Message()) == 0)//如果正确接收了一帧信息并解码成功
                                {
                                        User_ID_KEY2 = Read_User_ID;//接收学习到的NEC代码
                                        User_Data_LEY2 = Read_User_Data;
                                        Save_Str(EEPROM,10);//保存所有数据到EEPROM
                                        Read_User_ID = 0;
                                        Read_User_Data = 0;
                                        break;
                                }
                                if(Key_2)//检测到单次按下,则退出学习
                                {
                                        Key_2 = 0;
                                        break;
                                }
                        }
                        LED2 = 1;//LED2关闭,证明学习完毕
                }
               
                if(Key_Long_3)//检测到 KEY3 常按
                {
                        Key_Long_3 = 0;
                        LED2 = 0;//LED2亮起,证明可以学习了
                        while(1)
                        {
                                if((Get_NEC_Message()) == 0)//如果正确接收了一帧信息并解码成功
                                {
                                        User_ID_KEY3 = Read_User_ID;//接收学习到的NEC代码
                                        User_Data_LEY3 = Read_User_Data;
                                        Save_Str(EEPROM,10);//保存所有数据到EEPROM
                                        Read_User_ID = 0;
                                        Read_User_Data = 0;
                                        break;
                                }
                                if(Key_3)//检测到单次按下,则退出学习
                                {
                                        Key_3 = 0;
                                        break;
                                }
                        }
                        LED2 = 1;//LED2关闭,证明学习完毕
                }
               
                if(Key_1)//检测到 KEY1 按下  
                {
                        Key_1 = 0;
                        Send_NEC_Message(User_ID_KEY1,User_Data_LEY1);
                       
                        Send_Data1(User_ID_KEY1>>8);
                        Send_Data1(User_ID_KEY1);
                        Send_Data1(User_Data_LEY1);
                }
               
                if(Key_2)//检测到 KEY2 按下  
                {
                        Key_2 = 0;
                        Send_NEC_Message(User_ID_KEY2,User_Data_LEY2);
                       
                        Send_Data1(User_ID_KEY2>>8);
                        Send_Data1(User_ID_KEY2);
                        Send_Data1(User_Data_LEY2);
                }
               
                if(Key_3)//检测到 KEY3 按下
                {
                        Key_3 = 0;
                        Send_NEC_Message(User_ID_KEY3,User_Data_LEY3);
                       
                        Send_Data1(User_ID_KEY3>>8);
                        Send_Data1(User_ID_KEY3);
                        Send_Data1(User_Data_LEY3);
                }
        }
}
 楼主 | 2017-12-13 13:36 | 显示全部楼层
//测试串口0,与USB转串口直接连接   9600/30MHZ
//作者网址:WWW.JIXIN.PRO
#include<Uart_1.h>
bit busy1=0;//COM1用到的发送忙标志
/*******中断程序,最短程序 示范 UART1******************************************/
void INT_Uart1(void) interrupt 4
{
        if(RI)//清空读中断标志位
        {
                RI = 0;
                SBUF = SBUF;//把接收到的数据直接发送出去
                if(SBUF == 0XFA)//收到 0XFA ,单片机复位到烧写区
                        IAP_CONTR = 0x60;
        }
        if(TI)//清空发送中断标志位
        {
                TI = 0;
                busy1 = 0;
        }
}
// 描述: 串口初始化程序.
void Init_Uart1(void)
{
        SCON = 0x50;//
        AUXR |= 0x40;//定时器1,1T
        AUXR &= 0xFE;
        TMOD &= 0x0F;       
        TL1 = 0xF3;                //
        TH1 = 0XFC;//波特率设置                9600 30MHZ
        ET1 = 0;
        TR1 = 1;
        ES = 1;//允许COM1串行口中断
        //PS = 1;//COM1最高优先级中断               
}
//COM1发送一个字节
void Send_Data1(unsigned char dat)
{
        busy1 = 1;
        SBUF = dat;
        while(busy1);
        busy1 = 1;
       
}
//COM1发送一个字符串
void Send_Str1(unsigned char *s)
{
        do
                Send_Data1(*s++);
        while(*s);
}
//延时函数  主函数中使用
void Delay1ms(unsigned int a)        // 1ms @30.000MHz
{
        unsigned char i, j;
        unsigned int b=0;
        for(b=0;b<a;b++)
        {
                i = 30;
                j = 43;
                do
                {
                        while (--j);
                } while (--i);
        }
}
 楼主 | 2017-12-13 13:37 | 显示全部楼层
串口部分

串口的初始化与串口的发送数据子函数
 楼主 | 2017-12-13 13:38 | 显示全部楼层
//功能 :用于测试定时器T4的文件
//定时器每50ms扫描一次按键,若连续N次检测到按下状态则认为一次有效,将按键状态保存到一个全局变量
//主程序通过全局变量的状态判断哪个按键按下了。
//作者网址:WWW.JIXIN.PRO
#include<T4_Key.h>
#define  N_ms  2   // (N_ms+1)*25 ms 处理一次
#define         One         5   //定义单击一次需要的计数,大于这个计数的算作长按

bit Key_1=0,Key_2=0,Key_3=0;//三个按键的状态,全局变量 1表示按下 ,每次用过之后需要手动置零
bit Key_Long_1=0,Key_Long_2=0,Key_Long_3=0;//三个按键,全局变量,1表示长按,每次用过之后要清零


static unsigned char T4_Count=0;//T4中断计数器,只在这个文件里面使用
static unsigned int Key1_1=0,Key2_1=0,Key3_1=0;//检测三个按键用的临时变量

//初始化定时器T4
void Init_T4(void)
{
        //初始化T4作为MCULED指示灯
        T4T3M &= 0xDF;//12T工作模式
        T4L = 0xDC;
        T4H = 0x0B;//初始化时间  30MHZ 25MS
        //T4T3M |= 0x10;//P0.6输出T4的溢出率
        IE2 |= 0X40;//允许T4中断
        T4T3M |= 0x80;//打开T4定时器
}
//定时器T4中断服务程序 25Ms中断一次
void T4_INT(void) interrupt 20
{
        T4_Count++;
        if(T4_Count > N_ms)// (N_ms+1)*25 ms 处理一次
        {
                T4_Count = 0;
                LED1 = ~LED1;//板载LED1闪烁
               
                if(Key1_1)//如果已经按下了
                {
                        if(!KEY1)//如果第二次检测有效。
                        {
                                Key1_1 ++;
                                if(Key1_1 > One)
                                        Key_Long_1 = 1;
                        }
                        else //一旦检测到松手了,要么是单击了一次。要么是长按过后想松手了,也就是不希望发生长按的功能了
                        {
                                if(Key1_1 <= One)
                                {
                                        Key_Long_1 = 0;
                                        Key_1 = 1;
                                }
                                Key1_1 = 0;
                        }
                }
                else
                {
                        if(!KEY1)//第一次检测到按键按下
                                Key1_1++ ;//把按键状态送到临时变量里面
                        else
                        {
                                Key_Long_1 = 0;
                                Key1_1 =0;
                        }
                }
               
                if(Key2_1)//如果已经按下了
                {
                        if(!KEY2)//如果第二次检测有效。
                        {
                                Key2_1 ++;
                                if(Key2_1 > One)
                                        Key_Long_2 = 1;
                        }
                        else //一旦检测到松手了,要么是单击了一次。要么是长按过后想松手了,也就是不希望发生长按的功能了
                        {
                                if(Key2_1 <= One)
                                {
                                        Key_Long_2 = 0;
                                        Key_2 = 1;
                                }
                                Key2_1 = 0;
                        }
                }
                else
                {
                        if(!KEY2)//第一次检测到按键按下
                                Key2_1++ ;//把按键状态送到临时变量里面
                        else
                        {
                                Key_Long_2 = 0;
                                Key2_1 =0;
                        }
                }
               
                if(Key3_1)//如果已经按下了
                {
                        if(!KEY3)//如果第二次检测有效。
                        {
                                Key3_1 ++;
                                if(Key3_1 > One)
                                        Key_Long_3 = 1;
                        }
                        else //一旦检测到松手了,要么是单击了一次。要么是长按过后想松手了,也就是不希望发生长按的功能了
                        {
                                if(Key3_1 <= One)
                                {
                                        Key_Long_3 = 0;
                                        Key_3 = 1;
                                }
                                Key3_1 = 0;
                        }
                }
                else
                {
                        if(!KEY3)//第一次检测到按键按下
                                Key3_1++ ;//把按键状态送到临时变量里面
                        else
                        {
                                Key_Long_3 = 0;
                                Key3_1 =0;
                        }
                }
        }
}
//


定时器的初始化与按键数据的读取
 楼主 | 2017-12-13 13:39 | 显示全部楼层
//测试红外收发的功能   打开了CCP功能,使用了CCP0作为接收引脚,PCB丝印为A4的排母,连接红外模块的 IR
//                     发送采用模拟时序,使用P55管脚作为发送管脚,连接红外模块的  IE
//采用的编码协议为:NEC_upd6121 普通遥控器使用的协议
//单片机的频率:30MHZ    CCP运行时钟设置为12分频,为2.5MHZ
//作者网址:WWW.JIXIN.PRO
#include "IRM3638T.h"
#include "Uart_1.h"

sbit IRM_E = P5^5;//红外光发射控制引脚,高电平发射红外
sbit IRM_R = P1^1;//红外光接收引脚,正常状态高电平,接受到红外光读取到低电平

unsigned int Read_User_ID=0;//接收到的NEC协议的用户码
unsigned char Read_User_Data=0;//接收到的NEC协议的数据码

static unsigned int CCP_Bufer[70];//CCP接收缓冲区,用于接收红外数据  引导码+16位用户码+8位数据码+8位数据反码+结束码 ,共34个数据,需要68个脉宽
static unsigned char Read_F=0;//CCP中断调用,如果接收到了完整数据帧,开始解码
static unsigned char CCP_Counter=0;//CCP接收缓冲区计数用
//定义一个联合体,用于转换捕捉寄存器里面的数据 0-65535
static union
{
    unsigned int U16;
    unsigned char U8[2];
} High; //表示,处理高电平中断和处理低电平中断的临时变量


这里是 红外部分的读写与解码
 楼主 | 2017-12-13 13:48 | 显示全部楼层
//接收解码,使用CCP0。
//初始化CCP0  使用CCP0管脚,采样脉冲信号,利用捕获功能,计算高电平宽度和低电平宽度     板子上面A4排母
void Init_CCP0(void)
{
    //P_SW1 = 0X20;//CCP 全部分布到_3
    CF = 0;//PCA计数器阵列溢出标志位
    CR = 0;//PCA计数器阵列开关
    CCF2 = 0;//PCA2中断标志位
    CCF1 = 0;//PCA1中断标志位
    CCF0 = 0;//PCA0中断标志位
    CMOD = 0x00;//设置PCA时钟源1/12 & 禁止PCA定时器溢出中断 实际CCP运行频率是 2.5MHZ
    CCAPM0 = 0X71;//设置CCP0的参数,捕获模式,上升沿下降沿都捕获,允许CCP0中断
    CL = 0;
    CH = 0;//复位PCA寄存器
    CCAP0L = 0;
    CCAP0H = 0;//复位捕捉寄存器
    CR = 1;//打开PCA阵列
    Read_F = 0;//初始化时候清零
    CCP_Counter = 0;//初始化时候赋值为0
}
 楼主 | 2017-12-13 13:48 | 显示全部楼层
//PCA中断入口,具体是哪一个中断需要判断标志位
void PCA_isr(void) interrupt 7
{
    //由于只打开了CCP0中断允许,所以这里没有判断是哪一路CCP产生的中断
    CCF0 = 0;
    High.U8[0] = CCAP0H;
    High.U8[1] = CCAP0L;
    CCP_Bufer[CCP_Counter++] = High.U16;//把脉宽时间保存到数组里面
    //单片机每计数一次,表示0.4uS的时间
    //如果这个数据大于4mS小于 5mS,而且上一个数据大于8mS小于10mS,认为是一个合格的引导码
    if((CCP_Bufer[CCP_Counter-1]>10000)&&(CCP_Bufer[CCP_Counter-1]<12500)&&(CCP_Bufer[CCP_Counter-2]>20000)&&(CCP_Bufer[CCP_Counter-2]<25000))
    {
        CCP_Bufer[CCP_Counter-1] = 0;
        CCP_Bufer[CCP_Counter-2] = 0;
        CCP_Counter = 0;//用户接收的数据放到缓冲区的第0位
    }
    //接收全部协议需要66个脉宽,所以是0-65,
    if(CCP_Counter >= 65)//
    {
        Read_F = 1;
        CCP_Counter = 69;
    }
    CL = 0;
    CH = 0;//复位PCA寄存器
}
 楼主 | 2017-12-13 13:49 | 显示全部楼层
//解码CCP中断接收的数据。这个函数需要放到主函数里面循环调用才可以。
//本函数返回0表示接收到了有效数据,返回1表示没有接收到有效帧,返回2表示解码错误
//注意:接收的数据,是低位在前的。接收的那个用户码,是低八位在前。
unsigned char Get_NEC_Message(void)
{
    unsigned char i,j;
    unsigned char a[4];//将会解析出4个字节的数据, 用户码低,用户码高,数据码,数据码反码
    float b;
    if(Read_F == 1)
    {
        for(i=0; i<66; i++) //把数组里面的脉宽转换为mS的100倍。因为协议里面有0.56mS这些小数,这样便于数据分析
        {
            b = CCP_Bufer[i] ;
            b /= 10;
            b *= 4;//计算uS的数据 相当于 X0.4
            b /= 10;//mS的100倍
            CCP_Bufer[i] = b;
            //Send_Data1(CCP_Bufer[i]);//测试代码,用于串口分析接收的脉宽
        }
        j=0;
        a[0]=0;
        a[1]=0;
        a[2]=0;
        a[3]=0;
        for(i=0; i<66; i+=2) //开始解码四个字节数据
        {
            if(j < 8)
            {
                a[0] >>= 1;
                if( (CCP_Bufer[i+1]>CCP_Bufer[i]) && ((CCP_Bufer[i+1]-CCP_Bufer[i])>56) )//
                    a[0] |= 0X80;
            }
            if((j > 7) && (j < 16))
            {
                a[1] >>= 1;
                if( (CCP_Bufer[i+1]>CCP_Bufer[i]) && ((CCP_Bufer[i+1]-CCP_Bufer[i])>56) )//
                    a[1] |= 0X80;
            }
            if((j > 15) && (j < 24))
            {
                a[2] >>= 1;
                if( (CCP_Bufer[i+1]>CCP_Bufer[i]) && ((CCP_Bufer[i+1]-CCP_Bufer[i])>56) )//
                    a[2] |= 0X80;
            }
            if((j > 23) && (j < 32))
            {
                a[3] >>= 1;
                if( (CCP_Bufer[i+1]>CCP_Bufer[i]) && ((CCP_Bufer[i+1]-CCP_Bufer[i])>56) )//
                    a[3] |= 0X80;
            }
            j++;
        }
////////////测试程序,用于串口分析数据/////////////////////////////////////////////////////
//                Send_Data1(a[0]);
//                Send_Data1(a[1]);
//                Send_Data1(a[2]);
//                Send_Data1(a[3]);
//////////////////////////////////////////////////////////////////

        if((a[2]+a[3]) == 0XFF)// 用数据码和数据反码的特点验证接收数据是否正确
        {
            Read_User_ID = a[1];
            Read_User_ID <<= 8;
            Read_User_ID += a[0];
            Read_User_Data = a[2];
            Read_F = 0;//清零标志位
            CCP_Counter = 0;//这里清零后,中断里面的处理才会正常执行,否则单片机会对下一帧数据不响应
            for(i=0; i<66; i++) //清空接收数组
                CCP_Bufer[i] = 0;
            //Send_Data1(0);
            return 0;
        }
        else//解码出现错误
        {
            Read_F = 0;//清零标志位
            CCP_Counter = 0;//这里清零后,中断里面的处理才会正常执行,否则单片机会对下一帧数据不响应
            for(i=0; i<66; i++) //清空接收数组
                CCP_Bufer[i] = 0;
            Read_User_ID = 0;
            Read_User_Data =0;
            //Send_Data1(2);
            return 2;
        }
    }
    else
    {
        return 1;//表示没有接收到有效帧
    }
}
 楼主 | 2017-12-13 13:49 | 显示全部楼层
//根据协议发送数据,IO口模拟时序实现
//延时8.77us,是一个周期的1/3 的时间  一个周期26.3us,38KHZ
void Delay8_77us(void)//@30.000MHz
{
    volatile unsigned char i;
    i = 59;
    while (--i);
}
 楼主 | 2017-12-13 13:52 | 显示全部楼层
}
//载波发射
void Send_IRM(volatile unsigned int i)
{
    while(i--)
    {
        IRM_E = 1;
        Delay8_77us();
        IRM_E = 0;
        Delay8_77us();
        Delay8_77us();
    }
}
 楼主 | 2017-12-13 14:05 | 显示全部楼层
//载波不发射
void NO_Send_IRM(volatile unsigned int i)
{
    while(i--)
    {
        IRM_E = 0;
        Delay8_77us();
        Delay8_77us();
        Delay8_77us();
    }
}
 楼主 | 2017-12-13 14:19 | 显示全部楼层
//发射数据 0 ,符合NEC协议
void Send_NEC_0(void)
{
    Send_IRM(21);
    NO_Send_IRM(21);
}
//发射数据 1 ,符合NEC协议
void Send_NEC_1(void)
{
    Send_IRM(21);
    NO_Send_IRM(64);
}
 楼主 | 2017-12-13 14:19 | 显示全部楼层
//发射一帧完整的NEC信息 引导码+用户码低八位+用户码高八位+8位数据码+8位数据码的反码+结束码“0”
void Send_NEC_Message(unsigned int Code_User,unsigned char Code_Data)
{
    unsigned char i;
    unsigned int Code_User_2;
    Code_User_2 = Code_User;//使用临时变量,防止修改形参

    Send_IRM(342);
    NO_Send_IRM(171);//这两个函数构成了一个引导码

    for(i=0; i<16; i++) //发送16位的用户码
    {
        if(Code_User_2 & 0X0001)
            Send_NEC_1();
        else
            Send_NEC_0();
        Code_User_2 >>= 1;
    }

    Code_User_2 = Code_Data;
    for(i=0; i<8; i++) //发送8位的数据码
    {
        if(Code_User_2 & 0X01)
            Send_NEC_1();
        else
            Send_NEC_0();
        Code_User_2 >>= 1;
    }

    Code_User_2 = (~Code_Data);
    for(i=0; i<8; i++) //发送8位的数据码的反码
    {
        if(Code_User_2 & 0X01)
            Send_NEC_1();
        else
            Send_NEC_0();
        Code_User_2 >>= 1;
    }
    Send_NEC_0();//发送结束码
}
//
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册 手机登录

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册 手机登录
高级模式

论坛热帖

关闭

热门推荐上一条 /4 下一条

分享 快速回复 返回顶部 返回列表