红外 SDK

更新时间:2022-11-24 09:20:27下载pdf

由于涂鸦模组 SDK 只提供红外相关系统 DP 回调的数据接口,如果您想要实现红外功能,必须重新从驱动层开始实现红外发送与红外学习功能,大大增加了开发难度与开发周期。

红外应用组件的出现大大改变了现状,您无需关心红外相关数据链路的实现,只需要注册符合硬件的红外发送、接收引脚与红外发送接收状态回调即可完成红外相关功能开发。SDK 的整体结构如下所示:

红外 SDK

SDK 文件结构

.
├── Doc
│   ├── Readme.md
│   ├── tuya_ir_drv_bk7231n.c
│   ├── tuya_ir_drv_bk7231n.h
│   ├── tuya_ir_drv_rtl8710bn.c
│   ├── tuya_ir_drv_rtl8710bn.h
│   ├── tuya_ir_drv_rtl8720cf.c
│   ├── tuya_ir_drv_rtl8720cf.h
│   ├── tuya_ir_drv_rtl8720cs.c
│   ├── tuya_ir_drv_rtl8720cs.h
│   ├── tuya_ir_proc.c
│   └── tuya_ir_proc.h
├── include
│   ├── tuya_ir_app.h
│   ├── tuya_ir_ctrl.h
│   ├── tuya_ir_data_handle.h
│   ├── tuya_ir_drv_struct.h
│   └── tuya_ir_user_api.h
├── local.mk
├── README.md
├── src
│   ├── tuya_ir_app.c
│   ├── tuya_ir_app.o
│   ├── tuya_ir_ctrl.c
│   ├── tuya_ir_ctrl.o
│   ├── tuya_ir_data_handle.c
│   └── tuya_ir_data_handle.o
└── svc_ir_module.yaml

文件 说明 您是否需要关注
tuya_ir_app.c 红外应用组件应用逻辑处理
tuya_ir_ctrl.c 红外应用组件应用具体逻辑实现
tuya_ir_data_handle.c 红外学习码滤波处理函数
tuya_ir_user_api.h API 声明
tuya_ir_drv_struct.h 红外驱动结构体声明
Doc 已适配的平台驱动及红外应用组件 SDK 介绍

数据结构

您需要用到的驱动数据结构在tuya_ir_drv_struct.h头文件中已声明,其中驱动接口说明如下:

typedef enum
{
	TIM_COUNT_UP_MODE   = 0,
	TIM_COUNT_DOWN_MODE = 1,
	TIM_INVALID_MODE    = 2,
}TIM_COUNT_MODE_E;

typedef struct
{
	FLOAT_T timer_mhz;
	TIM_COUNT_MODE_E count_mode;     //0:Counting-up 1:Counting-down
}TUYA_IR_TIM_INFO,*P_TUYA_IR_TIM_INFO;

//ir_ops
typedef struct
{
	VOID_T  (*tuya_ir_drv_timer_init)(VOID_T);
	VOID_T  (*tuya_ir_drv_timer_start)(IN UINT_T tim_us);
	VOID_T  (*tuya_ir_drv_timer_stop)(VOID_T);
	UINT_T  (*tuya_ir_drv_timer_getcount)(VOID_T);
	VOID_T  (*tuya_ir_drv_timer_getinfo)(INOUT TUYA_IR_TIM_INFO *tim_info);

	VOID_T  (*tuya_ir_drv_pwm_init)(IN UCHAR_T ir_txpin,IN UINT_T freq);
	VOID_T  (*tuya_ir_drv_pwm_setfreq)(IN UINT_T freq);
	VOID_T  (*tuya_ir_drv_pwm_send)(VOID_T);
	VOID_T  (*tuya_ir_drv_pwm_stop)(VOID_T);

	VOID_T  (*tuya_ir_drv_gpioirq_init)(IN UCHAR_T ir_rxpin);
	VOID_T  (*tuya_ir_drv_gpioirq_en)(IN UCHAR_T is_enable);

	VOID_T  (*tuya_ir_drv_plat_related_init)(VOID_T);
	VOID_T  (*tuya_ir_drv_irtx_start_cb)(VOID_T);
	VOID_T  (*tuya_ir_drv_irtx_finish_cb)(VOID_T);
	VOID_T  (*tuya_ir_drv_irrx_start_cb)(VOID_T);
	VOID_T  (*tuya_ir_drv_irrx_finish_cb)(VOID_T);
}TUYA_IR_DRV_OPTS,*P_TUYA_IR_DRV_OPTS;

typedef struct
{
FLOAT_T timer_mhz;
TIM_COUNT_MODE_E count_mode; //0:Counting-up 1:Counting-down
}TUYA_IR_TIM_INFO,*P_TUYA_IR_TIM_INFO;
timer_mhz:硬件定数器频率
count_mode:硬件定时器计数模式
VOID_T (*tuya_ir_drv_timer_init)(VOID_T); 硬件定时器初始化
VOID_T (*tuya_ir_drv_timer_start)(IN UINT_T tim_us); 硬件定时器定时开启
VOID_T (*tuya_ir_drv_timer_stop)(VOID_T); 硬件定时器定时关闭
UINT_T (*tuya_ir_drv_timer_getcount)(VOID_T); 获取硬件定时器计数值
VOID_T (*tuya_ir_drv_timer_getinfo)(INOUT TUYA_IR_TIM_INFO *tim_info); 获取硬件定时器相关属性
VOID_T (*tuya_ir_drv_pwm_init)(IN UCHAR_T ir_txpin,IN UINT_T freq); pwm初始化
VOID_T (*tuya_ir_drv_pwm_setfreq)(IN UINT_T freq); pwm设置频率
VOID_T (*tuya_ir_drv_pwm_send)(VOID_T); pwm开启
VOID_T (*tuya_ir_drv_pwm_stop)(VOID_T); pwm关闭
VOID_T (*tuya_ir_drv_gpioirq_init)(IN UCHAR_T ir_rxpin); 外部中断初始化
VOID_T (*tuya_ir_drv_gpioirq_en)(IN UCHAR_T is_enable); 外部中断使能/失能
VOID_T (*tuya_ir_drv_plat_related_init)(VOID_T); 模组平台初始化(不同模组有所差异、不用则赋NULL)
VOID_T (*tuya_ir_drv_irtx_start_cb)(VOID_T); 红外发送开始驱动回调(不同模组有所差异,需要再发送设置某些参数,不用则赋NULL)
VOID_T (*tuya_ir_drv_irtx_finish_cb)(VOID_T); 红外发送结束驱动回调(不同模组有所差异,需要再发送设置某些参数,不用则赋NULL)
VOID_T (*tuya_ir_drv_irrx_start_cb)(VOID_T); 红外学习开始驱动回调(不同模组有所差异,需要再发送设置某些参数,不用则赋NULL)
VOID_T (*tuya_ir_drv_irrx_finish_cb)(VOID_T); 红外学习结束驱动回调(不同模组有所差异,需要再发送设置某些参数,不用则赋NULL)

您红外初始化需要了解的数据结构说明如下:

typedef struct
{
	SHORT_T carr_compensation_val;
	SHORT_T lowlevel_compensation_val;
}TUYA_IRAPP_TX_CFG_S;

typedef struct
{
	UCHAR_T                 txpin;
	UCHAR_T                 rxpin;
	TUYA_IR_STAT_CB         ir_stat_cb;
	TUYA_IRAPP_TX_CFG_S     ir_tx_cfg;
} TUYA_IRAPP_CFG_S,*P_TUYA_IRAPP_CFG_S;
参数 说明
txpin 红外发送引脚
rxpin 红外接收引脚
TUYA_IR_STAT_CB 红外发送接收状态回调
TUYA_IRAPP_TX_CFG_S 红外发送补偿值设置(不同平台硬件定时器定时误差有大有小,通过此变量设置)

开放接口

OPERATE_RET tuya_irapp_module_init(IN TUYA_IRAPP_CFG_S *p_ir_cfg,IN TUYA_IR_DRV_OPTS* p_ir_opts);
VOID_T tuya_irapp_irdata_send(IN TY_IR_CODE_S *ir_code, IN UCHAR_T code_num);
VOID_T tuya_irapp_irstudy_ctrl(IN TY_IR_STUDY_CTL_E irstudy_mode);
VOID_T tuya_irapp_set_irdata_recv_cb(IN TUYA_IR_DATARECV_CB cb);
CHAR_T tuya_irapp_is_irsend_stat(VOID_T);
VOID_T tuya_irctrl_set_carrorlow(CHAR_T enable);
VOID_T tuya_irctrl_timeout_irq(VOID_T);
VOID_T tuya_irctrl_recv_irq(VOID_T);

OPERATE_RET tuya_irapp_module_init(IN TUYA_IRAPP_CFG_S p_ir_cfg,IN TUYA_IR_DRV_OPTS p_ir_opts); /**
* @brief: tuya_irapp_module_init
* @desc: tuya Infrared function initialization
*
* @param[in] TUYA_IRAPP_CFG_S: p_ir_cfg
* @param[in] TUYA_IR_DRV_OPTS: p_ir_opts
*
* @return OPERATE_RET
*
* @note none
*/
VOID_T tuya_irapp_irdata_send(IN TY_IR_CODE_S *ir_code, IN UCHAR_T code_num); /**
* @brief: tuya_irapp_irdata_send
* @desc: tuya Infrared data transmission
*
* @param[in] ir_code: infrared data
* @param[in] code_num: num of ir_code
*
* @return VOID_T
*
* @note none
*/
VOID_T tuya_irapp_irstudy_ctrl(IN TY_IR_STUDY_CTL_E irstudy_mode); /**
* @brief: tuya_irapp_irstudy_ctrl
* @desc: tuya Infrared learning state control
*
* @param[in] irstudy_mode: Infrared learning state
*
* @return VOID_T
*
* @note none
*/
VOID_T tuya_irapp_set_irdata_recv_cb(IN TUYA_IR_DATARECV_CB cb); /**
* @brief: tuya_irapp_set_irdata_recv_cb
* @desc: tuya Infrared learning data callback
*
* @param[in] TUYA_IR_DATARECV_CB: Infrared learning data callback function pointer
*
* @return VOID_T
*
* @note none
*/
CHAR_T tuya_irapp_is_irsend_stat(VOID_T); /**
* @brief: tuya_irapp_is_irsend_stat
* @desc: Gets the infrared transmission status
*
* @return True OR False
*
* @note none
*/
VOID_T tuya_irctrl_set_carrorlow(CHAR_T enable); /**
* @brief: tuya_irctrl_set_carrorlow
* @desc: Set the infrared transmitting carrier or low level
*
* @return True OR False
*
* @note none
*/
VOID_T tuya_irctrl_timeout_irq(VOID_T); /**
* @brief: tuya_irctrl_timeout_irq
* @desc: Infrared timer interrupt handler function
*
* @return none
*
* @note Called by the developer in the timer interrupt callback function
*/
VOID_T tuya_irctrl_recv_irq(VOID_T); /**
* @brief: tuya_irctrl_recv_irq
* @desc: Infrared external interrupt handler function
*
* @return none
*
* @note Called by developer in external interrupt function callback
*/

DEMO

驱动接口实现Demo:

#include"tuya_ir_drv_rtl8710bn.h"

STATIC TY_IR_DRV_S ty_irhw ={0};

STATIC VOID_T tuya_rtl8710bn_ir_drv_timer_irq_handle(VOID_T *param);
STATIC VOID_T tuya_rtl8710bn_ir_drv_gpioirq_handle(UINT_T param, gpio_irq_event event);
STATIC VOID_T tuya_rtl8710bn_ir_drv_timer_init(VOID_T);
STATIC VOID_T tuya_rtl8710bn_ir_drv_timer_start(IN UINT_T tim_us);
STATIC VOID_T tuya_rtl8710bn_ir_drv_timer_stop(VOID_T);
STATIC UINT_T tuya_rtl8710bn_ir_drv_timer_getcount(VOID_T);
STATIC VOID_T tuya_rtl8710bn_ir_drv_timer_getinfo(INOUT TUYA_IR_TIM_INFO *tim_info);
STATIC VOID_T tuya_rtl8710bn_ir_drv_pwm_init(IN CHAR_T ir_txpin,IN UINT_T freq);
STATIC VOID_T tuya_rtl8710bn_ir_drv_pwm_setfreq(IN UINT_T freq);
STATIC VOID_T tuya_rtl8710bn_ir_drv_pwm_send(VOID_T);
STATIC VOID_T tuya_rtl8710bn_ir_drv_pwm_stop(VOID_T);
STATIC VOID_T tuya_rtl8710bn_ir_drv_gpioirq_init(IN UCHAR_T ir_rxpin);
STATIC VOID_T tuya_rtl8710bn_ir_drv_gpioirq_en(IN UCHAR_T is_enable);

OPERATE_RET tuya_rtl8710bn_get_ir_drv_ops(INOUT TUYA_IR_DRV_OPTS *p_irops)
{
	if (NULL == p_irops)
	{
		return OPRT_INVALID_PARM;
	}

	p_irops->tuya_ir_drv_timer_init         = tuya_rtl8710bn_ir_drv_timer_init;
	p_irops->tuya_ir_drv_timer_start        = tuya_rtl8710bn_ir_drv_timer_start;
	p_irops->tuya_ir_drv_timer_stop         = tuya_rtl8710bn_ir_drv_timer_stop;
	p_irops->tuya_ir_drv_timer_getcount     = tuya_rtl8710bn_ir_drv_timer_getcount;
	p_irops->tuya_ir_drv_timer_getinfo      = tuya_rtl8710bn_ir_drv_timer_getinfo;

	p_irops->tuya_ir_drv_pwm_init           = tuya_rtl8710bn_ir_drv_pwm_init;
	p_irops->tuya_ir_drv_pwm_setfreq        = tuya_rtl8710bn_ir_drv_pwm_setfreq;
	p_irops->tuya_ir_drv_pwm_send           = tuya_rtl8710bn_ir_drv_pwm_send;
	p_irops->tuya_ir_drv_pwm_stop           = tuya_rtl8710bn_ir_drv_pwm_stop;

	p_irops->tuya_ir_drv_gpioirq_init       = tuya_rtl8710bn_ir_drv_gpioirq_init;
	p_irops->tuya_ir_drv_gpioirq_en         = tuya_rtl8710bn_ir_drv_gpioirq_en;

	p_irops->tuya_ir_drv_plat_related_init  = NULL;
	p_irops->tuya_ir_drv_irtx_start_cb      = NULL;
	p_irops->tuya_ir_drv_irtx_finish_cb     = NULL;
	p_irops->tuya_ir_drv_irrx_start_cb      = NULL;
	p_irops->tuya_ir_drv_irrx_finish_cb     = NULL;

	return OPRT_OK;
}

STATIC VOID_T tuya_rtl8710bn_ir_drv_timer_irq_handle(VOID_T *param)
{
	TY_IR_DRV_S *p_ty_irhw = (TY_IR_DRV_S*)param;
	RTIM_INTClear(TIMx[p_ty_irhw->timerid]);

	//call tuya ir send irq function
	tuya_irctrl_timeout_irq();
}

STATIC VOID_T tuya_rtl8710bn_ir_drv_gpioirq_handle(UINT_T param, gpio_irq_event event)
{
	TY_IR_DRV_S  *p_ty_irhw = (TY_IR_DRV_S *)param;

	if (IRQ_RISE == event)
	{
		gpio_irq_set_event(&(p_ty_irhw->irq), IRQ_FALL);
	}
	else if (IRQ_FALL == event)
	{
		gpio_irq_set_event(&(p_ty_irhw->irq), IRQ_RISE);
	}

	tuya_irctrl_recv_irq();
}

STATIC VOID_T  tuya_rtl8710bn_ir_drv_timer_init(VOID_T)
{
	RTIM_TimeBaseInitTypeDef TIM_InitStruct;

	ty_irhw.timerid = TY_IR_TIMER_ID;

	RTIM_TimeBaseStructInit(&TIM_InitStruct);
	TIM_InitStruct.TIM_Idx           = ty_irhw.timerid;
	TIM_InitStruct.TIM_Prescaler     = 39;              // prescaler =  (TIM_Prescaler+1)
	TIM_InitStruct.TIM_UpdateEvent   = TRUE;            // UEV enable
	TIM_InitStruct.TIM_UpdateSource  = TIM_UpdateSource_Overflow;
	TIM_InitStruct.TIM_ARRProtection = TRUE;
	RTIM_TimeBaseInit(TIMx[ty_irhw.timerid], &TIM_InitStruct, TIMx_irq[ty_irhw.timerid], (IRQ_FUN)tuya_rtl8710bn_ir_drv_timer_irq_handle, (UINT_T)&ty_irhw);
}
STATIC VOID_T  tuya_rtl8710bn_ir_drv_timer_start(IN UINT_T tim_us)
{
	RTIM_TypeDef *RTIM = TIMx[ty_irhw.timerid];
	UINT_T period;

	RTIM->PSC = 39;
	period = (UINT_T)((FLOAT_T)tim_us  * 40 / ((RTIM->PSC & 0xFF) + 1));
	period = (period > 0xFFFF) ? 0xFFFF : period;
	RTIM_ChangePeriod(RTIM, period);
	RTIM_INTConfig(RTIM, TIM_IT_Update, TRUE);
	RTIM_Cmd(RTIM, TRUE);
}
STATIC VOID_T  tuya_rtl8710bn_ir_drv_timer_stop(VOID_T)
{
	RTIM_Cmd(TIMx[ty_irhw.timerid], FALSE);
}
STATIC UINT_T  tuya_rtl8710bn_ir_drv_timer_getcount(VOID_T)
{
	RTIM_TypeDef *RTIM = TIMx[ty_irhw.timerid];
	return RTIM_GetCount(RTIM);
}
STATIC VOID_T  tuya_rtl8710bn_ir_drv_timer_getinfo(INOUT TUYA_IR_TIM_INFO *tim_info)
{
	tim_info->timer_mhz = 1;                //1MHZ
	tim_info->count_mode = TIM_COUNT_UP_MODE;
}
STATIC VOID_T  tuya_rtl8710bn_ir_drv_pwm_init(IN CHAR_T ir_txpin,IN UINT_T freq)
{
	ty_irhw.txpin = ir_txpin;
	pwmout_init(&(ty_irhw.pwm), ty_irhw.txpin);
	pwmout_stop(&(ty_irhw.pwm));
}
STATIC VOID_T  tuya_rtl8710bn_ir_drv_pwm_setfreq(IN UINT_T freq)
{
	pwmout_period_us(&(ty_irhw.pwm), (UINT_T)(1000000 / freq));
	pwmout_pulsewidth_us(&(ty_irhw.pwm), (UINT_T)(1000000 / freq) >> 1);
}
STATIC VOID_T  tuya_rtl8710bn_ir_drv_pwm_send(VOID_T)
{
	pwmout_start(&(ty_irhw.pwm));
}
STATIC VOID_T  tuya_rtl8710bn_ir_drv_pwm_stop(VOID_T)
{
	pwmout_stop(&(ty_irhw.pwm));
}
STATIC VOID_T  tuya_rtl8710bn_ir_drv_gpioirq_init(IN UCHAR_T ir_rxpin)
{
	ty_irhw.rxpin = ir_rxpin;
	gpio_irq_init(&(ty_irhw.irq), ty_irhw.rxpin, (gpio_irq_handler)tuya_rtl8710bn_ir_drv_gpioirq_handle, (UINT_T)&ty_irhw);
	gpio_irq_pull_ctrl(&(ty_irhw.irq), PullUp);
	gpio_irq_set(&(ty_irhw.irq), IRQ_FALL, FALSE);
	gpio_irq_disable(&(ty_irhw.irq));
}
STATIC VOID_T  tuya_rtl8710bn_ir_drv_gpioirq_en(IN UCHAR_T is_enable)
{
	if (is_enable)
	{
		gpio_irq_set(&(ty_irhw.irq), IRQ_FALL, TRUE);
		gpio_irq_enable(&(ty_irhw.irq));
	}
	else
	{
		gpio_irq_set(&(ty_irhw.irq), IRQ_FALL, FALSE);
		gpio_irq_disable(&(ty_irhw.irq));
	}
}

#ifndef __TUYA_IR_DRV_RTL8710BN_H__
#define __TUYA_IR_DRV_RTL8710BN_H__

#include "gpio_irq_api.h"
#include "pwmout_api.h"
#include "timer_api.h"
#include "tuya_gpio.h"
#include "tuya_cloud_types.h"
#include "tuya_ir_drv_struct.h"

#ifdef __cplusplus
extern "C" {
#endif

#define TY_IR_TIMER_ID              4
#define TY_IR_TX_IO_ARRAY           {TY_GPIOA_5,TY_GPIOA_12,TY_GPIOA_14,TY_GPIOA_15,TY_GPIOA_22}
#define TY_IR_RX_IO_ARRAY           {TY_GPIOA_5,TY_GPIOA_12,TY_GPIOA_14,TY_GPIOA_15,TY_GPIOA_19,TY_GPIOA_22}
#define TY_IR_TX_CARR_COMPENSATION_VAL          (0)
#define TY_IR_TX_LOWLEVEL_COMPENSATION_VAL      (-10)

typedef struct
{
	gpio_irq_t         irq;
	pwmout_t           pwm;
	UCHAR_T            timerid;
	UCHAR_T            txpin;
	UCHAR_T            rxpin;
} TY_IR_DRV_S,*P_TY_IR_DRV_S;

OPERATE_RET tuya_rtl8710bn_get_ir_drv_ops(INOUT TUYA_IR_DRV_OPTS *p_irops);

#ifdef __cplusplus
} // extern "C"
#endif

#endif

应用Demo:

	HW_IRSET_S * ir_config = get_ir_config();
	TUYA_IRAPP_CFG_S ir_cfg = {0};
	ir_cfg.txpin = ir_config->ir_io_set.ir_send;
	ir_cfg.rxpin = ir_config->ir_io_set.ir_recv;
	ir_cfg.ir_stat_cb = irapp_stat_cb;
	ir_cfg.ir_tx_cfg.carr_compensation_val = TY_IR_TX_CARR_COMPENSATION_VAL;
	ir_cfg.ir_tx_cfg.lowlevel_compensation_val = TY_IR_TX_LOWLEVEL_COMPENSATION_VAL;
	TUYA_IR_DRV_OPTS ir_opts = {0};

	tuya_rtl8710bn_get_ir_drv_ops(&ir_opts);

	op_ret = tuya_irapp_module_init(&ir_cfg,&ir_opts);
	if (op_ret != OPRT_OK)
	{
		PR_ERR("tuya_irbox_init err:%d!",op_ret);
		return op_ret;
	}