红外遥控器解码
不知道程序那里出了问题?
#include "stm8s.h"
/* Private defines -----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/*
*********************************************************************************************************
*
* 模块名称 : 红外遥控解码
*
引导码 地址码 地址反码 数据码 数据反码
\ 9+4.5ms \ c0-c07 \ c0-c07 \ c0-c07 \ c0-c07 \
*********************************************************************************************************
*/
#define LED_GPIO_PORT (GPIOC)
#define LED_GPIO_PINS1 (GPIO_PIN_5)
#define LED_GPIO_PINS2 (GPIO_PIN_6)
#define REMOTE_ID 1 //红外遥控识别码(ID)
u8 Ir_Status=0; //红外接收处理状态
u8 Ir_Receive_Count=0; //红外接收数据位计数
u32 Ir_Receive_Data=0; //32位的红外接收数据
u8 Ir_receive_ok=0; //红外接收完成标志
void Delay(u32 __IO nCount)
{
while(nCount!=0)
nCount--;
}
/*
********************************************************************************
GPIO初始化
********************************************************************************
*/
void GPIO_Config(void)
{
GPIO_Init(GPIOB, GPIO_PIN_4, GPIO_MODE_IN_PU_IT); //PB4
GPIO_Init(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS1, GPIO_MODE_OUT_PP_LOW_FAST);//PC5
GPIO_Init(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS2, GPIO_MODE_OUT_PP_LOW_FAST);//PC6
}
/*
********************************************************************************
定时器初始化
********************************************************************************
*/
void TIM2_Config(void)
{
TIM2_DeInit();
TIM2_TimeBaseInit(TIM2_PRESCALER_2, 60000);//定时器设置1M的计数频率,1US的分辨率 ,计时60ms
TIM2_ClearFlag(TIM2_FLAG_UPDATE);
TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);
TIM2_Cmd(DISABLE);
}
/*
********************************************************************************
外部中断初始化
********************************************************************************
*/
void EXTIB_Config(void)
{
disableInterrupts();
EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOB, EXTI_SENSITIVITY_FALL_ONLY);//下降沿中断
enableInterrupts();
}
/*
********************************************************************************
红外解码初始化函数
********************************************************************************
*/
void Ir_Init(void)
{
GPIO_Config();
EXTIB_Config();
TIM2_Config();
}
/*
********************************************************************************
定时器溢出中断内处理
********************************************************************************
*/
void TIM_IT_Updata_Handdle(void)
{
TIM2_Cmd(DISABLE);
Ir_Status=0;
TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
TIM2_SetCounter(0);
//TIM2_Cmd(DISABLE);
// GPIO_WriteHigh(GPIOC,GPIO_PIN_5);
}
/*
********************************************************************************
红外接收数据处理函数
********************************************************************************
*/
u8 Ir_Process(void)
{
u8 Ir_num=0; //最终处理后的键值返回值
u8 Address_H,Address_L; //地址码,地址反码
u8 Data_H,Data_L; //数据码,数据反码
if(Ir_receive_ok==1) //接收完成
{
Address_H=Ir_Receive_Data>>24; //得到地址码
Address_L=(Ir_Receive_Data>>16)&0xff; //得到地址反码
//if((Address_H==(u8)~Address_L)&&(Address_H==REMOTE_ID))//检验遥控识别码(ID)及地址
if((Address_H==(u8)~Address_L))//检验遥控识别码(ID)及地址
{
Data_H=Ir_Receive_Data>>8; //得到数据码
Data_L=Ir_Receive_Data; //得到数据反码
if(Data_H==(u8)~Data_L) //接收数据码正确
{
Ir_num=Data_H; //正确键值
Ir_Receive_Data=0;
}
}
}
return Ir_num; //返回键值
}
/*
********************************************************************************
红外接收中断处理函数
********************************************************************************
*/
void Ir_Receive_Handle(void)
{
u16 Interval_tim=0;//两个下降沿间隔时间
switch(Ir_Status)
{
case 0://第一个下降沿,定时器开始计数
Ir_Status=1;
TIM2_Cmd(ENABLE); //Enable TIM2
TIM2_SetCounter(0); //定时器计数值清零
break;
case 1://第二个下降沿,定时器关闭,读取定时器计数值
TIM2_Cmd(DISABLE);
Interval_tim=0;
Interval_tim=TIM2_GetCounter(); //读取定时器计数值
TIM2_SetCounter(0); //定时器计数值清零
TIM2_Cmd(ENABLE); //Enable TIM2
//GPIO_WriteHigh(GPIOC,GPIO_PIN_5);//正常
if( (Interval_tim>=12500)&&(Interval_tim<=14500) )//判断引导码是否正确9+4.5ms
{
Ir_Status=2; //进入下一状态
}
else //引导码错误,从新接收
{
Ir_Status=0;
Ir_Receive_Count=0;
}
break;
case 2://开始32位数据的接收
TIM2_Cmd(DISABLE);
Interval_tim=0;
Interval_tim=TIM2_GetCounter();
TIM2_SetCounter(0);
TIM2_Cmd(ENABLE); //Enable TIM2
if( (Interval_tim>=1000)&&(Interval_tim<=1300) ) //间隔1.12ms ->0
{
Ir_Receive_Data=Ir_Receive_Data<<1;
Ir_Receive_Count++;
}
else if( (Interval_tim>=2000)&&(Interval_tim<=2600) ) //间隔2.25ms ->1
{
Ir_Receive_Data=Ir_Receive_Data<<1;
Ir_Receive_Data=Ir_Receive_Data|0x0001;
Ir_Receive_Count++;
}
else//不是0,1 接收错误,从新接收
{
Ir_Status=0;
Ir_Receive_Data=0;
Ir_Receive_Count=0;
}
//超出接收数据位数,接收下一个
while(Ir_Receive_Count==32)
{
Ir_receive_ok=1;//红外接收完成
Ir_Status=0;
Ir_Receive_Count=0;
break;
}
break;
default :
break;
}
}
/*
********************************************************************************
********************************************************************************
*/
//当红外接收到信号进入中断,运行定时器执行程序,红外未收到信号空闲时无中断定时器关闭
void main(void)
{
uint8_t key_val;
Ir_Init();
while(1)
{
if( Ir_receive_ok == 1 ) //一帧红外数据接收完成
{
key_val = Ir_Process();
Ir_receive_ok=0;
//不同的遥控器面板对应不同的键值 0-9
switch( key_val )
{
}
}
}
}
/*****************************/
INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4)
{
/* In order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction.
*/
disableInterrupts();
Ir_Receive_Handle();
enableInterrupts();
}
/*****************************/
INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)
{
/* In order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction.
*/
TIM_IT_Updata_Handdle();
}[/code]
凑巧我去年也做过一个stm8s003的红外接收
就上面的代码而言,我看到的差别在于,程序开始运行的时候,TIM2是关闭的
第一次按键之后,TIM2是关闭的,然后进case 0,清零打开TIM2,这一次是不正确的
之后每一次,TIM2都没有关闭,每一个case最后都TIM2_Cmd(ENABLE);了,后面每一次都正确
我就觉得,如果上电初始化就打开TIME2,是不是每一次就正确了呢?你可以试试。
说说我的做法,你可以参考:
区别在于,我没有使用定时器中断,我就设置定时器的周期也是1us,让它自动加,然后溢出
16位的定时器可以表达65.535ms,因此收到的引导码时间计数一定小于65535
红外输入引脚产生中断的时候,我用代码描述
if( start_flag ) {
time1 = TIM2_CNT; //开始的时候,记录时刻1
start_flag = 0;
time = 0;
return;
}
else
{
time2 = TIM2_CNT; //第二次的时刻
if(time2 >= time1) //计算时间
{
time = time2 -time1;
}
else
{
time = 0xFFFF - (time1 - time2) + 1; //定时器溢出时这样算
}
time1 = TIM2_CNT; //更新当前时刻,为下一个码做准备
}
..
后面就是用time去比较各种码的时间,跟你后面的代码差不多
就是不需要TIME2中断了。也不用开关TIM2,就直接读,然后注意溢出,还有重装载值是0xFFFF
TIME2是16位吗?我记得不是很清楚了,当时我选用的是16位那个
谢谢了,按你的建议改了,真的可以了,之前一直在改其他地方,没有注意到定时器的问题,看来以后检查程序要细心一点了。还有你的程序也参考了
可以发改新的代码出来参考一下吗,我现在也在做红外遥控,急需
感谢小编这个代码 我的红外解码也做成功了 按照你的代码键值显示是数字的有3位数