树莓派SPI驱动TI DAC8568输出信号失真问题排查
树莓派SPI DAC(Boost 8568)输出信号失真问题排查
我在开展树莓派项目时,将原有的I2C接口HiFi DAC扩展板(PCM5122)替换为SPI接口的Boost 8568 DAC,目标是通过该DAC输出处理后的EEG数据模拟信号。但实际测试中发现两者输出信号质量差异显著:示波器检测显示,新SPI DAC输出的信号存在明显失真,而原I2C DAC的输出信号清晰正常。
信号对比图
- HiFi DAC输出信号:

- BOOST DAC 8568输出信号:

我已尝试降低信号采样率与SPI最大传输速率,但问题仍未得到解决。目前怀疑问题与Boost DAC的时钟组件相关,或是需要调整其他SPI参数以匹配原DAC的信号输出质量。
当前使用的Python代码
import spidev import numpy as np import time import RPi.GPIO as GPIO from scipy.io import wavfile # Define DAC channels and their corresponding addresses (assuming 8 channels) CHANNELS = { 'A': 0b0000, # Channel A address 'B': 0b0001, # Channel B address 'C': 0b0010, # Channel C address 'D': 0b0011, # Channel D address 'E': 0b0100, # Channel E address 'F': 0b0101, # Channel F address 'G': 0b0110, # Channel G address 'H': 0b0111, # Channel H address } # LDAC GPIO pin (adjust as needed) LDAC_PIN = 17 def initialize_ldac(): GPIO.setmode(GPIO.BCM) GPIO.setup(LDAC_PIN, GPIO.OUT) GPIO.output(LDAC_PIN, GPIO.HIGH) # Default to inactive state def trigger_ldac(): GPIO.output(LDAC_PIN, GPIO.LOW) time.sleep(0.001) GPIO.output(LDAC_PIN, GPIO.HIGH) CHANNEL_MAP = { "A": 0, "B": 1, "C": 2, "D": 3, "E": 4, "F": 5, "G": 6, "H": 7 } def build_command(channel, data): if isinstance(channel, str): channel = CHANNEL_MAP[channel.upper()] # Map channel to integer data = int(data) & 0xFFFF # Ensure data is a 16-bit value command = 0b0011 << 4 | (channel & 0x0F) # Generate command msb = (command << 4) | ((data >> 12) & 0x0F) # Upper nibble of data lsb = (data >> 4) & 0xFF # Middle 8 bits of data return [msb, lsb] def send_to_dac(spi, channel, value): command = build_command(channel, value) spi.xfer2(command) def update_channels_with_ldac(spi, channel_values): for channel, value in channel_values.items(): send_to_dac(spi, channel, value) trigger_ldac() def set_all_channels_to_zero(spi): channel_values = {channel: 0 for channel in CHANNELS} update_channels_with_ldac(spi, channel_values) def load_wav_file(file_path, desired_duration_seconds): # Load WAV file and normalize the signal sample_rate, signal = wavfile.read(file_path) if signal.ndim > 1: # Handle multi-channel audio (stereo) signal = signal[:, 0] # Use only the first channel max_amplitude = np.max(np.abs(signal)) normalized_signal = signal / max_amplitude # Determine how many samples fit within the desired duration num_samples = int(sample_rate * desired_duration_seconds) if len(normalized_signal) > num_samples: normalized_signal = normalized_signal[:num_samples] else: # Repeat the signal to fit the desired duration repeated_signal = np.tile(normalized_signal, int(np.ceil(num_samples / len(normalized_signal)))) normalized_signal = repeated_signal[:num_samples] # Clip and convert to 16-bit integers normalized_signal = np.clip(normalized_signal * 32767, -32768, 32767).astype(int) return normalized_signal, sample_rate def play_wav_file(spi, wav_file, target_channel, desired_duration_seconds): audio_data, sample_rate = load_wav_file(wav_file, desired_duration_seconds) num_samples = len(audio_data) sample_interval = 1 / sample_rate # Time interval between samples start_time = time.time() # Record the start time for i, value in enumerate(audio_data): # Send data to the DAC channel_values = {channel: 0 for channel in CHANNELS} channel_values[target_channel] = value update_channels_with_ldac(spi, channel_values) # Ensure proper timing elapsed_time = time.time() - start_time expected_time = (i + 1) * sample_interval if elapsed_time < expected_time: time.sleep(expected_time - elapsed_time) # Stop playback if exceeded the desired duration if elapsed_time >= desired_duration_seconds: break if __name__ == "__main__": spi = spidev.SpiDev() spi.open(0, 0) spi.max_speed_hz = 500000 spi.mode = 0b00 initialize_ldac() try: target_channel = input("Enter the target channel (A, B, C, D, E, F, G, H): ").strip().upper() if target_channel not in CHANNELS: raise ValueError("Invalid channel.") wav_file = 'wav file dest here' desired_duration_seconds = 7 play_wav_file(spi, wav_file, target_channel, desired_duration_seconds) finally: set_all_channels_to_zero(spi) spi.close() GPIO.cleanup()
内容的提问来源于stack exchange,提问作者user28464365
相关产品推荐
相关产品推荐

