大家好, 关于 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 填满以后自动从头再填, 循环往复. 我需要用的时候直接读最近的一批缓冲区数据就可以.