在本篇文章中,我们将使用SAM4S Xplained Pro开发板来实际操作PWM数模转换DAC。
所需的硬件/软件 ● SAM4S Xplained Pro评估套件 ● I / O1 Xplained Pro扩展板 ● Atmel Studio
引脚、信号和调试器 在上一篇文章中,我们完成了对SAM4S PWM硬件的控制,通过Atmel软件框架(ASF)实现想要的功能。现在我们已经准备好让PWM硬件做一些有用的事情 - 即,只需RC低通滤波器就可以产生可编程模拟电压。我们需要做的第一件事就是通过我们的硬件设置来解决细节问题。我们将使用示波器测量来观察和分析PWM和DAC波形,因此该设置的一个重要部分是如何方便地探测相关信号。 如果您有I / O1扩展板,那么可以采用和我一样的硬件连接设置:
通过I / O1板上的RC滤波器实现低通滤波。事实上,这个RC滤波器的输入连接到SAM4S微控制器上的PWM引脚,此外RC滤波器还配备了一个漂亮的小丝网屏蔽波特图,。截止频率约为2340 Hz。 I / O1板不包含低通滤波器输入和输出信号的独立插头,因此我们需要找到另一种连接插头的方法。如果相关信号连接到奇数编号的引脚,20引脚EXT接头将很方便,但幸运的是,它们都是偶数编号,偶数编号的引脚无法访问:
幸运的是,其中一种信号可在其他地方获得。低通滤波器输出连接到引脚PB1,引脚PB1也可从SAM4S开发板上标有“SPARE / ALTERNATE SIGNALS”的通孔排中的端子9获得。这就是上面的照片显示其中一个探头存放在备用/备用编号9中的原因。没有方便的访问低通滤波器输入节点,所以我将一根跳线焊接到I / O1 EXT接头上的引脚8,如下:
我设置的唯一烦恼是跳线。如果您不喜欢焊接,可以选择以下方法:I / O1板上的低通滤波器输入连接到PWM通道1的负(即反向)输出在PROTO1板上(如上图所示),您可以轻松探测PWM通道0的负输出,因为它正好位于原型标题上:
因此,不是探测低通滤波器的实际输入,而是简单地探测PROTO1板上的PWM0-然后修改代码,使PWM通道0和1都被使能并始终产生相同的PWM信号。 最后,如果您没有I / O1板,您可以使用PROTO1板,面包板操作的直接焊接实现,以获得连接到其中一个PWM信号的低通滤波器。如果使用PROTO1板,请将其插入EXT2,这样就不必修改代码(EXT1和EXT2具有不同的PWM信号 - EXT1的通道0和EXT2的通道1)。这是I / O1板上使用的低通电路:
准确度和纹波
以下是PWM数模转换的基本代码框架:
- #include <asf.h>
- #define PWM1L_DAC IOPORT_CREATE_PIN(PIOA, 20)
- #define PWM_CLOCKSOURCE_FREQ 10000000
- #define PWM_FREQ 100000
- #define PWM_PERIOD_TICKS PWM_CLOCKSOURCE_FREQ/PWM_FREQ
- #define MEASURED_VHIGH 3
- float DAC_voltage = 1;
- pwm_channel_t PWM1_config;
- int main (void)
- {
- //clock configuration and initialization
- sysclk_init();
-
- /*Disable the watchdog timer and configure/initialize
- port pins connected to various components incorporated
- into the SAM4S Xplained development platform, e.g., the
- NAND flash, the OLED interface, the LEDs, the SW0 pushbutton.*/
- board_init();
-
- //connect peripheral B to pin A20
- pio_configure_pin(PWM1L_DAC, PIO_TYPE_PIO_PERIPH_B);
- //enable the peripheral clock for the PWM hardware
- pmc_enable_periph_clk(ID_PWM);
- //disable the PWM channel until it is properly configured
- pwm_channel_disable(PWM, PWM_CHANNEL_1);
- //PWM clock configuration
- pwm_clock_t PWMDAC_clock_config =
- {
- .ul_clka = PWM_CLOCKSOURCE_FREQ,
- .ul_clkb = 0,
- .ul_mck = sysclk_get_cpu_hz()
- };
-
- //apply the clock configuration
- pwm_init(PWM, &PWMDAC_clock_config);
-
- //select channel 1
- PWM1_config.channel = PWM_CHANNEL_1;
- //select clock A
- PWM1_config.ul_prescaler = PWM_CMR_CPRE_CLKA;
- /*The low-pass filter is connected to the inverted output
- for PWM channel 1, so to get an active-high signal we
- invert again by setting the polarity to low.*/
- PWM1_config.polarity = PWM_LOW;
- //left-aligned mode
- PWM1_config.alignment = PWM_ALIGN_LEFT;
-
- PWM1_config.ul_period = PWM_PERIOD_TICKS;
- PWM1_config.ul_duty = (DAC_voltage * MEASURED_VCC) / PWM_PERIOD_TICKS;
-
- //apply the channel configuration
- pwm_channel_init(PWM, &PWM1_config);
-
- //configuration is complete, so enable the channel
- pwm_channel_enable(PWM, PWM_CHANNEL_1);
-
- while(1);
- }
复制代码
您所见,我们使用预处理程序指令来定义 1. 驱动PWM硬件的时钟频率(即时钟A), 2. PWM波形的频率, 3. PWM波形的周期以时钟A为单位,并且 4. 测量的数字电源电压。
然后我们有一个浮点变量DAC_voltage,用于所需的输出电压。我们通过将PWM1_config.ul_period设置为PWM_PERIOD_TICKS来配置PWM频率。 PWM波形的频率(PWM_FREQ)不会影响标称DAC输出电压,但它会影响纹波量 - 如将PWM信号低通滤波器模拟电压中所讨论的,更高的PWM频率会导致更低的纹波,因为低通滤波器可以更有效地抑制信号的非直流分量。影响标称DAC电压的唯一两个因素是PWM波形的占空比和幅度(即,逻辑高电压减去逻辑低电压)。振幅超出了我们的控制范围,所以一切都归结为占空比。我们计算ul_duty(脉冲的持续时间,而不是占空比),如下所示:
- PWM1_config.ul_duty = (DAC_voltage * MEASURED_VCC) / PWM_PERIOD_TICKS;
复制代码
这个小计算简单地确保了ul_duty与ul_period的比率与所需DAC电压与PWM幅度的比率相同。在这里,我们假设测量的电源电压与幅度相同,我们很快就会发现这是我们的主要误差来源。 以下是上述设置的示波器捕获(PWM频率= 100 kHz,DAC_voltage = 1,PWM幅度= 3.28 V):
突出的测量结果显示在右侧。频率如预期,占空比与理论值一致:(1 V)/(3.28 V)= 0.305。主要差异是幅度。 PWM波形从大约100 mV切换到3 V,而不是0 V到3.28 V.现在这里有一个重要的细节:当逻辑低电压不是0 V时,DAC电压不再计算为(PWM振幅)×(占空比)。相反,我们需要使用 DAC电压=((VHIGH-VLOW)×占空比)+ VLOW 因此,在当前条件下的预期DAC电压是 DAC电压=((3 V-100 mV)×30.5%)+ 100 mV = 985 mV
这几乎与示波器计算的DAC电压的平均值完全相同。所以请记住,您不能简单地将示波器的“CH1 Vamp”乘以“CH1 + Dut”来确定预期的输出电压;您需要获取此乘法的结果并将其添加到PWM信号的实际逻辑低电压。在任何情况下,由于假定的逻辑高电压和低电压与实际逻辑高电压和低电压之间的差异,我们在平均DAC电压中存在~20 mV的误差。至于波纹,我们正在寻找大约150 mV的峰峰值。 (由于PWM波形中的逻辑转换同时发生噪声尖峰,因此测量范围存在问题。这是两个示波器通道之间串扰的结果;它们实际上并不存在于DAC信号中。)150 mV的纹波和20 mV的误差,到目前为止,我的总结论是我们在这里有一个DAC;它并不令人印象深刻,但如果这种性能足以满足您的应用需求,它比外部DAC更便宜,更简单。 以下是DAC_voltage = 0.5,1.5和2.5的范围捕获图像:
改进 我们可以做些什么来使这个PWM DAC稍微平滑一点?我们的两个主要问题是纹波和误差。纹波很容易降低:如上所述,我们只是增加PWM波形的频率。错误更成问题;最好的解决方案是缓冲PWM信号,使逻辑高电平和逻辑低电压更接近VCC和地。但是缓冲器芯片与高阶低通滤波器属于同一类别 - 如果超出基本的PWM-plus-RC滤波器实现,您可能只需使用外部DAC。因此,我们将简单地修改计算以代替PWM信号的实际高电压和低电压,而不是缓冲器。这看起来像是作弊,但实际上它是一种很好的设计技术:如果你正在使用一次性系统,那么按照一些基本的测量来修改代码是有意义的。如果您正在使用将大量生产的原型系统,那么根据您对原型的体验进行性能假设是有意义的。当然,从一个单元到另一个单元,高低电压可能会有很大差异;但话说回来,他们可能不会。无论如何,基于VCC和地的计算没有多大意义,因为通常微控制器的输出级不会一直驱动信号直到VCC或一直到地。 因此,让我们根据上面给出的逻辑高和逻辑低测量来修改代码,即VHIGH = 3 V和VLOW = 100 mV。 - #define MEASURED_VHIGH 3
- #define MEASURED_VLOW 0.1
- . . .
- PWM1_config.ul_duty = ((DAC_voltage - MEASURED_VLOW) / (MEASURED_VHIGH - MEASURED_VLOW)) * PWM_PERIOD_TICKS;
复制代码
以下是DAC_voltage = 1的结果。
因此,即使PWM占空比的变化也会导致高电压和低电压的足够变化,从而导致严重的误差。这提出了一种更复杂的方案的想法,其中计算根据占空比使用不同的高电压和低电压,但在我花费大量时间之前我会使用外部DAC。 至少我们知道我们可以改善波纹。让我们将PWM时钟源频率增加到120 MHz,将PWM频率增加到10 MHz。以下是DAC_voltage = 1的示波器捕获。PWM探头在第二次捕获时断开连接,这样我们就可以看到DAC波形在没有串扰的情况下看起来是什么样的。
较高的频率会将纹波降低到可忽略的水平,但是高电压和低电压已经发生了足够的变化以引入大量误差(回想一下,当我们使用DAC_voltage = 1的较低频率时,误差为零)。
总结 我们已经看到PWM DAC有各种的限制。除了上面讨论的误差和纹波以及较长的建立时间之外,可用的分辨率随着PWM频率的增加而降低 - 尽管PWM使用16位计数器,但更高的频率降低该计数器的可用宽度,因为周期和脉冲宽度由与同一计数器进行比较的寄存器确定。例如,如果PWM计数器复位为100,因为它必须从1 MHz时钟产生100μs周期,占空比寄存器不能超过100,导致分辨率小于7位(因为27 = 128)。最好的方法是:如果您能够容忍这些限制,PWM DAC是一种简单,低成本的解决方案,但大多数情况下您最好使用普通DAC,无论是外置还是集成到微控制器中。
|