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;
}