Files
OldPeopleHome/zigbee/ZStack-CC2530-r200/Components/hal/target/CC2530EB/hal_irdec.c
LitterDryFish 0657e3a6a9 组网
2019-08-23 09:32:51 +08:00

236 lines
8.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/***********************************************************
** FileName: IRDecode.c
** Introductions: IR Remote decode for MCU of CC2530
** Last Modify time: 2013.05.03
** Update: 基本解码测试
** Author: GuoZhenjiang<zhenjiang.guo@sunplusapp.com>
** Modify:
** 2013.05.03 lijian Change File Name to hal_irdec.c
***********************************************************/
#include <hal_board.h>
#include "hal_irdec.h"
#include <string.h>
#if defined(HAL_IRDEC) && (HAL_IRDEC == TRUE)
static struct {
uint8 IRIntTskId;
uint8 IRIntEp;
OSALIRDecData_t IRCodeTab;
} IRDecodeRes;
volatile uint8 IROverTimeAdd_En=FALSE, IROverTimeOvf_flg=FALSE;
volatile uint16 IROverTimeAdd_cnt=0;
volatile IRDecodeSta_t IRDeodeSta = WaitForGuideTrig1;
static uint8 cnt_Byte, cnt_bit; // 用于控制解码过程的基本变量
/***********************************************************
** 函数名称: IRDecodeT1Init
** 实现功能: 中断法进行红外解码初始化工作
** 入口参数: None
** 返回结果: None
***********************************************************/
void IRDecodeT1Init(uint8 taskid, uint8 ep)
{
// 保存任务号和端点号
IRDecodeRes.IRIntTskId = taskid;
IRDecodeRes.IRIntEp = ep;
// 初始化Timer1
P1SEL |= 0x04; // 配置P1.2为Timer1的外设功能引脚
P1DIR &= ~0x04; // 输入捕获引脚必须设置为输入
PERCFG |= 0x40; // Timer1占用第2引脚位置(通道0为P1.2)
P2SEL |= 0x04; // 当USART0和Timer1分配了相同引脚Timer1优先
// 定时器1初始化
T1CTL = (uint8)Tdiv_32 | (uint8)Tmod_stop; // 1MHz,暂停运行
CLR_T1CNT; // 清零定时器1
// Timer1通道0上升沿输入捕获设置
T1CCTL0 = 0x01; // 上升沿捕获,通道0输入捕获中断未使能,查询中断标志即可
T1CCTL0 |= 0x40; // T1CCTL0.IM 定时器1通道0中断开关
T1STAT = 0;
IEN1 |= 0x02; // IEN1.T1IE 定时器1中断总开关
EA = 1; // IEN0.EA 全局总中断开关
// 初始化Time4
P2SEL |= 0x10; // 定时器4优先级高于定时器1
T4CTL |= 0xEC; // 128分频,清空计数值,允许溢出中断,自由运行
T4CTL |= 0x10; // 启动定时器
IEN1 |= 0x10; // 打开定时器4总中断
}
/***********************************************************
** 函数名称: Timer1_ISR
** 实现功能: Timer1 中断处理函数,利用Timer1通道0输入捕获功能实现红外解码
** 入口参数: None
** 返回结果: None
***********************************************************/
HAL_ISR_FUNC_DECLARATION(Timer1_ISR, T1_VECTOR);
HAL_ISR_FUNCTION(Timer1_ISR, T1_VECTOR)
{
#define CLR_T1CH0_IF T1STAT &= 0xFE
#define CLR_T1CH1_IF T1STAT &= 0xFD
#define CLR_T1OVF_IF T1STAT &= 0xDF
#define CLR_T1IF IRCON &= 0xFD
static uint8 IRdata[15]; // 用于存储解析的红外数据
static uint16 tCapture = 0; // 用于存储判断每个捕获周期
// 红外解码中捕获到定时器1通道0上升沿
if(T1STAT & 0x01)
{
switch(IRDeodeSta)
{
case WaitForGuideTrig1:
IRDeodeSta = WaitForGuideTrig2;
CLR_T1CNT; // 清零定时器1
T1CTL = (uint8)Tdiv_32 | (uint8)Tmod_free; // 1MHz,自由计数模式
break;
case WaitForGuideTrig2:
tCapture = T1CC0L; // 获取当前一个周期值
tCapture |= (uint16)T1CC0H << 8;
CLR_T1CNT; // 清零定时器1
T1CTL = (uint8)Tdiv_32 | (uint8)Tmod_free; // 1MHz,自由计数模式
// 如果是引导码4.5ms引导码或者9ms引导码
if(((tCapture > T_IR_GUIDE9_MIN) && (tCapture < T_IR_GUIDE9_MAX)) || ((tCapture > T_IR_GUIDE4_MIN) && (tCapture < T_IR_GUIDE4_MAX)))
{
IRDeodeSta = Decoding;
// 准备解码工作
cnt_bit = 0;
cnt_Byte = 0;
}
else
IRDeodeSta = WaitForGuideTrig1;
IROverTimeAdd_cnt = 0;
break;
case Decoding:
tCapture = T1CC0L; // 获取当前一个周期值
tCapture |= (uint16)T1CC0H << 8;
CLR_T1CNT; // 清零定时器1
T1CTL = (uint8)Tdiv_32 | (uint8)Tmod_free; // 1MHz,自由计数模式
// 接收到位0?
if((tCapture > T_IR_0_MIN) && (tCapture < T_IR_0_MAX))
{
IRDeodeSta = Decoding;
IROverTimeAdd_cnt = 0;
IRdata[cnt_Byte] &= ~(0x80 >> cnt_bit); // 保存当前位0
cnt_bit++;
if(cnt_bit >= 8) // 接收完毕一个字节
{
IRDecodeRes.IRCodeTab.irCode[cnt_Byte] = IRdata[cnt_Byte];
cnt_bit=0;
cnt_Byte++;
if(cnt_Byte >= 15) // 超出最大接收队列长度
{
IRDeodeSta = Decode_BufOverflow;
goto OneIRpkgGot;
}
}
}
// 接收到位1?
else if((tCapture > T_IR_1_MIN) && (tCapture < T_IR_1_MAX))
{
IRDeodeSta = Decoding;
IROverTimeAdd_cnt = 0;
IRdata[cnt_Byte] |= 0x80 >> cnt_bit; // 保存当前位0
cnt_bit++;
if(cnt_bit >= 8) // 接收完毕一个字节
{
IRDecodeRes.IRCodeTab.irCode[cnt_Byte] = IRdata[cnt_Byte];
cnt_bit=0;
cnt_Byte++;
if(cnt_Byte >= 15) // 超出最大接收队列长度
{
IRDeodeSta = Decode_BufOverflow;
goto OneIRpkgGot;
}
}
}
// 没有超时,不是位0,不是位1,出错???
else
{
IRDeodeSta = Decode_OverUnknow;
goto OneIRpkgGot;
}
break;
default :
IRDeodeSta = WaitForGuideTrig1;
break;
}
OneIRpkgGot:
{
switch(IRDeodeSta) // 一次红外解码结束
{
// 处理 接收队列溢出导致解码结束
case Decode_BufOverflow:
// 处理 未知原因导致解码结束
case Decode_OverUnknow:
IROverTimeAdd_cnt = 0;
IRDecodeRes.IRCodeTab.irLen = cnt_Byte;
cnt_bit = 0;
cnt_Byte = 0;
OSALIRDecIntData_t* T1Ch0IntData;
T1Ch0IntData = (OSALIRDecIntData_t *)osal_msg_allocate(sizeof(OSALIRDecIntData_t));
T1Ch0IntData->hdr.event = IRDEC_INT_EVENT;
T1Ch0IntData->endPoint = IRDecodeRes.IRIntEp;
T1Ch0IntData->data = &IRDecodeRes.IRCodeTab;
osal_msg_send(IRDecodeRes.IRIntTskId, (uint8*)(T1Ch0IntData));
IRDeodeSta = WaitForGuideTrig1;
break;
default :
break;
}
}
CLR_T1CH0_IF; // 清除通道0输入捕获中断标志
}
CLR_T1IF; // 清除T1IF
}
/***********************************************************
** 函数名称: Timer4_ISR
** 实现功能: Timer4 中断处理函数,利用Timer1通道0输入捕获功能实现红外解码
** 入口参数: None
** 返回结果: None
***********************************************************/
HAL_ISR_FUNC_DECLARATION(Timer4_ISR, T4_VECTOR);
HAL_ISR_FUNCTION(Timer4_ISR, T4_VECTOR)
{
// (32MHz / 128) T = 4us; f = 250000Hz;
switch(IRDeodeSta)
{
// 等待第二次触发,检测引导码是否超时
case WaitForGuideTrig2:
IROverTimeAdd_cnt++;
if(IROverTimeAdd_cnt >= 16) // 约16ms内没有清零
{
IROverTimeAdd_cnt = 0;
IRDeodeSta = WaitForGuideTrig1;
}
break;
// 位0 位1 解码中,检测是否解码超时
case Decoding:
IROverTimeAdd_cnt++;
if(IROverTimeAdd_cnt >= 5) // 4ms内没有清零
{
IROverTimeAdd_cnt = 0;
IRDecodeRes.IRCodeTab.irLen = cnt_Byte;
cnt_bit = 0;
cnt_Byte = 0;
OSALIRDecIntData_t* T4OvfIntData;
T4OvfIntData = (OSALIRDecIntData_t *)osal_msg_allocate(sizeof(OSALIRDecIntData_t));
T4OvfIntData->hdr.event = IRDEC_INT_EVENT;
T4OvfIntData->endPoint = IRDecodeRes.IRIntEp;
T4OvfIntData->data = &IRDecodeRes.IRCodeTab;
osal_msg_send(IRDecodeRes.IRIntTskId, (uint8*)(T4OvfIntData));
IRDeodeSta = WaitForGuideTrig1;
}
break;
default :
IROverTimeAdd_cnt = 0;
break;
}
T4OVFIF = 0; // 清除定时器4溢出中断标志
T4IF = 0; // 清除定时器4总中断标志
}
#endif //#if defined(HAL_IRDEC) && (HAL_IRDEC == TRUE)