大家好,关于W801的DMA使用,我是用DMA捕获输入PWM信号的占空比,根据手册上升沿下降沿均会捕获当前计数值到捕获寄存器,使用DMA关联PWM捕获可以减少中断次数,有几个问题咨询一下:
1、因为一直要进行捕获,所以想把DMA设置成一直捕获,接收缓冲区循环存储捕获值,存满了从头再开始存储,请问如何设置?
2、手册中“DMA数据流控制寄存器”有一个auto_reload标志,这个标志是什么含义?没有设置为循环模式时,该位置为1是不是DMA就可以一直循环发送下去?该位置一的时候DMA发送完成中断会每发完一次重复发生吗?
3、DMA循环长度寄存器,里面有两个长度,一个是目的地址循环长度,一个是源地址循环长度,这个长度单位是字节还是字?比如DMA捕获输入PWM信号的占空比存到内部缓冲区,按WORD方式传送,burst 1,缓冲区长度100字节,这两个长度参数如何设置?另外这种循环模式下,DMA传输完成中断是什么时候发生?我试了多种可能都没跑起来。
提前感谢各位大佬热心帮忙!
不知道这个demo对你有没有帮助
/*****************************************************************************
*
* File Name : main.c
*
* Description: main
*
* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd.
* All rights reserved.
*
* Author : dave
*
* Date : 2014-6-14
*****************************************************************************/
#include "wm_include.h"
#include "wm_cpu.h"
#include "wm_dma.h"
u8 send_data[8] = {0};
u8 recv_data[8] = {0};
static void gpio_dma_callback(void)
{
printf("--->%s\r\n",__func__);
printf("recv_data:");
for(int i = 0; i < 8; i++)printf("%02X ",recv_data[i]);
printf("\n");
}
void UserMain(void)
{
extern void tls_sys_clk_set();
extern u32 tls_mem_get_avail_heapsize(void);
tls_sys_clk_set(CPU_CLK_80M);
printf("\n \\\\\\|///\n");
printf(" \\\\ .-.- //\n");
printf(". ( .@.@ ) \n");
printf("+-------oOOo-----(_)-----oOOo---------+\n\n");
printf(" ---> Compile "__DATE__", "__TIME__"\n");
printf(" ---> %s.c\r\n",__func__);
printf(" ---> GetHeap:%d\n",tls_mem_get_avail_heapsize());
printf("\n+---------------------Oooo------------+\n");
u8 dmaCh;
struct tls_dma_descriptor DmaDesc;
printf("send_data:");
for(int i = 0; i < 8; i++)printf("%02X ",send_data[i]);
printf("\n");
printf("recv_data:");
for(int i = 0; i < 8; i++)printf("%02X ",recv_data[i]);
printf("\n");
for(int i = 0; i < (sizeof(send_data)/sizeof(char)); i++)
{
send_data[i] = i;
}
printf("send_data:");
for(int i = 0; i < 8; i++)printf("%02X ",send_data[i]);
printf("\n");
printf("recv_data:");
for(int i = 0; i < 8; i++)printf("%02X ",recv_data[i]);
printf("\n");
dmaCh = tls_dma_request(1, 0);
printf("send_data:%08X\n",&send_data[0]);
DmaDesc.src_addr = send_data;
DmaDesc.dest_addr = recv_data;
printf("src_addr: %08X\n",DmaDesc.src_addr);
printf("dest_addr:%08X\n",DmaDesc.dest_addr);
DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_DEST_ADD_INC |TLS_DMA_DESC_CTRL_SRC_ADD_INC | TLS_DMA_DESC_CTRL_BURST_SIZE1 | TLS_DMA_DESC_CTRL_DATA_SIZE_BYTE | TLS_DMA_DESC_CTRL_TOTAL_BYTES(8);
DmaDesc.valid = TLS_DMA_DESC_VALID;
DmaDesc.next = NULL;
tls_dma_start(dmaCh, &DmaDesc, 0);
tls_dma_irq_register(dmaCh, (void (*))gpio_dma_callback, NULL, TLS_DMA_IRQ_TRANSFER_DONE);
}
@isme 非常感谢,这段代码可以实现DMA传送,但是好像不能循环发送。我的应用是捕获来自PWM的占空比,捕获后通过DMA传送到RAM缓冲区。我对这个占空比的计算不必实时处理,需要的时候处理一下就可以。这个PWM频率比较高,为了节约RAM以及减少中断(PWM中断和DMA中断最好都不用),我设定一个固定长度的缓冲区,DMA填满以后自动从头再填,循环往复。我需要用的时候直接读最近的一批缓冲区数据就可以。