所有关于电路
项目

数模转换与SAM4S外围DMA控制器

2016年5月9日通过罗伯特Keim

第三部分在这三篇系列文章向您展示了如何生成值离散的正弦信号,不断将这些数据转换成模拟信号而不造成了CPU的负担过重。

第三部分在这三篇系列文章向您展示了如何生成值离散的正弦信号,不断将这些数据转换成模拟信号而不造成了CPU的负担过重。

支持信息

所需的硬件/软件

前面的文章

别紧张你的处理器

在前一篇文章中,我们完成了一些艰苦的过程配置数模转换器控制器(通道),然后我们无限使用while循环,不断生成一个三角形波。这决不是一个微不足道的成就,但与此同时,它将远离理想CPU的负担所需的所有指令继续DAC的活动。

假设我们使用1 MHz的DAC采样率;如果单片机有其他重要的任务来执行,这将是严重不便的处理器每秒一百万次,被迫中断执行不同的指令需要访问数组,增加一个计数器,数据加载到通道的conversion-data登记,或执行其他任务,可能需要在一个特定的应用程序。

当然,芯片设计者早已认识到这个problem-why阻塞一个复杂的微处理器和一些简单的数据从一个内存位置移动到另一个?为什么不加入另一个“处理器”,知道如何移动数据,多一点,让这个subprocessor减轻CPU的负担吗?好吧,事实证明,这的确是一个很好的想法,而这些数据交换subprocessors-referred为直接内存访问(DMA)控制器都被纳入许多微控制器和数字信号处理器。

在项目的这个阶段,我们将添加DMA功能对我们的数模转换利用SAM4S外围的DMA控制器(PDC)。在这个模块的帮助下,我们可以将正弦波值从RAM通道conversion-data注册以最小的CPU干预。下面的表,从491页的SAM4S数据表(PDF),列出了支持的PDC的外围设备:

右边的“数字频道”表明PDC使用优先级处理多个传输请求时,通道0是最高优先级。我们不需要担心任何优先级业务在这个项目中,因为我们使用的是只有一个PDC外围。还要注意一些渠道支持发送和接收,这意味着您可以使用PDC,例如,移动数据的UART传输和存储数据由UART接收。

首先,一些三角学

在我们使用PDC移动正弦信号的数据通道,我们需要正弦信号数据。让我们看一下如何生成离散正弦波值。首先我们需要包含一个头文件,将提供我们需要的数学功能。我们将使用“arm_math。h”文件,它给了我们罪()函数,定义了π为3.14159265358979。现在让我们提醒自己一个正弦波的一些基本特征:

当我们使用sin()函数,值对应于一个完整的周期要求参数范围从0到2π。sin()函数返回0,当参数是0,π,或2π;它返回1(最大值)当论点就是介于0到π(即。π/ 2),它将返回1时(最小值)的观点是π2π的正中间(即。3π/ 2)。创建一个正弦信号的最大和最小值不同于1和1,我们sin()返回值乘以一个常数称为振幅。我们也可以给offset-e.g正弦信号。上面,提高它的轴,这样没有部分波扩展低于0添加一个常数相乘而导致的所有数据点的返回值振幅。

所以如果我们想生成一个正弦波周期,第一个罪()参数是0,最后一个应该是2π。但是我们之间所有的参数吗?嗯,在这一点上我们需要决定有多少数据点,即样品,我们希望每个正弦波周期。然后我们2π除以每周期来确定样品的数量多少的观点从一个数据点增加到下一个。

下面的代码应该有助于您理解整个discrete-sine生成过程:

/ /变量的离散时间正弦波uint16_t SineWave_12bit [SAMPLES_PER_CYCLE];浮动DiscreteSineArgument DiscreteSineArgumentStep;DiscreteSineArgument = 0;DiscreteSineArgumentStep =(2 *π)/ SAMPLES_PER_CYCLE;(n = 0;n < SAMPLES_PER_CYCLE;n + +) {SineWave_12bit [n] = (uint16_t) ((SINE_AMPLITUDE * sin (DiscreteSineArgument)) + SINE_MIDRANGE);DiscreteSineArgument = DiscreteSineArgument + DiscreteSineArgumentStep;}

我喜欢平滑正弦波,所以在这个项目中,我们将使用100样本/周期。SINE_AMPLITUDE设置为2047.5,即。,一半12位DAC的范围。这意味着最大值将2047.5项以上中型值和最小值将2047.5计数低于中等价值,因此正弦波将涵盖DAC的整个4095 -计数输出范围。

SINE_MIDRANGE也设置为2047.5,因为我们想要的最小值在0。(通常是0项对应一个模拟输出电压为0 V,但在SAM4S DAC, 0项对应于模拟参考电压的六分之一。这个问题简要讨论的结果和结论”部分前一篇文章)。

回到了PDC

这是激发PDC通道所涉及的步骤:

  1. 添加PDC ASF模块(我不知道为什么它被称为“外围DMA控制器例子”):

  1. 定义一个结构类型pdc_packet_t,用于PDC通道配置,和一个指针类型的变量PDC,用来点外围的PDC的基地址寄存器。
  2. 相关的地址加载到基地址使用函数指针对应于您正在使用的外围;对于这个项目,函数是dacc_get_pdc_base ()。
  3. 使用pdc_packet_t结构来存储起始地址和长度的DMA传输。长度是指字节如果您正在8位数据,半字如果你是16位的数据移动,如果你正在32位数据和文字。
  4. 使用pdc_tx_init配置DMA通道传输或接收()或pdc_rx_init()会同pdc_packet_t结构。
  5. 启动PDC转移使用pdc_enable_transfer ()。

PDC自动移动数据在适当的时间,因为它的操作是由传输和/或接收信号控制的边缘地位。例如,通道,PDC转移新数据只有当通道的transmit-ready信号表明,DAC硬件准备执行一个新的转换。

上述过程可以翻译成代码如下:

/ / PDC变量pdc_packet_t DACC_PDC_Config;Pdc * PDC_ptr_to_DACC;PDC_ptr_to_DACC = dacc_get_pdc_base(通道);DACC_PDC_Config。ul_addr = (uint32_t) SineWave_12bit;DACC_PDC_Config。ul_size = SAMPLES_PER_CYCLE;pdc_tx_init (PDC_ptr_to_DACC &DACC_PDC_Config &DACC_PDC_Config);pdc_enable_transfer (PDC_ptr_to_DACC PERIPH_PTCR_TXTEN);

我们仍然需要CPU

PDC完成时将所有的数据从缓冲通道,一个中断是用来引起CPU干预;处理器需要知道PDC转移完成,这样就可以重新配置PDC通道,从而确保正弦波数据不断移动的通道。所以,参与实现PDC的最后一个步骤是启用适当的中断和建立一个中断服务例程(ISR)时将执行PDC已经完成了转移。

在ISR,我们只是配置PDC通道相同的缓冲区长度和传输。由于通道的集成FIFO(在“基础”的讨论前一篇文章),处理器应该没有困难完成本重配置通道耗尽之前转换数据。

这是interrupt-related代码:

int主要(空白){。/ /启用通道的“传输缓冲区的终结”中断dacc_enable_interrupt(通道,DACC_IMR_ENDTX);/ /启用通道中断的嵌套矢量中断控制器NVIC_EnableIRQ (DACC_IRQn);。}无效DACC_Handler (void){/ /确认如果发射的“中断传输缓冲区的终结”(dacc_get_interrupt_status(通道)& DACC_ISR_ENDTX){/ /配置PDC这样正弦波的一代继续pdc_tx_init (PDC_ptr_to_DACC, &DACC_PDC_Config &DACC_PDC_Config);}}

您可能想知道如何爱特梅尔公司工作室知道DACC_Handler()函数是通道ISR-there没有显式地指定它。嗯,实际上是愉快地简单:函数名“DACC_Handler”是官方的标识符为通道的ISR,所有你要做的就是名字的函数DACC_Handler(),它会自动被用作任何通道的ISR中断。这个方案同样适用于其他peripherals-ADC_Handler (), UART0_Handler(),等等。

一个缓冲还是两个?

当你使用pdc_tx_init配置PDC通道()或pdc_rx_init(),您必须指定的起始地址和长度转移“当前”转移。但是,您可以选择指定起始地址和传输长度的“下一个”转移。在上面的代码中,我配置了频道为“当前”和“下一个”转移。配置只有一个传输通道,您可以使用NULL第三个参数,如下:

pdc_tx_init (PDC_ptr_to_DACC &DACC_PDC_Config, NULL);

使用这两种传输的优点是减少CPU的干预;CPU配置PDC通道后,两个缓冲区,而不是一个。我想two-transfer配置也会方便的如果你想移动数据或从一个缓冲然后或从不同的缓冲:您可以设置两个缓冲区与一个叫pdc_rx_init()或pdc_tx_init(),从而保持适当的序列不确定哪些缓冲所需的CPU被只是感动。

结果

您可以使用以下链接下载源和项目文件:

DMA_DAC_SineWave_Part3.zip

这里是一个捕捉范围显示生成的正弦波DAC:

注意,频率10 kHz。这就是我们期望:样品周期是1 / (1 MHz) = 1µs,我们有100个样本每循环。因此,正弦波周期100µs, 1 /(100µs) = 10 kHz。我们可以概括如下:

\ [f{正弦}= \压裂{样本\速度}{样品周期\ / \}\]

如果你想要一个更高的正弦波的频率,你可以减少样品每循环(导致低质量的波形)或增加采样率(SAM4S DAC的最大沉降时间是0.5µs,因此你也许不会把采样率超出2 MHz)。

结论

系列在这个项目中我们详细看看定时器/计数器模块、数模转换器控制器外围DMA控制器,和一些代码来生成一个离散时间正弦波。这个功能证明可以用于各种各样的应用程序。这样一个application-namely,生成基带波形软件定义无线电将是以后的一篇文章的主题。