完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
不用外部中断下降沿触发方式和不占用整个定时器,就普通的IO实现红外接收;我自己写了个,但是到了最后,不行不知道为什么,求大神给个好的红外接收模块,在下谢谢了~~~
if(IRIN == 0) //引导码低电平 { r_LC_L++; if(r_LC_L >= 34&&r_LC_L <= 38) { b_IR_flag = 1; } else { b_IR_flag = 0; } } if(b_IR_flag) { if(IRIN == 1) //引导码高电平 { r_LC_H++; if(r_LC_H >= 16&&r_LC_H <= 20) { b_IR_flag1 = 1; } else { b_IR_flag1 = 0; } } } if(b_IR_flag1) { for(i = 0;i < 4;i++) { for(j = 0;j < 8;j++) { value = value >> 1; while(!IRIN) //数据码低电平,位0和位1相同的部分 { r_CD_L++; } if(r_CD_L >= 420&&r_CD_L <= 620) { while(IRIN) //数据码高电平,位0和位1区别的部分 { r_CD_H++; } if(r_CD_H >= 420&&r_CD_H <= 620) //在这范围是位0 { value &= 0x7f; } else if(r_CD_H >= 1600&&r_CD_H <= 1800) //在这范围是位1 { value |= 0x80; } } } IR_Value = value; } if(IR_Value[2] = ~IR_Value[3]) //数据码的前面和后面相等时,表示解码完成 { b_IR_ok = 1; } } |
|
相关推荐
28个回答
|
|
我发一下我写的STC15的NEC码解码(不是RC5等编码),用的是外部中断+定时器(定时器只是负责自加全局计时变量,所以可以加入其它代码),不同的是思路是使用状态机,所以实时性非常强,我觉得你可以借鉴一下这个思路。我状态机的转换关系如下:
1. ERROR状态下,检测是否出现起始码,是则进入RCVDAT,否则留在ERROR 2. RCVDAT状态下且接收到32位以下,连续接收,每次如果接收到0、1则储存入中间变量tmp,接收到的位数cnt++。否则回到ERROR。 3. RCVDAT状态下且接收完32位后,进行校验(是否源码等于反码)。成功,则储存为结果addr、cmd,进入REPEAT状态,清零tmp,cnt,repeat。否则,回到ERROR 4. REPEAT状态下,如果接收到重复码,则repeat++。否则回到ERROR。 不用外部中断和定时器就只能不停地while循环扫描,实时性很低堵塞程序还容易被打断,但是也可以实现。 [C] 纯文本查看 复制代码 #ifndef _INFRA_H_#define _INFRA_H_#include "main.h"/* 红外遥控 1. INFRA->INT0->P3.2 2.使用定时器统计外部中断间隔来区分不同编码 硬件上使用上拉电阻进行反相 使用状态机实现非阻塞读取*/***it INFRA=P3^2;//INT0typedef struct s_DEV_INFRA{ u8 addr;//地址 u8 cmd;//命令 u8 repeat;//重复次数(最大255次即连按25s以上) void(*Init)(void);//初始化函数}DEV_INFRA;//外部程序接口typedef enum{ INFRARED_ERROR =0, INFRARED_11 =162, INFRARED_12 =98, INFRARED_13 =226, INFRARED_21 =34, INFRARED_22 =2, INFRARED_23 =194, INFRARED_31 =224, INFRARED_32 =168, INFRARED_33 =144, INFRARED_41 =104, INFRARED_42 =152, INFRARED_43 =176, INFRARED_51 =48, INFRARED_52 =24, INFRARED_53 =122, INFRARED_61 =16, INFRARED_62 =56, INFRARED_63 =90, INFRARED_71 =66, INFRARED_72 =74, INFRARED_73 =82 }INFRA_KEY;//遥控器编码typedef enum{ NEC_RCVDAT,//数据读取状态 NEC_REPEAT,//重复码状态 NEC_ERROR//空闲状态,未接收和接收错误状态}NEC_STAT;//状态机状态extern DEV_INFRA DEV_Infra0;void INFRA_Init(void);#endif [C] 纯文本查看 复制代码 #include"Infra.h"#include"Uart.h"#defineNEC_TIM_OVERFLOW_LENGTH_US(200)//定时器计数周期,理论上越小越好static voidNEC_Init(void);static u32NEC_GetDelay(void);DEV_INFRADEV_Infra0={0,0,0,NEC_Init};//INFRA->INT0->P3.2//TIM3,200us@30MHz//使用TIM3测量INFRA引脚上低电平之间的周期static voidNEC_Init(void){CLRBIT(P3M0,2);CLRBIT(P3M1,2);INFRA=1;IT0=1;//上升、下降沿EX0=1;T4T3M |= 0x02;//定时器时钟1T模式T3L = 0x100-(SYSCLK/1000000*NEC_TIM_OVERFLOW_LENGTH_US)%0x100;//0x90;//设置定时初值T3H = 0x100-(SYSCLK/1000000*NEC_TIM_OVERFLOW_LENGTH_US)/0x100;//0xE8;//设置定时初值SETBIT(IE2,5);//开中断T4T3M |= 0x08;//定时器3开始计时}staticu16NEC_TimCnt=0;//定时器溢出计数(周期NEC_TIM_OVERFLOW_LENGTH_US微秒)voidTIM3_ISR(void)interrupt19{NEC_TimCnt++;}//获取与上一次调用NEC_GetDelay()后的间隔static u32NEC_GetDelay(void){staticu16 lastcnt=0;u16delay=NEC_TimCnt-lastcnt;lastcnt=NEC_TimCnt;return delay*NEC_TIM_OVERFLOW_LENGTH_US;}//硬件电路上对信号做了反相,故可用下降沿计数//起始码->8位地址码->8位地址反码->8位命令码->8位命令反码->重复码->重复码->...voidINT0_ISR(void)interrupt0{u32t=0;static NEC_STAT flag=NEC_ERROR;//状态机标志//统计高低电平t=NEC_GetDelay();#ifdef_DEBUG_//sprintf("%ldt",t);//UART_SendString(str);#endifswitch(flag){caseNEC_ERROR://扫描是否出现起始码{if( t>=12000 && t<=15000 )//起始码{flag=NEC_RCVDAT;//进入数据接收状态}break;}caseNEC_RCVDAT://数据接收状态{staticu8cnt=0;//接收位数计数staticu32tmp=0;//接收if(cnt<32){tmp<<=1;cnt++;if( t>=1600 && t<= 2600)//编码1{tmp++;}else if( t>=600 &&t<=1400)//编码0{//tmp&=~(0x01);}else//都不是,发送错误{flag=NEC_ERROR;cnt=0;tmp=0;break;}}if(cnt==32)//接收完32bit{if(((u8)(tmp>>24)==(u8)(~(tmp>>16)))&&((u8)((tmp>>8))==(u8)~tmp))//地址、命令校验{DEV_Infra0.addr=tmp>>24;DEV_Infra0.cmd=~tmp&0xFF;DEV_Infra0.repeat=0;flag=NEC_REPEAT;}else//校验失败{flag=NEC_ERROR;}cnt=0;tmp=0;}break;}caseNEC_REPEAT://重复码{if( t>=30000 && t<=42000)//【这个地方与其它资料不同,并非长98ms】{flag=NEC_REPEAT;}elseif((t>=10000)&&(t<=12000)){if(DEV_Infra0.repeat<0xFF){DEV_Infra0.repeat++;}flag=NEC_REPEAT;}elseif( t>12000 && t<=15000 )//起始码{flag=NEC_RCVDAT;//进入数据接收状态}else{flag=NEC_ERROR;}break;}default:flag=NEC_ERROR;break;}} |
|
|
|
谢谢~~~
|
|
|
|
我的第一任务就是解码,不解码我没事干,不等待干吗?
|
|
|
|
不是所有的遥控器编码都具有这个特点,特别是无线的,干扰很严重,利用比例关系,还可以还原一部分***扰的脉冲
|
|
|
|
比用中断要好,为什么自己理解去
|
|
|
|
很好,学习到了很多
|
|
|
|
我最近写了个很好的红外,普通IO口就可以实现
|
|
|
|
#include
#define IR_time 100 #define IR_Sync_Max (15000/IR_time) #define IR_Sync_Min (9700/IR_time) #define IR_Sync_Divide (12375/IR_time) #define IR_Data_Max (3000/IR_time) #define IR_Data_Min (600/IR_time) #define IR_Data_Divide (1685/IR_time) #define IR_Bit_Num 32 uchar r_IR_SyCnt; uchar r_bitcnt; uchar IR_datashif; uchar IR_data; uchar IR_code; uchar IR_UserH; uchar IR_UserL; bit b_IR_temp; bit b_IR_State; bit b_Sync; bit b_IR_ok; /*********êééÏ346P*******/ void IR_on(void) { uchar Sync_time; r_IR_SyCnt++; b_IR_temp = b_IR_State; b_IR_State = IRIN; if(b_key_IR) { if(b_IR_temp&&!b_IR_State) { Sync_time = r_IR_SyCnt; r_IR_SyCnt = 0; if(Sync_time > IR_Sync_Max) {b_Sync = 0;} else if(Sync_time >= IR_Sync_Min) { if(Sync_time >= IR_Sync_Divide) { b_Sync = 1; r_bitcnt = IR_Bit_Num; } } else if(b_Sync) { if((Sync_time < IR_Data_Min)|(Sync_time > IR_Data_Max)) {b_Sync = 0;} else { IR_datashif >>= 1; if(Sync_time >= IR_Data_Divide) {IR_datashif |= 0x80;} if(--r_bitcnt == 0) { b_Sync = 0; if(~IR_datashif == IR_data) { IR_code = IR_data; b_IR_ok = 1; } } } if((r_bitcnt&7) == 0) { IR_UserH = IR_UserL; IR_UserL = IR_data; IR_data = IR_datashif; } } } } } 这是我写的红外,普通IO口就可以实现,不占用CPU资源,不影响其他任务的工作,现在分享出来,谢谢~~~ |
|
|
|
你好! 红外解码建议采用波形记录型,这样可以做成万用型的学习型遥控器; 这是一个学习型红外遥控器模块,采用的是波形记录形式 https://bbs.elecfans.com/jishu_1905959_1_1.html 带有上位机功能:显示解码数据、显示红外波形,以及红外发射按键 |
|
|
|
只有小组成员才能发言,加入小组>>
3278 浏览 9 评论
2951 浏览 16 评论
3455 浏览 1 评论
8984 浏览 16 评论
4045 浏览 18 评论
1094浏览 3评论
567浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
564浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2299浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1855浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-20 04:49 , Processed in 1.232297 second(s), Total 68, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号