雷竞技注册
项目

了解和使用SAM4S数模转换器

2016年5月4日,经过罗伯特·凯

这个由三篇文章组成的系列文章的第2部分将探讨SAM4S DAC。我们将查看硬件配置、电气特性和应用程序编程接口。

这个由三篇文章组成的系列文章的第2部分将探讨SAM4S DAC。我们将查看硬件配置、电气特性和应用程序编程接口。

支持信息

所需的硬件/软件

前一篇文章

的通道

本文的目标是使SAM4S通道(数模转换器控制器)生成一个简单的三角波(我们将切换到一个正弦波,将直接内存访问,在第3部分中),年底这篇文章中,我们将介绍各种重要的细节与DAC的电特性,控制DAC操作的寄存器,以及Atmel软件框架(ASF)提供的软件接口。在我看来,SAM4S数据表中的DACC部分和ASF的DACC模块的文档并不像它们可能的那样清晰和信息丰富。如果您过去在使用DACC时遇到过困难,那么本文将扩展和巩固您对这个方便的外设的理解。如果您是DACC的新手,这将是一个全面而有益的介绍。

基础知识

SAM4S DACC包括两个相同,独立的数字到模数通道。它们提供12位分辨率,这意味着写入DAC转换数据寄存器的值可以是0到0到(212.- 1),即4095.如前一篇文章所讨论的那样,DAC可以运作不同步的模式,其中写入转换数据寄存器的写入启动模拟输出的更新,或者触发模式,其中更新在内​​部或外部同步信号上由上升沿启动。我们将使用触发模式来确保更新之间的相同间隔;在上一篇文章中,我们配置了定时器/计数器模块0的通道1,以提供100 kHz平方波以触发DAC。这是触发信号的范围捕获;它在内部路由到DACC,但我们也在港口引脚上驱动它,以便我们可以探测它。

两个DAC通道都可以通过SAM4S外设直接存储器访问控制器更新(直接存储器访问缩写为DMA,并且该控制器模块又缩写为PDC)。PDC允许我们连续向DAC发送新的转换值,CPU参与最小。我们将在第3部分介绍该项目的PDC部分。

最后,您应该意识到DACC包含一个先进的(FIFO)转换数据缓冲区。忘记这个缓冲区很容易,因为你没有直接与它互动;相反,您只需将数据写入转换数据寄存器,而DAC硬件则其余部分。即,如果它仍然占用以前的转换,则它将数据存储在FIFO中,然后当DAC可用于新的转换过程时,请检索数据。

这个FIFO并没有您想象的那么有用,因为它只能存储4个转换值,但我认为这比一次只写入一个值要好。当我们查看固件时,您将看到,在将数据写入转换数据寄存器之前,您必须通过检查DACC中断状态寄存器中的TXRDY标志来确保FIFO没有满。

ASF问题

SAM4S DACC的ASF接口似乎包括一些可能导致大量混乱的疏忽,因此让我们仔细看看DACC配置过程。

解雇DACC的前两个步骤并不呈现任何问题。首先,重置DACC硬件,然后选择半字模式或全文模式:

dacc_reset(DACC);//一次写一个16位值,而不是一个32位Word dacc_set_transfer_mode(dacc,halfword_mode)中的两个16位值;

在半字模式下,DACC硬件只查看写入到转换数据寄存器的值的低16位。在全字模式下,硬件将下16位解释为一个值,上16位解释为第二个值。在任何情况下,我们处理的是12位DAC,因此任何16位转换值的上4位将被忽略(除非您使用“标签模式”;你们可以在1124页读到更多SAM4S Datasheet.(PDF))。

现在我们需要配置dac计时参数,这就是事情变得有点混乱的地方。为此我们使用的函数是dacc_set_timing()。这个函数用于各种Atmel微控制器,这意味着这个函数必须能够为不同的dac模块配置定时,这反过来意味着ASF包含不同版本的dacc_set_timing()函数。ASF将用于SAM4S项目的版本如下:

uint32_t dacc_set_timing(dacc * p_dacc,uint32_t ul_refresh,uint32_t ul_max,uint32_t ul_startup){uint32_t mr = p_dacc-> dacc_mr&(〜(dacc_mr_refresh_msk | dacc_mr_startup_msk);MR | = DACC_MR_REFRESH(UL_REFRESH);if(ul_max){mr | = dacc_mr_maxs;}否则{MR&=〜dacc_mr_maxs;MR | =(dacc_mr_startup_msk&((ul_startup)<< dacc_mr_startup_pos));p_dacc-> dacc_mr = mr;返回dacc_rc_ok;}

不幸的是,这个功能有两个问题。首先,它包括UL_REFRESH参数。由于泄漏而导致的DAC产生的模拟电压随着时间的推移而逐渐减小;为了保持适当的输出电压,DAC必须“刷新”。这种刷新可以通过简单地在指定的“刷新时间内的转换数据寄存器中以简单地编写相同的值(或新值,如果需要)来实现。但是,Atmel的XMEGA设备中的DAC硬件(也可能其他人)包含自动刷新功能。用于设置刷新间隔的UL_REFRESH参数反映了此自动刷新功能。这里的麻烦是SAM4S DACC模块不是有自动刷新,因此这是不是应该与SAM4S项目一起使用的功能。

第二个问题与第一个问题有关。在尝试配置不存在的自动刷新硬件的过程中,上述版本的DACC_SET_TIMING()函数清除DACC模式寄存器的位8。为什么我们应该关心第8位?这就是为什么,从4.(PDF)SAM4S数据表:

我并不声称自己知道任何关于这个神秘的关键部分的本质或影响;我所知道的是,我不会忽视知名IC制造商发布的数据表中所包含的可怕、明确的警告。raybet开户因此,我拒绝使用任何胆敢清除dacc_set_timing()函数的dacc_set_timing()函数。

幸运的是,这个令人厌恶的情况的补救措施相当简单:首先,修改两个ASF文件,使SAM4E.也可以用于SAM4的DACC_SET_TIMING()版本S.项目。SAM4E DACC缺少自动刷新,据我所知,SAM4E DACC和SAM4S DACC之间没有显着差异。其次,删除导致第8位要清除的DACC_SET_TIMING()部分。我会使用Diffchecker帮助澄清修改。以下是第一个文件的更改,“dacc.c”(原始版本在左侧,我的修改版本位于右侧):

以下是第二个文件的更改,“dacc.h”:

在我们继续前进之前,让我们谈谈我们如何刷新DAC,因为我们没有自动刷新。1181页SAM4S数据表的(PDF)告诉我们“8位精度”的刷新间隔为24μs:

在我看来,对于12位DAC,8位精度相当较低,所以我宁愿使用较短的刷新间隔 - 可能10μs?我们在该项目中的目标是连续波形生成,因此我们可以通过维持大于或等于100 kHz的采样率来强制DAC更新之间的该最小间隔。

DAC时钟

当你在Atmel Studio中生成一个新项目时,默认时钟配置(在“conf_clock.h”中找到)给你一个主时钟(MCK)频率为120兆赫。外围时钟的频率等于MCK的频率,驱动DAC电路的时钟的频率(称为“DAC时钟”)是外围时钟的频率除以2。因此,默认配置留给我们fDAC_clock= 60 MHz。不幸的是,最大DAC时钟频率为50 MHz:

为了解决这个问题,我修改了" conf_clock.h "如下:

// ===== pll0(a)选项(fpll =(fclk * pll_mul)/ pll_div)//在此处使用mul和div有效值。#define config_pll0_source pll_src_mainck_xtal #define config_pll0_mul 16 //以前这是20 #define config_pll0_div 1

这导致fMCK= 96 MHz,因此FDAC_clock= 48 MHz。

启动时间

作为配置DACC的一部分,我们需要指定提供所需的启动时间所需的DAC时钟滴答数。我们在这里没有匆忙,所以我们将使用最大值:

启动\ \[钟\蜱虫= \压裂{40 \ \μs}{\压裂{1}{48 \ MHz}} = \ 1920 \]

因此,我们使用十进制30作为调用dacc_set_timing()的第三个参数。(此功能的第二个参数用于启用或禁用极速模式;你可以读到更多425.(PDF))

最后,我们可以使用DAC

以下是所有DACC配置代码:

//启用DACC的外部时钟pmc_enable_peripher_clk (ID_DACC);dacc_reset(DACC);//每次写入一个16位的值,而不是在一个32位的字中写入两个16位的值;dacc_set_timing(DACC, MAXSPEED_MODE_DISABLED, STARTUP_TIME_1920_TICKS);// dacc_set_channel_selection(DACC, DACC_CHANNEL0);/*选择定时器/计数器通道1的TIO输出作为触发器。注意,本例中的“通道1”仅指timer/counter模块0的通道1,而不是timer/counter模块1的通道1。此外,该数据表仅指定“TIO输出”作为触发器源,没有说明这是指TIOA还是TIOB或两者。通过一些实验,我确定只有TIOA会触发DAC,而不是TIOB。* / dacc_set_trigger(通道、TC_CHANNEL1_TIO);//启用dacc_enable_channel(DACC, DACC_CHANNEL0);

这里是我们用来生成三角形波以零开始的代码,增加到DAC的最大电压(对应于4095的转换值),减少到零,增加到最大值,等等。

n = 0;while(1){//检查TXRDY标志if ((dacc_get_interrupt_status(DACC) & TXRDY) == false) {continue;} //写入转换值dacc_write_conversion_data(DACC, n);if (n == 4095) {incree_or_递减=递减;} else {n++;}} else {if (n == 0) {incree_or_decrease = INCREASE;} else {n——;}}}

您可以使用标有“备用/备用信号”行中的终端10探测DAC波形。这些通孔左侧的电位器允许您调整DAC的参考电压;我将我的2.4 V.

结果与结论

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

dma_dac_sinewave_part2.zip.

这里是DAC波形的范围捕获:

为什么最小和最大值为0.42 V和2.0 V而不是0 V和2.4 V?答案在DAC电气特性中找到:

这个很容易被忽略的小细节告诉我们,DAC的输出范围是有限的。参考电压为2.4 V时,理论范围为0.4 V到2v,这与我们的测量结果一致。

下一个范围捕获确认了DAC输出电压的更新与触发信号同步(我将增量增加到350次,而不是1次,以使过渡更明显):

DAC硬件需要25个DAC时钟周期以更新输出。因此,触发信号上的上升沿与DAC电压的变化之间的间隔应为25 / fDAC_clock= 521 ns,这与我们在范围内所看到的一致。

现在DAC通过来自定时器/计数器模块的采样率信号进行操作并正确触发,我们已经为第3部分做好了准备,其中我们将生成正弦曲线的转换值并使用PDC将这些值馈送到DAC。

下一篇文章串联:使用SAM4S外围DMA控制器的数模转换

自己试试这个项目吧!得到bom。