天热了坐着就不站着、躺着就不坐着,风扇手动换挡简直很要命,某宝买了一个遥控改装后按键失去作用了很不爽,于是自己换芯片改装呗,第一次做红外遥控不知所措,百度一堆解码过程最多的就是使用定时器判断解码 ,后来找到一种简单的解码就是通过PWM输入捕获,判断两个下降沿的宽度完成解码,标准NEC协议则是 同步(9+4.5ms) 、数据1 (2.25ms),数据 0(1.12ms),具体可参考协议。
于是开搞了 第一次用了PIC16F616 做完发现芯片内存不够,于是转STM8S003 ,记录一下调试代码:
方法则是采用TIM1 捕获信号的下降沿 ,TIM2 则记录输入空闲时间 ,当超过设定空闲时间后认为当前帧已经结束了(有的遥控发出的信息会多2bit ,至今不明原因所以采用此方法)
#include "time.h"
#include "iostm8s003f3.h"
#include "sys.h"
#define CAPSIZEMAX 100
uint16_t captureint[CAPSIZEMAX]={0};
uint8_t capcount =0;
uint8_t lastcapcount =0;
uint16_t caplasttiak =0;
void time_s_init(void)//tim2
{
TIM2_IER = 0x00;
//分频值(1024分频)16MHZ / 1024 = 15,625HZ,fCK_CNT =fCK_PSC / 2 ^(PSCR[3:0])
TIM2_PSCR =0xf;//15 ,16Mhz /32768 =?488.28125? hz = 2.048ms
// 最大计数时间 :2.048ms *65536 =134.217秒
TIM2_CNTRH =0;
TIM2_CNTRL=0;
TIM2_CR1 |= 0x01;//enable timer2
TIM2_SR1 = 0; // 清除更新中断
}
void Timer1CaptureInit(void)
{
TIM1_CNTRH = 0x00;//清零计数器高8位
TIM1_CNTRL = 0x00;//清零计数器低8位
//计数器的时钟频率(fCK_CNT)等于fCK_PSC/( PSCR[15:0]+1)
//16Mhz / =16 =1Mhz =1us
TIM1_PSCRH = 0x00;//计数器时钟分频高8位
TIM1_PSCRL = 0x0F;//计数器时钟分频低8位15+1分频
TIM1_CCER2 &= (unsigned char)~0x01;//清零TIM1_CCER3中的CC3E位,之后才可配置TIM1_CCMR3
TIM1_CCMR3 = 0x01;//配置TIM1_CCMR3中的CC1S位为1,CC3通道配置为输入,IC3映射到TI3FP1上
//无滤波器、无预分频器(捕获输入口上检测到的每一个边沿都触发一次捕获)
TIM1_CCER2 |= 0x02;//下降沿触发
TIM1_IER |= 0x08;//CC3IE=1,使能捕获/比较3中断
TIM1_CCER2 |= 0x01;//捕获使能
TIM1_CR1 |= 0x01;//使能定时/计数器
}
//软件解码
#define SYNC_L (13558-200)//13558
#define SYNC_H (13558+200)
#define LOW_L (1135-200)
#define LOW_H (1135+200)//1135
#define HIGH_L (2243-200)
#define HIGH_H (2243+200)//2243
uint8_t IRDACMD(uint8_t *ret)
{
uint8_t tempbuf[4]={0};
uint8_t i,j,retv=0;
uint16_t det,CUR;
uint16_t *src=captureint;
if(lastcapcount!=capcount)//收到数据。。
{
CUR =TIM2_CNTRH;
CUR<<=8;
CUR|=TIM2_CNTRL;//得到现在时间
det = (CUR>caplasttiak)?(CUR-caplasttiak):\
(0xffff-caplasttiak+CUR+1);
if(det>=50)//50*2.048ms = 102.4ms超时时间,认定当前帧接收完毕
{
if(capcount<34)//数据帧失效
{
goto errto;
}
}
else
{
return 0;//继续接收
}
}
else //未接收到数据
{
return 1;
}
det =(src[1]>=src[0])?(src[1]-src[0]):(0xffff-src[0]+src[1]+1);//计算控制周期
if((det>SYNC_L)&&(det<SYNC_H)){;}// 同步头 (13.655667ms) /0.001ms = 13,655.667
else{ goto errto;}
src++;
for(i=0;i<4;i++)//包含4个数据
{
tempbuf[i]=0;//clear
for(j=0;j<8;j++)// 8bit
{
det =(src[1]>=src[0])?(src[1]-src[0]):(0xffff-src[0]+src[1]+1);//计算控制周期
src++;
if((det>LOW_L)&&(det<LOW_H)){;} //0 逻辑:1.143917ms /0.001ms =1,143.917
else if((det>HIGH_L)&&(det<HIGH_H))//1逻辑:2.259583ms/0.001ms =2,259.583
{
tempbuf[i]|=(1<<j); //低位在前,
}
else {retv =1;goto errto;}
}
}
ret[0] =tempbuf[0]; ret[1] =tempbuf[2];
retv= 0x80;
errto:
capcount =0;
lastcapcount=capcount;//失效
return retv;
}
#pragma vector=TIM1_CAPCOM_CC3IF_vector//TIM1CA3
__interrupt void TIM1_CAPCOM_CC3IF(void)// 捕获
{
captureint[capcount] =TIM1_CCR3H;
captureint[capcount]<<=8;
captureint[capcount]|=TIM1_CCR3L;
caplasttiak = TIM2_CNTRH;//当前计数器tim2
caplasttiak<<=8;
caplasttiak|=TIM2_CNTRL;
if(++capcount>=CAPSIZEMAX){capcount=0;}
TIM1_SR1 &= (unsigned char)~0x08;//清除CC3IF标志
return;
}