12.3. 应用示例

12.3.1. 红外收发

12.3.1.1. 初始化

IR 寄存器基地址通过设备句柄配置,句柄中还可以配置一些中断回调函数,供中断触发时调用。初始化参数为 \ref GX_HAL_IR_CFG_T,初始化接口为 \ref gx_hal_ir_init。

    GX_IR_CFG_T cfg = {0};
    memset(&cfg, 0, sizeof(cfg));
    cfg.tx_carrier_duty = 30;
	cfg.tx_carrier_freq = 38000;

	cfg.std_rx_done_cb = gx_ir_test_recv_std_cb;
	cfg.std_rx_err_cb = gx_ir_test_recv_std_err_cb;
	cfg.ud_rx_thr_cb = gx_ir_test_recv_ud_thr_cb;
	cfg.ud_rx_done_cb = gx_ir_test_recv_ud_cb;
	cfg.ud_tx_done_cb = gx_ir_test_send_ud_done_cb;
	cfg.std_tx_done_cb = gx_ir_test_std_tx_done_cb;
	cfg.ud_rx_full_cb = gx_ir_test_ud_rx_full_cb;
	cfg.ud_rx_empty_cb = gx_ir_test_ud_rx_empty_cb;
	cfg.ud_tx_thr_cb = gx_ir_test_ud_tx_thr_cb;
	cfg.ud_tx_full_cb = gx_ir_test_ud_tx_full_cb;
	cfg.ud_tx_empty_cb = gx_ir_test_ud_tx_empty_cb;
	cfg.user_data = &gx_ir_test_ring_buff;

	gx_ir_init(&hal_cfg);

12.3.1.2. 标准协议接收

接收配置参数 \ref GX_HAL_IR_RX_CFG_T,配置接口为 \ref gx_hal_ir_recv_cfg,接收接口为 \ref gx_hal_ir_recv_data_std,不同参数接收的方式参考示例代码中的标准协议接收实现。

    GX_HAL_IR_RX_CFG_T rx;
	uint32_t data = 0;
	uint8_t type = 0;
	uint8_t repeat = 0;
	int ret =0;

	memset(&rx, 0, sizeof(rx));
	rx.rx_thr_start = 0xbff;
	rx.rx_thr_data = 0xbff;
	rx.deb_legth = 0x17;
	rx.demod_legth = 0x07;
	rx.std_rx_tov = 180*1000;
	rx.demod_en = 1;
	rx.invert_en = 1; //翻转电平
	rx.deb_en = 1;
	gx_ir_recv_cfg(&rx, GX_HAL_IR_RECV_STD_MODE, GX_HAL_IR_ON);
	while(1)
	{
		ret = gx_ir_recv_data_std(&rx, (void*)&data, &type, 0);
		repeat = !!(type & 0x80);
		type = type & 0x7f;
		printf("%s(%x),recv type: %s %s, data: %x\r\n", ((ret==0)||(ret==0x10)) ? "Done" : "Error", ret,
			type == 0 ? "9012" :
			type == 1 ? "NEC" :
			type == 2 ? "RC5" :
			type == 3 ? "RC6" : "unknown",
			repeat ? "REPEAT" : "", data); //bit0~6, 0:9012,1:NEC,2:RC5,3:RC6; bit7, 1:重复码,0:键值
	}

12.3.1.3. 标准协议发送

发送配置参数 \ref GX_HAL_IR_TX_CFG_T,接收接口为 \ref gx_hal_ir_send_data_std,不同参数发送的方式参考示例代码中的标准协议发送实现。

    void gx_mdelay(unsigned int msec)
    {
        uint32_t i = 5000;
        while (msec--)
            while(i--);
    }


    GX_HAL_IR_TX_CFG_T tx = {0};
    uint32_t data[4] = {0x23456789,0xeeff1122,0x1b2b3b4b,0x90441c02};
    memset(&tx, 0, sizeof(tx));
    tx.type = 1; //NEC 协议类型
    tx.modulation_en = 1; //使能调制
    tx.data = (void*)data;
    tx.data_len = 4;
    gx_ir_send_data_std(&tx, gx_mdelay, 200);

    return 0;

12.3.1.4. 灵活模式接收

灵活模式接收可获取到连续的波形数据,包括波形周期计数和高电平计数,计数乘以分频后的 tick 即为电平时长。接收配置参数 \ref GX_HAL_IR_RX_CFG_T,配置接口为 \ref gx_hal_ir_recv_cfg,接收接口为 \ref gx_hal_ir_recv_data_ud,不同参数接收的方式参考示例代码中的灵活模式接收实现。

    GX_HAL_IR_RX_CFG_T rx;
    uint32_t data[256] = {0};
    GX_HAL_IR_UD_DATA_T *ir_ud = (GX_HAL_IR_UD_DATA_T *)data;
    #define GX_IR_UD_TICK     10 ///< ir clk(12M) / ud_div(120) = 100K, 10 us
    int ret = 0;

    memset(&rx, 0, sizeof(rx));
	rx.rx_thr_start = 0xbff;
	rx.rx_thr_data = 0xbff;
	rx.deb_legth = 0x17;
	rx.demod_legth = 0x07;
	rx.ud_rx_tov = 15000;
	rx.demod_en = 1;
	rx.invert_en = 1;
	rx.deb_en = 1;
	rx.ud_clk_div = 120-1; //100KHz,10 us
	rx.ud_rxfifo_thr = 0;
    gx_ir_recv_cfg(&rx);
    gx_ir_ud_rx_flush();
    ret = gx_ir_recv_data_ud(&rx, (void*)data, 256, 0);
    printf("ret %d,recv data:\r\n", ret);
    if(ret > 0)
    {
        for(int i = 0; i < ret; i++)
        {
            printf("%d:data %x, h %d us, l %d us\r\n", i, data[i], ir_ud[i].high_level_cnt*GX_IR_UD_TICK, \
                            (ir_ud[i].cycle_cnt-ir_ud[i].high_level_cnt)*GX_IR_UD_TICK);
        }
    }
    return ret;

12.3.1.5. 灵活模式发送

灵活模式发送连续的波形数据,数据格式为波形的电平和长度,参考 \ref GX_HAL_IR_UD_DATA_T 的定义。发送配置参数 \ref GX_HAL_IR_TX_CFG_T,接收接口为 \ref gx_hal_ir_send_data_ud。

以下为发送 MNEC 协议数据:

    GX_HAL_IR_TX_CFG_T tx;
    uint32_t data[64] = {0x04b00320,0x00640032,0x00c80032,0x00c80032,0x00c80032, /* 0111 */
                    0x00c80032,0x00640032,0x00640032,0x00c80032, /* 1001 */
                    0x00c80032,0x00c80032,0x00640032,0x00640032, /* 1100 */
                    0x00640032,0x00640032,0x00640032,0x00640032, /* 0000 */
                    0x00c80032,0x00c80032,0x00c80032,0x00c80032, /* 1111 */
                    0x00c80032,0x00c80032,0x00640032,0x00640032, /* 1100 */
                    0x00c80032,0x00640032,0x00640032,0x00c80032, /* 1001 */
                    0x00c80032,0x00c80032,0x00640032,0x00640032, /* 1100 */
                    0x00c80032};
    memset(&tx, 0, sizeof(tx));
    tx.modulation_en = 1;
    tx.ud_clk_div = 120-1;
    tx.ud_txfifo_thr = 3;
    tx.data = (void*)data;
    tx.data_len = 34;
    gx_ir_send_data_ud(&tx);

12.3.1.6. 中断方式接收标准协议

接收完成触发中断,并获取接收状态。通过回调函数传入接收数据和状态。中断接收启动接口为 \ref gx_hal_ir_recv_std_it_start,回调函数在初始化时配置。

    //接收完成回调
    int gx_ir_test_recv_std_cb(void* unsigned int data, unsigned char type, unsigned char error)
    {
        printf("data:%x, type:%d\r\n", data, type);
        if(error & GX_HAL_IR_CUSTOM_CODE_ERR) ///< custom code error
        {
            printf("custom code error!\r\n");
        }
        if(error & GX_HAL_IR_COMMAND_CODE_ERR) ///< command code error
        {
            printf("command code error!\r\n");
        }
        if(error & GX_HAL_IR_PORT_DET_ERR) ///< port_det_err
        {
            printf("port_det_error!\r\n");
        }

        return 0;
    }


    GX_HAL_IR_RX_CFG_T rx;

    memset(&rx, 0, sizeof(rx));
	rx.rx_thr_start = 0xbff;
	rx.rx_thr_data = 0xbff;
	rx.deb_legth = 0x17;
	rx.demod_legth = 0x07;
	rx.std_rx_tov = 180*1000;
	rx.demod_en = 1;
	rx.invert_en = 1;
	rx.deb_en = 1;
	rx.kdc_cmp_en = 1;
	rx.cc_cmp_en = 1;
    gx_ir_recv_std_it_start(&rx);

    return 0;

12.3.1.7. 中断方式接收灵活模式数据

通过中断方式接收一串红外数据,红外模块先将波形数据存入 FIFO,接收完成后产生完成中断,然后将数据读出。启动中断接收灵活模式数据接口 \ref gx_hal_ir_recv_ud_it_start,获取接收数据接口 \ref gx_hal_ir_get_ud_recv_data,回调函数在初始化时配置。回调中存入缓存 buffer,buffer 写入参考 \ref gx_ir_test_write_ud_recv_data。

int gx_ir_test_recv_ud_cb(void* ir_dev)
{
	uint32_t val = 0;
	uint16_t cnt = gx_ir_get_udrx_fifo_count();
	while(cnt--)
	{
		val = gx_ir_get_udrx_fifo_data();
		gx_ir_test_write_ud_recv_data((unsigned int*)&val, 1);
	}
	g_ud_rx_done =1;
	return 0;
}

/*灵活模式中断接收,通过中断方式接收一串红外数据,红外模块先将波形数据存入 FIFO,接收完成后产生完成中断,然后将数据读出*/
int gx_ir_test_recv_ud_it(void)
{
	GX_HAL_IR_RX_CFG_T rx;
	uint32_t data[256] = {0};
	GX_HAL_IR_UD_DATA_T *ir_ud = (GX_HAL_IR_UD_DATA_T *)data;
	#define GX_IR_UD_TICK     10 ///< ir clk(8M) / ud_div(80) = 100K, 10 us
	uint32_t ret =0;

	memset(&rx, 0, sizeof(rx));
	rx.rx_thr_start = 0xbff;
	rx.rx_thr_data = 0xbff;
	rx.deb_legth = 0x17;
	rx.demod_legth = 0x07;
	rx.ud_rx_tov = 22000;
	rx.demod_en = 1;
	rx.invert_en = 1;
	rx.deb_en = 1;
	rx.ud_clk_div = 120-1; //100KHz,10 us
	rx.ud_rxfifo_thr = 2;
	gx_ir_ud_rx_flush();
	gx_ir_recv_ud_it_start(&rx);
	while (1)
	{
		if(g_ud_rx_done == 0)
			continue;
		g_ud_rx_done = 0;
		printf("ud rx done.\r\n");

		ret = gx_ir_test_get_ud_recv_data((void*)data, 256);
		if(ret)
		{
			for(int i = 0; i < ret; i++)
			{
				printf("%d:data %x, h %d us, l %d us\r\n", i, data[i], ir_ud[i].high_level_cnt*10, \
								(ir_ud[i].cycle_cnt-ir_ud[i].high_level_cnt)*10);
			}
		}
	}
}

12.3.1.8. 中断方式发送灵活模式数据

通过发送灵活模式数据,发送完成后会触发中断,调用回调函数。启动中断发送灵活模式数据接口 \ref gx_hal_ir_send_ud_it_start,停止接口 \ref gx_hal_ir_send_ud_it_stop,回调函数在初始化时配置。

    volatile static uint8_t g_ud_tx_done = 0;
    static uint32_t *g_data;                                     /*!< 异步发送数据指针 */
    static uint32_t g_len;                                     /*!< 异步发送数据长度 */
    static uint32_t g_count;                                   /*!< 异步发数据计数 */

    /*灵活模式发送FIFO到达阈值回调函数*/
    int gx_ir_test_ud_tx_thr_cb(void* ir_dev)
    {
        int spare = ((GX_HAL_IR *)ir_dev)->tx_fifo_depth -gx_ir_get_udtx_fifo_count();
        while((spare > 0) && (g_count < g_len))
        {
            gx_ir_udtx_fifo_put(g_data[g_count]);
            g_count++;
            spare--;
        }
        printf("tx thr\r\n");
        return 0;
    }

    /*灵活模式发送FIFO空回调函数*/
    int gx_ir_test_ud_tx_empty_cb(void* ir_dev)
    {
        if(g_count == g_len)
            gx_ir_udtx_write_endflag();
        printf("tx fifo empty\r\n");
        return 0;
    }

    /*灵活模式中断发送,带调制*/
    int gx_ir_test_send_ud_it(void)
    {
        GX_HAL_IR_TX_CFG_T tx;
        uint32_t data[] = {0x04b00320,0x00640032,0x00c80032,0x00c80032,0x00c80032, /* 0111 */
                        0x00c80032,0x00640032,0x00640032,0x00c80032, /* 1001 */
                        0x00c80032,0x00c80032,0x00640032,0x00640032, /* 1100 */
                        0x00640032,0x00640032,0x00640032,0x00640032, /* 0000 */
                        0x00c80032,0x00c80032,0x00c80032,0x00c80032, /* 1111 */
                        0x00c80032,0x00c80032,0x00640032,0x00640032, /* 1100 */
                        0x00c80032,0x00640032,0x00640032,0x00c80032, /* 1001 */
                        0x00c80032,0x00c80032,0x00640032,0x00640032, /* 1100 */
                        0x00c80032};
        gx_ir_ud_tx_wait_done();
        memset(&tx, 0, sizeof(tx));
        tx.modulation_en = 1;
        tx.ud_clk_div = 120-1;
        tx.ud_txfifo_thr = 3;
        tx.data = (void*)data;
        tx.data_len = 34;
        g_ud_tx_done = 0;
        g_count = gx_ir_get_udtx_fifo_depth() > tx.data_len ? tx.data_len : gx_ir_get_udtx_fifo_depth();
        g_len = tx.data_len;
        g_data = data;
        gx_ir_send_ud_it_start(&tx);

        while(g_ud_tx_done == 0);

        return 0;
    }