/************************************************************************************************************************ ******* 文件名: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:1us count++; //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; //数据接收buffer g_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; //1ms ET1 = 1; //使能定时器1 TR1 = 1; //启动定时器1 TH0 = 0; //定时器0装初值 TL0 = 0; //11.0592MHz 计满最大值计数值的时间为:71111us ET0 = 1; //使能定时器0 IT0 = 1; //设置外部中断0为跳变沿触发方式,从高到低的负跳变触发 EX0 = 1; //开启外部中断0 EA = 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; //先关闭外部中断0 while( WAVE_RECV ); //如果当前为高电平,则等待低电平的到来 TH0 = 0; TL0 = 0; //11.0592MHz:71111us TR0 = 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; //电平状态持续时间计数器归0 return; } else { goto DecExit; } DecExit: { //LED3 = ~LED3; //改变P1.2状态 TR0 = 0; EA = 1; //使能所有中断 EX0 = 1; //开外部中断0 TF0 = 0; //溢出标志位软件清0 return; } } /************************************************ ********** 功能:433模块退出,释放资源 ********** ************************************************/ int m433_Exit(M433_Service *p433_srv) { EA = 0; //关闭所有中断 EX0 = 0; //关闭外部中断0 TR0 = 0; //关闭定时器0 TF0 = 0; //溢出标志位软件清0 TH1 = 0; TL1 = 0; ET1 = 0; TR1 = 0; //关闭定时器1 count = 0; g_Receive = 0x0; //数据接收buffer g_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 0 P1 = g_DecData & 0xFF; P1 = (g_DecData >> 8) & 0xFF; P1 = (g_DecData >> 16) & 0xFF; //此处可以通过点亮led来验证解码的结果,我的单片机板上只有8个led灯。 #else m433Serv.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 0 if( m433_TaskSchedule( &m433Serv ) ) //433任务调度 { printf("433 module task schedule error,exit!\n"); m433_Exit( &m433Serv ); } #endif #endif TF0 = 0; //定时器0溢出标志位清0 EA = 1; //开所有中断 EX0 = 1; //重开外部中断0 g_DecOK = 1; //数据解码已经完成,可以接收新的数据了 //g_Display = 1; //解析后的数据可以送数码管显示了 g_RecvOK = 0; //解析完成,开始接收新的数据 } #if 0 if (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; }
共2条
1/1 1 跳转至页
单片机实现PT2262解码示例代码
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |