IR Transmit - DMA Transfer
该示例演示红外发送功能的使用方法。
该实例使用 IR 外设利用 DMA 搬运进行数据发送,实现红外发射功能。
使用逻辑分析仪观察 IR 发送波形。
环境需求
该示例支持以下开发套件:
Hardware Platforms |
Board Name |
---|---|
RTL8752H HDK |
RTL8752H EVB |
更多信息请参考 快速入门。
硬件连线
连接 IR 发送引脚 P2_5 至逻辑分析仪。
编译和下载
该示例的工程路径如下:
Project file: board\evb\io_sample\IR\Tx+GDMA\mdk
Project file: board\evb\io_sample\IR\Tx+GDMA\gcc
请按照以下步骤操作构建并运行该示例:
打开工程文件。
按照 快速入门 中 编译 APP Image 给出的步骤构建目标文件。
编译成功后,在路径
mdk\bin
或gcc\bin
下会生成 app binapp_MP_xxx.bin
文件。按下 reset 按键,开始运行。
测试验证
在逻辑分析仪内,观察 IR 发送波形。波形如下图所示:

IR 发送波形
代码介绍
该章节分为以下几个部分:
源码路径
工程路径:
sdk\board\evb\io_sample\IR\Tx+GDMA
源码路径:
sdk\src\sample\io_sample\IR\Tx+GDMA
该工程的工程文件代码结构如下:
└── Project: tx_gdma
└── secure_only_app
└── include
├── app_define.h
└── rom_uuid.h
├── cmsis includes CMSIS header files and startup files
├── overlay_mgr.c
├── system_rtl876x.c
└── startup_rtl876x.s
├── lib includes all binary symbol files that user application is built on
├── rtl8752h_sdk.lib
├── gap_utils.lib
├── ROM.lib
└── adc.lib
├── peripheral includes all peripheral drivers and module code used by the application
├── rtl876x_rcc.c
├── rtl876x_pinmux.c
├── rtl876x_nvic.c
├── rtl876x_gdma.c
└── rtl876x_ir.c
├── profile
└── app includes the ble_peripheral user application implementation
└── main.c
初始化
当 EVB 复位启动时,执行 main
函数,执行以下流程:
int main(void)
{
extern uint32_t random_seed_value;
srand(random_seed_value);
__enable_irq();
ir_demo();
...
}
在 ir_demo
中,包含了 PAD/PINMUX 设置,IR 外设初始化和 DMA 外设初始化流程。
void ir_demo(void)
{
...
board_ir_init();
driver_ir_init(IR_Send_Data.CarrierFreq);
driver_ir_gdma_init();
...
}
board_ir_init
为 IR 相关引脚的 PAD 与 PINMUX 设置,包含如下流程:
配置 PAD:设置引脚、PINMUX 模式、PowerOn、无内部上拉,输出低。
配置 PINMUX:分配引脚为 IRDA_TX 功能。
driver_ir_init
为对 IR 外设的初始化,包含如下流程:
使能 RCC 时钟。
设置 IR 发送频率为 38kHz。
设置 IR 载波占空比为 1/3。
设置 IR 为发送模式。
设置不反转 IR 发送数据。
设置 IR 发送 FIFO 阈值为 2。
使能 IR DMA 发送,设置 waterLevel。
void driver_ir_init(uint32_t vFreq) { /* Enable ir clock */ RCC_PeriphClockCmd(APBPeriph_IR, APBPeriph_IR_CLOCK, ENABLE); /* Initialize ir */ IR_InitTypeDef IR_InitStruct; IR_StructInit(&IR_InitStruct); IR_InitStruct.IR_Freq = vFreq;//vFreq; IR_InitStruct.IR_DutyCycle = 3; /* !< 1/3 duty cycle */ IR_InitStruct.IR_Mode = IR_MODE_TX; IR_InitStruct.IR_TxInverse = IR_TX_DATA_NORMAL; IR_InitStruct.IR_TxFIFOThrLevel = IR_TX_FIFO_THR_LEVEL; IR_InitStruct.IR_TxDmaEn = ENABLE; IR_InitStruct.IR_TxWaterLevel = 15; IR_Init(&IR_InitStruct); }
driver_ir_gdma_init
为对 DMA 外设的初始化,包含如下流程:
使能 RCC 时钟。
使用 DMA 通道 1。
DMA 的传输方向为内存到外设传输。
源端地址为
GDMA_Send_Buf
,目的端地址为&IR->TX_FIFO
。使能 DMA 通道 1 总传输完成中断
GDMA_INT_Transfer
。使能 DMA 传输。
void driver_ir_gdma_init(void) { RCC_PeriphClockCmd(APBPeriph_GDMA, APBPeriph_GDMA_CLOCK, ENABLE); GDMA_InitTypeDef GDMA_InitStruct; /*--------------GDMA init-----------------------------*/ GDMA_StructInit(&GDMA_InitStruct); GDMA_InitStruct.GDMA_ChannelNum = IO_TEST_GDMA_CHANNEL_MUM; GDMA_InitStruct.GDMA_BufferSize = IO_TEST_GDMA_TRANSFER_SIZE; GDMA_InitStruct.GDMA_DIR = GDMA_DIR_MemoryToPeripheral; GDMA_InitStruct.GDMA_SourceInc = DMA_SourceInc_Inc; GDMA_InitStruct.GDMA_DestinationInc = DMA_DestinationInc_Fix; GDMA_InitStruct.GDMA_SourceDataSize = GDMA_DataSize_Word; GDMA_InitStruct.GDMA_DestinationDataSize = GDMA_DataSize_Word; GDMA_InitStruct.GDMA_SourceMsize = GDMA_Msize_1; GDMA_InitStruct.GDMA_DestinationMsize = GDMA_Msize_1; GDMA_InitStruct.GDMA_SourceAddr = (uint32_t)(GDMA_Send_Buf); GDMA_InitStruct.GDMA_DestinationAddr = (uint32_t)(&IR->TX_FIFO); GDMA_InitStruct.GDMA_DestHandshake = GDMA_Handshake_IR_TX; GDMA_Init(IO_TEST_GDMA_Channel, &GDMA_InitStruct); GDMA_INTConfig(IO_TEST_GDMA_CHANNEL_MUM, GDMA_INT_Transfer, ENABLE); /*-----------------GDMA IRQ init-------------------*/ NVIC_InitTypeDef nvic_init_struct; nvic_init_struct.NVIC_IRQChannel = IO_TEST_GDMA_Channel_IRQn; nvic_init_struct.NVIC_IRQChannelCmd = (FunctionalState)ENABLE; nvic_init_struct.NVIC_IRQChannelPriority = 3; NVIC_Init(&nvic_init_struct); GDMA_Cmd(IO_TEST_GDMA_CHANNEL_MUM, ENABLE); }
功能实现
定义 IR 发送数据数组:有载波数据用载波个数与 0x80000000 进行或运算表示,无载波数据用载波个数与 0x00000000 进行或运算表示。
执行
IR_Cmd()
,使能 IR 外设发送功能。void ir_demo(void) { /* Data to send */ IR_Send_Data.CarrierFreq = 38000; IR_Send_Data.DataLen = IO_TEST_GDMA_TRANSFER_SIZE; IR_Send_Data.DataBuf[0] = 0x80000000 | 0x200; IR_Send_Data.DataBuf[1] = 0x00000000 | 0x100; for (uint16_t i = 2; i < IR_Send_Data.DataLen - 1;) { IR_Send_Data.DataBuf[i] = 0x80000000 | (0x0A + i * 5); IR_Send_Data.DataBuf[i + 1] = 0x00000000 | (0x14 + i * 5); i += 2; } IR_Send_Data.DataBuf[IR_Send_Data.DataLen - 1] = 0x80000000 | 0x800; /* Test data buffer */ for (uint32_t i = 0; i < IO_TEST_GDMA_TRANSFER_SIZE; i++) { GDMA_Send_Buf[i] = IR_Send_Data.DataBuf[i]; } ... IR_Cmd(IR_MODE_TX, ENABLE); }
当 DMA 搬运数据完成时,触发
GDMA_INT_Transfer
中断,进入 DMA 中断处理函数IO_TEST_GDMA_Channel_Handler
。失能 DMA 通道 1 总传输完成中断
GDMA_INT_Transfer
,失能 DMA 通道 1 传输,清除中断挂起位。待 IR 波形全部打出后,在逻辑分析仪内可观察到 IR 发送波形。
void IO_TEST_GDMA_Channel_Handler(void) { GDMA_INTConfig(IO_TEST_GDMA_CHANNEL_MUM, GDMA_INT_Transfer, DISABLE); GDMA_Cmd(IO_TEST_GDMA_CHANNEL_MUM, DISABLE); DBG_DIRECT("IO_TEST_GDMA_Channel_Handler\r\n"); GDMA_ClearINTPendingBit(IO_TEST_GDMA_CHANNEL_MUM, GDMA_INT_Transfer); }