Olin dijo algunas cosas buenas. Me gustaría añadir un par de cosas:
Hay muchos DAC de audio que cuestan menos de US $ 3 cada uno. Acabo de hacer una búsqueda en Digikey para CS43 (los DAC de Cirrus Logic comienzan con eso) y encontré 46 DAC estéreo. El más caro fue de US $ 7.80, pero el 90% de ellos fue menos de US $ 5. Incluso el más barato de estos tendrá un mejor rendimiento que una escalera R-2R hecha a mano.
Mientras estás en Digikey, ofrecen docenas de osciladores a 11.2896 MHz o 22.579 MHz (que son 256 o 512 veces a 44.1 KHz). Muchos de estos son menos de US $ 2.
Un "truco" para usar los DAC de audio normales es que necesita un reloj de muestra decente (también denominado LRCLK) y un reloj de bits de serie (SCLK). Normalmente, estos no pueden ser modificados por la CPU. Pero en su esquema R-2R no podría hacerlo de una interrupción de todos modos. Incluso si estuviera en la interrupción de prioridad más alta, todavía tendrías un poco de jitter del orden de 40+ ns. Con el audio, preferirías que el jitter sea 2 ns o menos.
Su idea de usar un ADC de precisión para calibrar cada código de salida R-2R podría funcionar, pero necesitaría una tabla de 2 ^ 16 bits o 2 ^ 24 bits (dependiendo del número de bits). Y necesitarías dos tablas, una para cada canal de audio. Esto es apenas manejable para un DAC de 16 bits, y casi imposible para un DAC de 24 bits.
Si realmente desea hacer un DAC, construir un DAC delta-sigma de primer orden en un FPGA o CPLD es súper fácil y suena mucho mejor que un R casero típico. -2R DAC. Pero aún así no sonaría tan bien como un Cirrus Logic súper barato de US $ 2, Burr-Brown o AKM DAC. Aun así, he creado este tipo de DAC y me complacería proporcionar el código fuente de VHDL.
Actualización: ¡Agregué más cosas!
Aquí está el código VHDL para un DAC Delta-Sigma de primer orden:
-----------------------------------------------------------------------------
-- First Order Delta Sigma DAC
--
-- din is a signed integer where -full_scale represents a DAC output of 0 volts
-- and +full_scale is a DAC output of VCC.
-----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity dac_ds is
generic (n_bits :integer);
port (reset :in std_logic;
clk :in std_logic;
din :in std_logic_vector (n_bits-1 downto 0); -- Signed integer
dout :out std_logic
);
end dac_ds;
architecture arch_dac_ds of dac_ds is
signal err :std_logic_vector (n_bits+1 downto 0) := (others=>'0'); -- Error accumulator is 2 bits larger
signal dout_int :std_logic := '0';
begin
process (reset, clk)
variable val :std_logic_vector (n_bits+1 downto 0);
variable fs_neg :std_logic_vector (n_bits+1 downto 0);
variable fs_pos :std_logic_vector (n_bits+1 downto 0);
begin
if reset='1' then
err <= (others=>'0');
dout_int <= '0';
elsif rising_edge(clk) then
val := (din(din'high) & din(din'high) & din) + err;
fs_neg := (others=>'0');
fs_neg(0) := '1';
fs_neg(fs_neg'high downto fs_neg'high-2) := "111";
fs_pos := (others=>'0');
fs_pos(fs_pos'high-2) := '1';
if val(val'high) = '0' then
dout_int <= '1';
err <= val + fs_neg; -- err <= value + (-full scale)
else
dout_int <= '0';
err <= val + fs_pos; -- err <= value + (+full scale)
end if;
end if;
end process;
dout <= dout_int;
end arch_dac_ds;
La salida se verá como un flujo de bits seudoaleatorio. Recomiendo ejecutarlo a la frecuencia de reloj más alta que pueda, ya que es una potencia de 2 múltiplos de la frecuencia de muestreo. 22.579 MHz sería el más lento en el que lo ejecutaría. 45.xxx o 90.xxx MHz sería aún mejor.
Normalmente, ejecutaría esta salida en un filtro RC simple. Haga que la R sea lo suficientemente grande como para que su salida FPGA / CPLD aún pueda girar de riel a riel. Hacer C lo suficientemente grande como para filtrar correctamente. He usado 3.3K y 0.1 uF y funciona bien. 0.01 uF podría ser mejor. La salida del filtro RC se almacenaría luego en un amplificador operacional. Cuanto más rápida es la frecuencia de reloj, más fácil es hacer este filtro y mayor es la precisión resultante.
Solo porque alguien lo mencionará: usted podría hacer lo mismo con una salida PWM simple, pero el filtro RC tendría que ser mucho más grande y su diseño es más crítico, con menos precisión. Irónicamente, en un FPGA este DAC Delta-Sigma es más pequeño que un circuito PWM similar.
Sí, puede convertirlo en una clase de amplificador de clase D, pero las tasas de conmutación de salida son muy altas. Esto significa que su "etapa de potencia" tendría que manejar estas velocidades y usted también tendrá más pérdidas de conmutación (menos eficiencia).
Este es un DAC delta-sigma muy simple. Hay muchas formas de mejorarlo si lo desea, pero como lo es, tendrá un mejor rendimiento que un R-2R DAC hecho en casa.