IR - tx_dma

本 demo 主要介绍 IR 使用 DMA 的方式发送数据。

硬件连接

本 demo 使用到的 gpio 参考 board_ir_gpio_init ,将红外发射二极管与 IR 引脚连接,具体连接方式如下表(以BL808为例):

硬件连接

开发板 IR 引脚

外接模块

VCC

红外发射二极管正极

TX(GPIO11)

红外发射二极管负极

软件实现

更详细的代码请参考 examples/peripherals/ir/ir_tx_dma

1board_init();
  • board_init 中会开启 IR 时钟,并选择 IR 时钟源和分频。

1board_ir_gpio_init();
  • 配置相关引脚为 IR 功能

 1struct bflb_ir_tx_config_s tx_cfg = {
 2    .tx_mode = IR_TX_CUSTOMIZE,
 3    .data_bits = 0,
 4    .tail_inverse = 0,
 5    .tail_enable = 0,
 6    .head_inverse = 0,
 7    .head_enable = 0,
 8    .logic1_inverse = 1,
 9    .logic0_inverse = 1,
10    .data_enable = 1,
11    .swm_enable = 0,
12    .output_modulation = 1,
13    .output_inverse = 0,
14    .freerun_enable = 1,
15    .continue_enable = 1,
16    .fifo_width = IR_TX_FIFO_WIDTH_24BIT,
17    .fifo_threshold = 1,
18    .logic0_pulse_width_1 = 0,
19    .logic0_pulse_width_0 = 0,
20    .logic1_pulse_width_1 = 2,
21    .logic1_pulse_width_0 = 0,
22    .head_pulse_width_1 = 0,
23    .head_pulse_width_0 = 0,
24    .tail_pulse_width_1 = 0,
25    .tail_pulse_width_0 = 0,
26    .modu_width_1 = 17,
27    .modu_width_0 = 34,
28    .pulse_width_unit = 1124,
29};
30
31irtx = bflb_device_get_by_name("irtx");
32
33/* TX init */
34bflb_ir_tx_init(irtx, &tx_cfg);
35bflb_ir_link_txdma(irtx, true);
36bflb_ir_tx_enable(irtx, true);
  • 获取 irtx 句柄

  • 设置 tx_mode 为 IR_TX_CUSTOMIZE 模式,调用 bflb_ir_tx_init(irtx, &tx_cfg) 初始化 ir tx

  • 调用 bflb_ir_link_txdma(irtx, true) 使能 ir tx dma 功能

  • 调用 bflb_ir_tx_enable(irtx, true) 开启 ir tx

 1struct bflb_dma_channel_config_s dma_config = {
 2    .direction = DMA_MEMORY_TO_PERIPH,
 3    .src_req = DMA_REQUEST_NONE,
 4    .dst_req = DMA_REQUEST_IR_TX,
 5    .src_addr_inc = DMA_ADDR_INCREMENT_ENABLE,
 6    .dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE,
 7    .src_burst_count = DMA_BURST_INCR1,
 8    .dst_burst_count = DMA_BURST_INCR1,
 9    .src_width = DMA_DATA_WIDTH_32BIT,
10    .dst_width = DMA_DATA_WIDTH_32BIT,
11};
12
13for (i = 0; i < 128; i++) {
14    tx_buffer[i] = i * 0x01010101;
15}
16
17dma0_ch0 = bflb_device_get_by_name("dma0_ch0");
18bflb_dma_channel_init(dma0_ch0, &dma_config);
19bflb_dma_channel_irq_attach(dma0_ch0, dma0_ch0_isr, NULL);
  • 对于 TX, DMA 的配置如下:传输方向(direction)为内存到外设(MEMORY_TO_PERIPH),源请求(src_req)为内存,目标请求(dst_req)为 DMA_REQUEST_IR_TX

  • 初始化 tx_buffer

  • 调用 bflb_dma_channel_init(dma0_ch0, &dma_config) 初始化 DMA

  • 调用 bflb_dma_channel_irq_attach(dma0_ch0, dma0_ch0_isr, NULL) 注册 dma 通道 0 中断

1struct bflb_dma_channel_lli_pool_s tx_llipool[1];
2struct bflb_dma_channel_lli_transfer_s tx_transfers[1];
3
4tx_transfers[0].src_addr = (uint32_t)tx_buffer;
5tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_IR_TDR;
6tx_transfers[0].nbytes = 128 * 4;
7bflb_dma_channel_lli_reload(dma0_ch0, tx_llipool, 1, tx_transfers, 1);
8bflb_dma_channel_start(dma0_ch0);
  • 分配一块 lli 内存池,最多可以传输 4064 * 1 字节

  • 配置一块内存(tx_transfers)进行传输,源地址(src_addr)为存储发送数据的内存地址(tx_buffer),目标地址(dst_addr)为 IR TX FIFO地址(DMA_ADDR_IR_TDR)

  • 调用 bflb_dma_channel_lli_reload(dma0_ch0, tx_llipool, 1, tx_transfers, 1) 初始化

  • 调用 bflb_dma_channel_start(dma0_ch0) 启动 DMA 传输

1while (dma_tc_flag0 != 1) {
2    bflb_mtimer_delay_ms(1);
3}
4printf("Check wave\r\n");
  • DMA 传输完成后,查看波形

编译和烧录

参考 环境搭建

实验现象

按下 RST 按键,数据传输完成后,查看波形是否正确。