/************************************************************************************************************************
******* 文件名:Decode.c
******* 描  述:用一个外部中断IO脚配合定时器0实现对2262系列编码信号进行软解码, PT2262的输出信号经LM358整形放大后由单片机P3.2口输入,作为单片机的外部中断源。
******* 编  码:A0 -- A11 中的每bit用2bit表示:0码:00 ;1码:11
******* 硬  件:PT2262发射模块、LM358+R25.接收模块、STC89C52RC单片机
******* 晶  振:11.0592MHz
******* 日  期:2014-05-21 (zqjun@HK)
******* 说  明:1、PT2262输出编码包括8位地址码、4位数据码、1位同步码,共13位, 顺序:A0 A1 -- A10 A11 + 同步码 + A0 A1 -- A10 A11 + 同步码,连续发四次。2、四个振荡周期为1个编码计时单位,记作T,除同步码外,编码中只有2种类别的组合脉冲取名长脉冲和短脉冲,其中:长脉冲由3T高电平、1T低电平组成;短脉冲由1T高电平、3T低电平组成。3、同步码,由1T高电平31T低电平组合(实际测试同步码低电平宽度基本在10ms以上)。4、只需测量低电平或者高电平长短,即可知是长还是短脉冲,超过12T时间没有脉冲变化就有可能是同步码。
************************************************************************************************************************/#include <reg52.h>    //8051系列单片机头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Decode.h" //各种宏定义、全局变量、全局结构体声明/**************************************************
********* 功能:利用定时器1实现1ms延时 ************
**************************************************/
void T1_timer(void) interrupt 3 using 1
{TH1 = (65536 - DELAY)/256;TL1 = (65536 - DELAY)%256; //922:1ms   450:1uscount++;//LED1 = ~LED1;//改变P1.1状态
}/**************************************************
***************** 功能:xms延时 *******************
**************************************************/
void delayms(uint xms)
{uint i, j;for(i = xms; i > 0; i--) //延时xms{for(j = 110; j > 0; j--);}
}#if 0
/*****************************************************
*********** 功能:数码管显示0 ~ F之间的值 ************
*****************************************************/
/*
void display(uint arry_index)
{   dula = 1;        //开段选P0 = table[ arry_index ]; //送段选数据   dula = 0;        //关段选P0 = 0xFF;        //消影delayms(Display_DELAY);     //延时
}
*//**************************************************************************** 功能: 把十六进制数据转换为十进制数据 ************************* 返回值:转换之后结果,即十进制数据    ****************************************************************************/
/*
uint Hex2Decimal(unsigned long num)
{uint ret = 0;if( (0 <= num) && (num <= 15) ) //0 ~ F{ret = ( (num & 0x8) * 8 ) +( (num & 0x4) * 4 ) +( (num & 0x2) * 2 ) +( (num & 0x1) * 1 );return ret;}return 0;
}
*//********************************************************************
****** 功能:解析接收到的解码后的数据,送8段数码管显示解码结果 ******
********************************************************************/
/*
void Parse_DecData(unsigned long decdata)
{unsigned long temp = 0;temp = decdata & 0xF00000; //编码最高4位wela = 1;P0 = 0xFE; //第1位数码管wela = 0;//display( Hex2Decimal(temp >> 20) );display( temp >> 20 );temp = decdata & 0x0F0000;wela = 1;P0 = 0xFD; //第2位数码管wela = 0;//display( Hex2Decimal(temp >> 16) );display( temp >> 16 );temp = decdata & 0x00F000;wela = 1;P0 = 0xFB; //第3位数码管wela = 0;//display( Hex2Decimal(temp >> 12) );display( temp >> 12 );temp = decdata & 0x000F00;wela = 1;P0 = 0xF7; //第4位数码管wela = 0;//display( Hex2Decimal(temp >> 8) );display( temp >> 8 );temp = decdata & 0x0000F0;wela = 1;P0 = 0xEF; //第5位数码管wela = 0;//display( Hex2Decimal(temp >> 4) );display( temp >> 4 );temp = decdata & 0x00000F; //编码最低4位wela = 1;P0 = 0xDF; //第6位数码管wela = 0;//display( Hex2Decimal(temp) );display( temp );return;
}
*/
#endif/*************************************************
********** 功能:十六进制数据比较大小 ************
*************************************************/
/*
int HexDataCompare(unsigned long data_recv, unsigned long data_base)
{if( (data_recv == 0) || (data_base == 0) ){return -1; }unsigned int i;unsigned long temp = data_recv;for (i = 0; i < 4; i++){temp = data_recv & 0xFF;}return 0;
}
*//**********************************************
************ 功能:全局变量预初始化 *************
**********************************************/
int PrevInitial(M433_Service *p433_srv)
{//g_Display = 0; //数码管显示全局控制标志uchar i;for (i = 0; i < NODE_MAX; i++){memset( &p433_srv->m433CodeTable[i], 0, sizeof(p433_srv->m433CodeTable[i]) );}p433_srv->m433WorkMode = MODE_NORMAL; //1, 初始化为正常工作模式p433_srv->m433_DecData_Learn = 0x0; //新对码值p433_srv->m433_DecData_Curr = 0x0; //当前接收到的编码信号值//p433_srv->m433_DecData_Prev = 0x0; //以前接收到的编码信号值p433_srv->m433_DevCount = 0; //已经对码的设备计数器p433_srv->m433_LearnStart = 0; //学习对码开始p433_srv->m433_LearnOK = 0; //学习对码成功p433_srv->m433_Enable = 1; //使能433模块count = 0;g_Receive = 0x0; //数据接收bufferg_DecData = 0x0; //待解码buffer,数据接收buffer的备份g_RecvOK = 0;     //接收完成标志g_DecOK = 1;   //解码完成标志,第一次进来置1以获取接收后的数据g_Running = 1; //循环检测开启return 0;
}/***************************************************************
******************** 功能:单片机中断系统初始化 **********************
***************************************************************/
void MCU_Int_Initial( void )
{TMOD = 0x11; //设置定时器0和1的工作方式1:16位定时器TH1 = (65536 - DELAY)/256;TL1 = (65536 - DELAY)%256; //1msET1 = 1; //使能定时器1TR1 = 1; //启动定时器1TH0 = 0; //定时器0装初值TL0 = 0; //11.0592MHz 计满最大值计数值的时间为:71111usET0 = 1; //使能定时器0IT0 = 1; //设置外部中断0为跳变沿触发方式,从高到低的负跳变触发EX0 = 1; //开启外部中断0EA = 1;  //开启所有中断
}/*********************************************************************
************** 功能: 外部中断0服务函数,实现对2262解码 ***************
************** 中断功能开启后,下降沿触发中断进入此函数 **************
*********************************************************************/
void INT0_ISR(void) interrupt 0 using 1
{unsigned char i = 0;unsigned char j = 0;unsigned int Low_Level_Count = 0;  //低电平状态持续时间计数器unsigned int Wide_Low = 0;   //宽脉冲低电平持续时间unsigned int Narrow_Low = 0; //窄脉冲低电平持续时间EX0 = 0; //先关闭外部中断0while( WAVE_RECV ); //如果当前为高电平,则等待低电平的到来TH0 = 0;TL0 = 0; //11.0592MHz:71111usTR0 = 1; //启动定时器0,开始测量低电平的宽度,检测同步码while( ! WAVE_RECV ) //中断进入时当前为低电平状态{if( TF0 == 1 ) //如果定时器溢出,TF0位由硬件置1{goto DecExit; //定时器超时溢出则退出}}TR0 = 0; //电平状态发生变化,停止timer0计数,取得当前计数值Low_Level_Count = TH0;Low_Level_Count = Low_Level_Count << 8;Low_Level_Count = Low_Level_Count + TL0; //根据定时器计数值取得低电平的宽度//if( ((TIME_SYNC - TIME_SYNC_RANDOM) < Low_Level_Count) && (!g_RecvOK) ) //判断电平宽度,检测是否为同步码,事实上超过10ms即有可能为同步头if( ((TIME_SYNC_COMMON - TIME_SYNC_RANDOM) < Low_Level_Count) && (!g_RecvOK) ) //判断电平宽度,检测是否为同步码,超过8.5ms即有可能为同步头{//LED0 = ~LED0;Wide_Low = Low_Level_Count / 32; //根据同步码低电平宽度取得宽脉冲低电平宽度值Narrow_Low = Low_Level_Count / 11; //根据同步码低电平宽度取得窄脉冲低电平宽度值g_Receive = 0x0;for( i = 0; i < 24; i++ ) //循环24次解码{while( WAVE_RECV ); //如果当前高电平状态,则等待低电平到来TH0 = 0;TL0 = 0; //定时器重装初值TR0 = 1; //电平变化,开启定时器0 ,测量低电平的宽度while( ! WAVE_RECV ) {if( TF0 == 1 ) {goto DecExit; //如果定时0溢出则退出} }TR0 = 0; //电平状态发生变化,停止计数Low_Level_Count = TH0;Low_Level_Count = Low_Level_Count << 8;Low_Level_Count = Low_Level_Count + TL0; //根据定时器0计数值取得低电平的宽度//if( ((TIME_BIT1 - TIME_BIT_RANDOM) < Low_Level_Count) && (Low_Level_Count < (TIME_BIT1 + TIME_BIT_RANDOM)) )//宽脉冲的低电平宽度:1表示if( ((Wide_Low - TIME_BIT_RANDOM) < Low_Level_Count) && (Low_Level_Count < (Wide_Low + TIME_BIT_RANDOM)) ) //宽脉冲的低电平宽度:1表示{g_Receive = g_Receive << 1;g_Receive = g_Receive + 0x01; //存入1}//else if( ((TIME_BIT0 - TIME_BIT_RANDOM) < Low_Level_Count) && (Low_Level_Count < (TIME_BIT0 + TIME_BIT_RANDOM)) ) //判断窄脉冲低电平宽度:0表示else if( ((Narrow_Low - TIME_BIT_RANDOM) < Low_Level_Count) && (Low_Level_Count < (Narrow_Low + TIME_BIT_RANDOM)) ) //窄脉冲低电平宽度:0表示{g_Receive = g_Receive << 1;//g_Receive = g_Receive + 0x00; //存入0}else {goto DecExit; //在24个脉冲周期上,有一个在时间上匹配,则表明收到的为干扰波,丢弃掉}if( g_DecOK == 1 ) //如果接收到的数据已经解码处理完成,再重新获取新的数据{//LED1 = ~LED1;g_DecData = g_Receive;}}//g_Display = 0;//禁止向数码管送数据g_RecvOK = 1; //数据接收完毕,等待解析g_DecOK = 0;  //数据等待解析,重置解码标志Low_Level_Count = 0; //电平状态持续时间计数器归0return;}else {goto DecExit;}DecExit:{//LED3 = ~LED3; //改变P1.2状态TR0 = 0;EA = 1; //使能所有中断 EX0 = 1; //开外部中断0TF0 = 0; //溢出标志位软件清0return; }
} /************************************************
********** 功能:433模块退出,释放资源 **********
************************************************/
int m433_Exit(M433_Service *p433_srv)
{EA = 0;  //关闭所有中断 EX0 = 0; //关闭外部中断0TR0 = 0; //关闭定时器0TF0 = 0; //溢出标志位软件清0TH1 = 0; TL1 = 0; ET1 = 0; TR1 = 0; //关闭定时器1count = 0;g_Receive = 0x0; //数据接收bufferg_DecData = 0x0; //待解码buffer,数据接收buffer的备份g_RecvOK = 0;     //接收完成标志g_DecOK = 0;   //解码完成标志,第一次进来置1以获取接收后的数据p433_srv->m433_Enable = 0;p433_srv->m433_LearnStart = 0;p433_srv->m433_LearnOK = 0;p433_srv->m433WorkMode = MODE_NORMAL; //1, 初始化为正常工作模式p433_srv->m433_DecData_Learn = 0x0; //新对码值p433_srv->m433_DecData_Curr = 0x0; //当前值//p433_srv->m433_DecData_Prev = 0x0; //以前接收到的编码信号值p433_srv->m433_DevCount = 0;g_Running = 0; //停止循环检测return 0;
}/*********************************************************************
************************** main function *****************************
*********************************************************************/
int main(void)
{unsigned char i = 0;unsigned long dec_Data = 0x0; //解码后的24位编码M433_Service m433Serv; //struct.if( PrevInitial( &m433Serv ) ) //初始化全局变量{m433_Exit( &m433Serv );return -1; }MCU_Int_Initial(); //中断、定时器/计数器初始化/**解析接收到的码值**/while( g_Running ){if( g_RecvOK ) //数据接收完成,等待解码{g_DecOK = 0; //置位0,表示数据解析还未完成#if 0P1 = g_DecData & 0xFF; P1 = (g_DecData >> 8) & 0xFF;P1 = (g_DecData >> 16) & 0xFF; //此处可以通过点亮led来验证解码的结果,我的单片机板上只有8个led灯。#elsem433Serv.m433_DecData_Curr = g_DecData;//if( 1 == m433Serv.m433_LearnStart ) //是否开始学习对码//{//    //m433Serv.m433_DecData_Prev = g_DecData; //开始对码,首先更新的之前保存的对码信号值 //    //m433Serv.m433_DecData_Learn = g_DecData; //新的编码信号值 //}if( m433Serv.m433_DecData_Curr == CTRL_KEY_ENABLE ) //======> 按键A:布防 <======{m433Serv.m433WorkMode = MODE_NORMAL; //1, 初始化为正常工作模式m433Serv.m433_Enable = 1; //使能433报警探测功能//LED0 = ~LED0;}else if( m433Serv.m433_DecData_Curr == CTRL_KEY_DISABLE ) //======> 按键B:撤防 <======{m433Serv.m433WorkMode = MODE_SLEEP; //睡眠模式,不输出报警信息m433Serv.m433_Enable = 0; //关闭433报警探测功能//LED1 = ~LED1;}else if( m433Serv.m433_DecData_Curr == CTRL_KEY_LEARNING ) //======> 按键C:学习对码 <======{m433Serv.m433WorkMode = MODE_LEARNING;//学习对码模式,把接下来收到的新编码存入码表//LED2 = ~LED2;}else if( m433Serv.m433_DecData_Curr == CTRL_KEY_TEST ) //======> 按键D:测试对码是否生效 <======{if( 1 == m433Serv.m433_LearnOK ) //学习对码成功,才可以测试新加入的设备是否生效{m433Serv.m433WorkMode = MODE_TEST; //测试模式,匹配新报警设备的报警信号}else{m433Serv.m433WorkMode = MODE_NORMAL; //对码不成功则依旧进入正常工作模式继续探测}//LED3 = ~LED3;}else //=============>四按键钥匙以外的编码信号到来<============={    if( (1 == m433Serv.m433_LearnStart) && (0 == m433Serv.m433_LearnOK) ){m433Serv.m433WorkMode = MODE_LEARNING; //如果对码模式已经开启,则进入对码模式开始学习新的编码信号值        }else{m433Serv.m433WorkMode = MODE_NORMAL; //非对码模式则默认为正常工作模式}LED4 = ~LED4;}if( 0 == m433Serv.m433_Enable ) //如果未开启433布防功能{LED5 = ~LED5; }#if 0if( m433_TaskSchedule( &m433Serv ) ) //433任务调度{printf("433 module task schedule error,exit!\n");m433_Exit( &m433Serv );}#endif#endifTF0 = 0; //定时器0溢出标志位清0EA = 1;  //开所有中断EX0 = 1; //重开外部中断0g_DecOK = 1;   //数据解码已经完成,可以接收新的数据了//g_Display = 1; //解析后的数据可以送数码管显示了 g_RecvOK = 0;  //解析完成,开始接收新的数据}#if 0if (g_Display){g_Display = 0;//Show_Data = 0x5555C0;Parse_DecData( Show_Data ); //解析编码数据,分位送8段数码管显示}//if (count == 250)//250ms间隔闪烁//{//   count = 0;//   LED0 = ~LED0;//改变P1.0状态//}
#endif}m433_Exit( &m433Serv );return 0;
}

单片机实现PT2262解码示例代码相关推荐

  1. 单片机实现PT2262解码原理

    1.ASK调制: "幅移键控"又称为"振幅键控",也有称为"开关键控"(通断键控),所以又记作OOK信号.ASK是一种相对简单的调制方式.幅 ...

  2. 二维码编解码 Java调用示例代码

    二维码编解码 支持二维码的生成与识别.二维码生成时,直接返回生成的二维码图片 二维码生成 复制代码 二维码解码 复制代码 注意,该示例代码仅适用于 www.apishop.net网站下API 使用该产 ...

  3. ABOV单片机UART串口通讯实现讲解及示例代码-[MC96F6332D]

    一.准备工作 1.KEIL C51编译环境 2.CodeGen8 代码生成器 3.MC96F6332D 开发板 4.USB-OCD II仿真器 二.生成串口通讯代码 1.在CodeGen8 代码生成器 ...

  4. ABOV单片机内部中断优先级寄存器IP1x/IPx的设置代码实现讲解及示例代码-[MC96F6332D]

    一.准备工作 1.KEIL C51编译环境 2.外部中断EINT示例代码-MC96F6332D 3.MC96F6332D 开发板 4.USB-OCD II仿真器 二.代码部分 1.现代单片机MC96F ...

  5. ABOV单片机UART串口通讯中Printf函数实现讲解及示例代码-[MC96F6332D]

    一.准备工作 1.KEIL C51编译环境 2.CodeGen8 代码生成器 3.MC96F6332D 开发板 4.USB-OCD II仿真器 二.生成串口代码 1.在CodeGen8 代码生成器的外 ...

  6. STC单片机获取红外解码从串口输出

    STC单片机获取红外解码从串口输出 串口数据演示 所使用的红外接收头VS1838 VS1838引脚定义 电气特性 所使用的红外按键板 红外遥控接收模块 VS/HX1838 相关的资料: https:/ ...

  7. python开源项目及示例代码

    1 算法 1.1 字符串处理 re 正则表达式的标准库. StringIO / cStringIO 以读写文件的方式来操作字符串(有点类似于内存文件). cStringIO 是 C 语言实现的,提供高 ...

  8. 单片机18b20c语言程序,AVR单片机控制DS18B20的示例C程序

    原标题:AVR单片机控制DS18B20的示例C程序 #include #include #include #include unsigned char data_H, data_L,wendu; un ...

  9. python项目实例代码-python开源项目及示例代码

    下面列出的各种 Python 库/模块/工具,如果名称带超链接,说明是第三方的:否则是 Python 语言内置的. 1 算法 1.1 字符串处理 re 正则表达式的标准库. StringIO / cS ...

最新文章

  1. 省钱之道--图解域域树域林根域的含义
  2. 对于ESP8266-340模块改成MicroPytyhon模块
  3. 数据库中char与varchar类型的区别
  4. 1.9 matlab字符与字符串
  5. PMcaff课堂干货实录 | 社交产品骨灰大神:千万级社交产品是怎样炼成的
  6. Linux crontab定时执行任务
  7. horizon client 无法识别域_「领域驱动设计DDD」事件风暴简介:实现域驱动设计的简便方法...
  8. vue数组对象双向绑定
  9. 后端架构高可用可伸缩
  10. java例程练习(多线程[线程同步问题])
  11. 主打轻薄长续航搭载骁龙730 联想Z6发布 1899元起!
  12. python 虚线_Python 包安装和管理工具 pip 19.2 发布
  13. 10分钟 教你学会Linux/Unix下的vi文本编辑器
  14. Linux 基金会成立持续交付基金会
  15. 如何使用计算机小学生课件,小学生计算机课件
  16. 【历史上的今天】5 月 19 日:Java 之父诞生;中国首家互联网公司成立;CP/M 操作系统发明者出生
  17. SDN网络下有哪些SDN交换机选择?
  18. 什么是横向扩展、纵向扩展?
  19. ACM顶会CIKM 2022放榜!度小满AI Lab三篇入选
  20. 人脸服务器如何与门禁系统对接,安全升级!人脸识别门禁终端集门禁考勤访客对讲一步到位...

热门文章

  1. 抽象方法和抽象类规则
  2. Python生成英文大小写和数字的随机数
  3. Vultr VPS开放HTTP端口
  4. 仿蜜蜂视频TV实现gridview选中放大,并且放大时弹出底部说明
  5. Linux内核编译基础
  6. 云豹短视频app源码中,标签选择功能的实现
  7. 多线程的实现与多线程的同步机制-让你轻松掌握多线程编程
  8. 话单数据采集简单了解
  9. 计算机专业研究生职业生涯规划
  10. mapping.xml POJO的映射文件