首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从计时器计数到内存的STM32 DMA

从计时器计数到内存的STM32 DMA
EN

Stack Overflow用户
提问于 2020-04-12 19:55:53
回答 2查看 5.2K关注 0票数 4

我用的是STM32H743。我有一个外部时钟信号进入GPIO引脚,我想非常准确地测量每一个上升(或下降)边缘之间的外部时钟信号。所以我设置好了,TIM4由外部时钟触发,TIM5由内部振荡器触发。

我编写了一个IRQ,这样每当TIM4触发时,就会运行一个中断来捕获TIM5的值。它似乎工作正常,但我想知道我是否可以通过DMA来避免所有上下文切换和释放CPU。基本上,我希望设置一个DMA,以便每个TIM4事件启动一个DMA传输,将TIM5计数器值复制到某个循环缓冲区。

我已经搜索过论坛和DMA文档,但我不清楚计时器寄存器是否可以是有效的DMA源。我在想也许我可以做这样的事:

代码语言:javascript
运行
复制
hDma->PAR = (uint32_t) &htim5.Instance->CNT;
hDma->M0AR = (uint32_t) myBufferPtr;
hDma->NDTR = myBufferSize;
hDma->CR |= (uint32_t)DMA_SxCR_EN;

但我不确定这能不能用。

短版本:我可以使用计时器的CNT寄存器作为DMA传输源吗?会是外设到内存的传输吗?还是从记忆到记忆的转移?我还需要其他旗帜才能让这件事成功吗?还是说不可能?还是有另一个STM32特性可以使计算脉冲之间的时间更容易呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-15 10:40:48

免责声明

我必须承认,到目前为止,我在STM32方面的长期实践经验一直停留在主流控制器家庭,如STM32F0、STM32F3、STM32F4和STM32L4。因此,我是根据那些控制器在你的情况下会给你提供什么来回答的。STM32H7系列要强大得多,更不用说它还提供了一些附加的DMA技术,如DMA2D、MDMA和许多我不确定的东西。但我认为一个简化的答案也可能对你有帮助,所以我敢写它。

我可以使用计时器的CNT寄存器作为DMA传输源吗?会是外设到内存的传输吗?还是从记忆到记忆的转移?我还需要其他旗帜才能让这件事成功吗?还是说不可能?

我希望这能奏效。我看不出有什么理由不在DMA传输中读取TIMx_CNT寄存器。

CNT寄存器绝对是一个外围地址,所以您必须将它配置为外设到内存的传输。我认为,外设/内存分离是指DMA控制器从每一个STM32中实现的总线矩阵中获取数据(或从它传递数据的总线)的总线。

还是有另一个STM32特性可以使计算脉冲之间的时间更容易呢?

是的,有:许多TIM外围设备(并不都是相同的)为您提供了一个名为“输入捕获”的功能,它将TIM实例的通道(子)外围设备连接到输入端,并具有(相同的!)蒂姆外围做内部时钟。前提是,您想要测量的引脚有一个TIMx_CHy备用函数,而不是“仅”一个TIMx_ETR函数。

TIM外围设备提供了丰富的各种不同配置选项--只要您还不习惯,就会有复杂的混乱。作为一个介绍和一个很好的概述,我推荐来自ST的两个申请说明:

查找这两个,我找到了第三个您可能需要检查的更好的精度,与HRTIM计时器相关:

票数 6
EN

Stack Overflow用户

发布于 2021-08-17 02:14:43

使用STM32CubeIDE配置器很容易做到:

  1. 配置定时器,启用输入捕获通道,启用DMA (模式循环,外设到内存,数据宽度字/字)。启用中断。
  2. 准备用于存储捕获的计数器值的缓冲区
  3. 主回路前DMA方式启动集成电路
  4. 对于高速操作,您可以在这些回调中将数据从timerCaptureBuffer复制到timerCaptureBufferSafe。例如,DMA内存到内存传输,以尽量减少在HAL_TIM_IC_CaptureHalfCpltCallback和HAL_TIM_IC_CaptureCallback中断中花费的时间。对存储在timerCaptureBufferSafe内存中的相邻捕获值进行处理,对内存回调信号数据做好准备。您可以使用信令标志,这样timerCaptureBufferSafe就不会被覆盖。

下面是一个示例:

代码语言:javascript
运行
复制
#define TIM_BUFFER_SIZE 128
uint32_t timerCaptureBuffer[TIM_BUFFER_SIZE];
uint32_t timerCaptureBufferSafe[TIM_BUFFER_SIZE];
// ...

HAL_DMA_RegisterCallback(&hdma_memtomem_dma2_stream2,
HAL_DMA_XFER_CPLT_CB_ID,
myDMA_Callback22);
// ...

HAL_TIM_IC_Start_DMA(&htim2, TIM_CHANNEL_1, uint32_t*)timerCaptureBuffer,TIM_BUFFER_SIZE);
// ...

void HAL_TIM_IC_CaptureHalfCpltCallback(TIM_HandleTypeDef *htim)
{
    HAL_DMA_Start_IT(&hdma_memtomem_dma2_stream2,
    (uint32_t)&timerCaptureBuffer[0],
    (uint32_t)&timerCaptureBufferSafe[0],
    sizeof(timerCaptureBuffer)/2/4);
    // ...
}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    HAL_DMA_Start_IT(&hdma_memtomem_dma2_stream2,
    (uint32_t)&timerCaptureBuffer[TIM_BUFFER_SIZE/2],
    (uint32_t)&timerCaptureBufferSafe[TIM_BUFFER_SIZE/2],
    sizeof(timerCaptureBuffer)/2/4);
    // ...
}
void myDMA_Callback22(DMA_HandleTypeDef *_hdma)
{
    //...
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61177322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档