当前位置: 代码迷 >> 综合 >> 【ZYNQ-7000开发之十六】音频信号处理
  详细解决方案

【ZYNQ-7000开发之十六】音频信号处理

热度:13   发布时间:2024-01-06 17:57:47.0

本编文章将使用Zynq开发平台Miz702上的ADAU1761音频编解码芯片,进行采样模拟音频信号(2路),转成数字信号,然后再通过ADAU1761转成模拟信号输出(2路)。在此基础上通过左右声道相减,简单的实现人声消除。本文不介绍ADAU1761驱动的编写方法,直接采用 Ali Aljaani编写的IP。
ADAU1761参数的配置参考 ADA1761 Datasheet

本文所使用的开发板是Miz702(兼容zedboard)
PC 开发环境版本:Vivado 2015.2 Xilinx SDK 2015.2
3.5mm公对公的音频连接线一根
ADA1761驱动IP core下载

建立vivado工程

建好工程之后,把下载好的IP添加到IP Repository里面,如图所示
这里写图片描述
点击Create Blcok Design,完成后点击Add IP,把ZYNQ PS,添加进来,然后双击ZYNQ,进行如下配置
这里写图片描述
在Clock Configuration下,使能FLCK_CLK1,并且把时钟配置成10Mhz,如图所示
这里写图片描述
选中IIC_1和FCLK_CLK1,右击,点击Make external
这里写图片描述
结果如图所示
这里写图片描述
点击Add IP,添加zed_audio_ctrl IP,添加好之后点击Run Connection Automation
这里写图片描述
选中zed_audio_ctrl上其余的接口,右击,Make external
这里写图片描述
在空白处右击,选择Create port
然后按照如图所示配置
这里写图片描述
点击Add IP,添加Constant IP,配置如下
这里写图片描述
新建一个约束文件,把以下引脚约束添加进来

# Miz702 or zedboard Audio Codec Constraints
set_property PACKAGE_PIN AA6 [get_ports BCLK]
set_property IOSTANDARD LVCMOS33 [get_ports BCLK]
set_property PACKAGE_PIN Y6 [get_ports LRCLK]
set_property IOSTANDARD LVCMOS33 [get_ports LRCLK]
set_property PACKAGE_PIN AA7 [get_ports SDATA_I]
set_property IOSTANDARD LVCMOS33 [get_ports SDATA_I]
set_property PACKAGE_PIN Y8 [get_ports SDATA_O]
set_property IOSTANDARD LVCMOS33 [get_ports SDATA_O]
#MCLK
set_property PACKAGE_PIN AB2 [get_ports FCLK_CLK1]
set_property IOSTANDARD LVCMOS33 [get_ports FCLK_CLK1]
set_property PACKAGE_PIN AB4 [get_ports iic_1_scl_io]
set_property IOSTANDARD LVCMOS33 [get_ports iic_1_scl_io]
set_property PACKAGE_PIN AB5 [get_ports iic_1_sda_io]
set_property IOSTANDARD LVCMOS33 [get_ports iic_1_sda_io]
set_property PACKAGE_PIN AB1 [get_ports {ADDRESS[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ADDRESS[0]}]
set_property PACKAGE_PIN Y5 [get_ports {ADDRESS[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ADDRESS[1]}]

配置好之后和ADDRESS连接在一起,
然后就可以Create HDL wapper,点击Generate bitstream

建立软件工程

打开SDK之后,新建一个空的工程
新建头文件文件,
audio.h

#ifndef __AUDIO_H_
#define __AUDIO_H_#include "xparameters.h"/* Redefine audio controller base address from xparameters.h */
#define AUDIO_BASE XPAR_ZED_AUDIO_CTRL_0_BASEADDR/* Slave address for the ADAU audio controller 8 */
#define IIC_SLAVE_ADDR 0x70/* I2C Serial Clock frequency in Hertz */
#define IIC_SCLK_RATE 400000/* ADAU internal registers */
enum audio_regs {R0_CLOCK_CONTROL                                = 0x00,R1_PLL_CONTROL                                  = 0x02,R2_DIGITAL_MIC_JACK_DETECTION_CONTROL           = 0x08,R3_RECORD_POWER_MANAGEMENT                      = 0x09,R4_RECORD_MIXER_LEFT_CONTROL_0                  = 0x0A,R5_RECORD_MIXER_LEFT_CONTROL_1                  = 0x0B,R6_RECORD_MIXER_RIGHT_CONTROL_0                 = 0x0C,R7_RECORD_MIXER_RIGHT_CONTROL_1                 = 0x0D,R8_LEFT_DIFFERENTIAL_INPUT_VOLUME_CONTROL       = 0x0E,R9_RIGHT_DIFFERENTIAL_INPUT_VOLUME_CONTROL      = 0x0F,R10_RECORD_MICROPHONE_BIAS_CONTROL              = 0x10,R11_ALC_CONTROL_0                               = 0x11,R12_ALC_CONTROL_1                               = 0x12,R13_ALC_CONTROL_2                               = 0x13,R14_ALC_CONTROL_3                               = 0x14,R15_SERIAL_PORT_CONTROL_0                       = 0x15,R16_SERIAL_PORT_CONTROL_1                       = 0x16,R17_CONVERTER_CONTROL_0                         = 0x17,R18_CONVERTER_CONTROL_1                         = 0x18,R19_ADC_CONTROL                                 = 0x19,R20_LEFT_INPUT_DIGITAL_VOLUME                   = 0x1A,R21_RIGHT_INPUT_DIGITAL_VOLUME                  = 0x1B,R22_PLAYBACK_MIXER_LEFT_CONTROL_0               = 0x1C,R23_PLAYBACK_MIXER_LEFT_CONTROL_1               = 0x1D,R24_PLAYBACK_MIXER_RIGHT_CONTROL_0              = 0x1E,R25_PLAYBACK_MIXER_RIGHT_CONTROL_1              = 0x1F,R26_PLAYBACK_LR_MIXER_LEFT_LINE_OUTPUT_CONTROL  = 0x20,R27_PLAYBACK_LR_MIXER_RIGHT_LINE_OUTPUT_CONTROL = 0x21,R28_PLAYBACK_LR_MIXER_MONO_OUTPUT_CONTROL       = 0x22,R29_PLAYBACK_HEADPHONE_LEFT_VOLUME_CONTROL      = 0x23,R30_PLAYBACK_HEADPHONE_RIGHT_VOLUME_CONTROL     = 0x24,R31_PLAYBACK_LINE_OUTPUT_LEFT_VOLUME_CONTROL    = 0x25,R32_PLAYBACK_LINE_OUTPUT_RIGHT_VOLUME_CONTROL   = 0x26,R33_PLAYBACK_MONO_OUTPUT_CONTROL                = 0x27,R34_PLAYBACK_POP_CLICK_SUPPRESSION              = 0x28,R35_PLAYBACK_POWER_MANAGEMENT                   = 0x29,R36_DAC_CONTROL_0                               = 0x2A,R37_DAC_CONTROL_1                               = 0x2B,R38_DAC_CONTROL_2                               = 0x2C,R39_SERIAL_PORT_PAD_CONTROL                     = 0x2D,R40_CONTROL_PORT_PAD_CONTROL_0                  = 0x2F,R41_CONTROL_PORT_PAD_CONTROL_1                  = 0x30,R42_JACK_DETECT_PIN_CONTROL                     = 0x31,R67_DEJITTER_CONTROL                            = 0x36,R58_SERIAL_INPUT_ROUTE_CONTROL                  = 0xF2,R59_SERIAL_OUTPUT_ROUTE_CONTROL                 = 0xF3,R61_DSP_ENABLE                                  = 0xF5,R62_DSP_RUN                                     = 0xF6,R63_DSP_SLEW_MODES                              = 0xF7,R64_SERIAL_PORT_SAMPLING_RATE                   = 0xF8,R65_CLOCK_ENABLE_0                              = 0xF9,R66_CLOCK_ENABLE_1                              = 0xFA
};/* Audio controller registers */
enum i2s_regs {I2S_DATA_RX_L_REG   = 0x00 + AUDIO_BASE,I2S_DATA_RX_R_REG   = 0x04 + AUDIO_BASE,I2S_DATA_TX_L_REG   = 0x08 + AUDIO_BASE,I2S_DATA_TX_R_REG   = 0x0c + AUDIO_BASE,I2S_STATUS_REG      = 0x10 + AUDIO_BASE,
};#endif

新建C文件
audio.c


#include <stdio.h>
#include <xil_io.h>
#include <sleep.h>
#include "xiicps.h"
#include <xil_printf.h>
#include <xparameters.h>
#include "xuartps.h"
#include "stdlib.h"
#include "audio.h"// Parameter definitions
#define UART_BASEADDR XPAR_PS7_UART_1_BASEADDR
#define GPIO_BASE XPAR_GPIO_0_BASEADDR#define LED_CHANNEL 1
//----------------------------------------------------
// PROTOTYPE FUNCTIONS
//----------------------------------------------------
unsigned char IicConfig(unsigned int DeviceIdPS);
void AudioPllConfig();
void AudioWriteToReg(unsigned char u8RegAddr, unsigned char u8Data);
void AudioConfigureJacks();
void LineinLineoutConfig();
void read_superpose_play();;
//Global variables
XIicPs Iic;int main(void)
{xil_printf("------------------Enter Main Fun------------------------------\r\n");//Configure the IIC data structureIicConfig(XPAR_XIICPS_0_DEVICE_ID);//Configure the Audio Codec's PLLAudioPllConfig();//Configure the Line in and Line out ports.//Call LineInLineOutConfig() for a configuration that//同时开启Miz702的两个输入(绿色)和输出(红色)AudioConfigureJacks();xil_printf("-----------------ADAU1761 configured----------------------------\n\r");while(1){//循环采集 播放read_superpose_play();}return 0;
}
//
void read_superpose_play(void)
{u32  in_left, in_right, out_left, out_right;while (!XUartPs_IsReceiveData(UART_BASEADDR)){// 采集到的左右声道的数据in_left = Xil_In32(I2S_DATA_RX_L_REG);in_right = Xil_In32(I2S_DATA_RX_R_REG);out_left =    in_left ;out_right =   in_right ;//输出Xil_Out32(I2S_DATA_TX_L_REG, out_left);Xil_Out32(I2S_DATA_TX_R_REG, out_right);//消除人声// out_right = in_right - out_right ;//Xil_Out32(I2S_DATA_TX_L_REG, out_right );//Xil_Out32(I2S_DATA_TX_R_REG, out_right);}
}/* ---------------------------------------------------------------------------- ** IicConfig() ** ---------------------------------------------------------------------------- ** Initialises the IIC driver by looking up the configuration in the config* table and then initialising it. Also sets the IIC serial clock rate.* ---------------------------------------------------------------------------- */
unsigned char IicConfig(unsigned int DeviceIdPS)
{XIicPs_Config *Config;int Status;/* Initialise the IIC driver so that it's ready to use */// Look up the configuration in the config tableConfig = XIicPs_LookupConfig(DeviceIdPS);if(NULL == Config) {return XST_FAILURE;}// Initialise the IIC driver configurationStatus = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress);if(Status != XST_SUCCESS) {return XST_FAILURE;}//Set the IIC serial clock rate.XIicPs_SetSClk(&Iic, IIC_SCLK_RATE);return XST_SUCCESS;
}/* ---------------------------------------------------------------------------- ** AudioPllConfig() ** ---------------------------------------------------------------------------- ** Configures audio codes's internal PLL. With MCLK = 10 MHz it configures the* PLL for a VCO frequency = 49.152 MHz, and an audio sample rate of 48 KHz.* ---------------------------------------------------------------------------- */
void AudioPllConfig() {unsigned char u8TxData[8], u8RxData[6];int Status;Status = IicConfig(XPAR_XIICPS_0_DEVICE_ID);if(Status != XST_SUCCESS) {xil_printf("\nError initializing IIC");}// Disable Core ClockAudioWriteToReg(R0_CLOCK_CONTROL, 0x0E);// Write 6 bytes to R1 @ register address 0x4002u8TxData[0] = 0x40; // Register write address [15:8]u8TxData[1] = 0x02; // Register write address [7:0]u8TxData[2] = 0x02; // byte 6 - M[15:8]u8TxData[3] = 0x71; // byte 5 - M[7:0]u8TxData[4] = 0x02; // byte 4 - N[15:8]u8TxData[5] = 0x3C; // byte 3 - N[7:0]u8TxData[6] = 0x21; // byte 2 - 7 = reserved, bits 6:3 = R[3:0], 2:1 = X[1:0], 0 = PLL operation modeu8TxData[7] = 0x01; // byte 1 - 7:2 = reserved, 1 = PLL Lock, 0 = Core clock enable// Write bytes to PLL Control register R1 @ 0x4002XIicPs_MasterSendPolled(&Iic, u8TxData, 8, (IIC_SLAVE_ADDR >> 1));while(XIicPs_BusIsBusy(&Iic));// Register address set: 0x4002u8TxData[0] = 0x40;u8TxData[1] = 0x02;// Poll PLL Lock bitdo {XIicPs_MasterSendPolled(&Iic, u8TxData, 2, (IIC_SLAVE_ADDR >> 1));while(XIicPs_BusIsBusy(&Iic));XIicPs_MasterRecvPolled(&Iic, u8RxData, 6, (IIC_SLAVE_ADDR >> 1));while(XIicPs_BusIsBusy(&Iic));}while((u8RxData[5] & 0x02) == 0); // while not lockedAudioWriteToReg(R0_CLOCK_CONTROL, 0x0F);    // 1111// bit 3: CLKSRC = PLL Clock input// bits 2:1: INFREQ = 1024 x fs// bit 0: COREN = Core Clock enabled
}/* ---------------------------------------------------------------------------- ** AudioWriteToReg ** ---------------------------------------------------------------------------- ** Function to write one byte (8-bits) to one of the registers from the audio* controller.* ---------------------------------------------------------------------------- */
void AudioWriteToReg(unsigned char u8RegAddr, unsigned char u8Data) {unsigned char u8TxData[3];u8TxData[0] = 0x40;u8TxData[1] = u8RegAddr;u8TxData[2] = u8Data;XIicPs_MasterSendPolled(&Iic, u8TxData, 3, (IIC_SLAVE_ADDR >> 1));while(XIicPs_BusIsBusy(&Iic));
}/* ---------------------------------------------------------------------------- ** AudioConfigureJacks() ** ---------------------------------------------------------------------------- ** Configures audio codes's various mixers, ADC's, DAC's, and amplifiers to* accept stereo input from line in and push stereo output to line out.* ---------------------------------------------------------------------------- */
void AudioConfigureJacks()
{//AudioWriteToReg(R4_RECORD_MIXER_LEFT_CONTROL_0, 0x01); //enable mixer 1AudioWriteToReg(R4_RECORD_MIXER_LEFT_CONTROL_0, 0x0f);AudioWriteToReg(R5_RECORD_MIXER_LEFT_CONTROL_1, 0x07); //unmute Left channel of line in into mxr 1 and set gain to 6 dbAudioWriteToReg(R6_RECORD_MIXER_RIGHT_CONTROL_0, 0x0f); //enable mixer 2AudioWriteToReg(R8_LEFT_DIFFERENTIAL_INPUT_VOLUME_CONTROL,0x03);AudioWriteToReg(R9_RIGHT_DIFFERENTIAL_INPUT_VOLUME_CONTROL,0x03);AudioWriteToReg(R10_RECORD_MICROPHONE_BIAS_CONTROL, 0x01);AudioWriteToReg(R7_RECORD_MIXER_RIGHT_CONTROL_1, 0x07); //unmute Right channel of line in into mxr 2 and set gain to 6 dbAudioWriteToReg(R19_ADC_CONTROL, 0x13); //enable ADCsAudioWriteToReg(R22_PLAYBACK_MIXER_LEFT_CONTROL_0, 0x21); //unmute Left DAC into Mxr 3; enable mxr 3AudioWriteToReg(R24_PLAYBACK_MIXER_RIGHT_CONTROL_0, 0x41); //unmute Right DAC into Mxr4; enable mxr 4AudioWriteToReg(R26_PLAYBACK_LR_MIXER_LEFT_LINE_OUTPUT_CONTROL, 0x05); //unmute Mxr3 into Mxr5 and set gain to 6db; enable mxr 5AudioWriteToReg(R27_PLAYBACK_LR_MIXER_RIGHT_LINE_OUTPUT_CONTROL, 0x11); //unmute Mxr4 into Mxr6 and set gain to 6db; enable mxr 6AudioWriteToReg(R29_PLAYBACK_HEADPHONE_LEFT_VOLUME_CONTROL, 0xFF);//Mute Left channel of HP port (LHP)AudioWriteToReg(R30_PLAYBACK_HEADPHONE_RIGHT_VOLUME_CONTROL, 0xFF); //Mute Right channel of HP port (LHP)//AudioWriteToReg(R31_PLAYBACK_LINE_OUTPUT_LEFT_VOLUME_CONTROL, 0xE6); //set LOUT volume (0db); unmute left channel of Line out port; set Line out port to line out mode//AudioWriteToReg(R32_PLAYBACK_LINE_OUTPUT_RIGHT_VOLUME_CONTROL, 0xE6); // set ROUT volume (0db); unmute right channel of Line out port; set Line out port to line out modeAudioWriteToReg(R31_PLAYBACK_LINE_OUTPUT_LEFT_VOLUME_CONTROL, 0xFE); //set LOUT volume (0db); unmute left channel of Line out port; set Line out port to line out modeAudioWriteToReg(R32_PLAYBACK_LINE_OUTPUT_RIGHT_VOLUME_CONTROL, 0xFE); // set ROUT volume (0db); unmute right channel of Line out port; set Line out port to line out modeAudioWriteToReg(R35_PLAYBACK_POWER_MANAGEMENT, 0x03); //enable left and right channel playback (not sure exactly what this does...)AudioWriteToReg(R36_DAC_CONTROL_0, 0x03); //enable both DACsAudioWriteToReg(R58_SERIAL_INPUT_ROUTE_CONTROL, 0x01); //Connect I2S serial port output (SDATA_O) to DACsAudioWriteToReg(R59_SERIAL_OUTPUT_ROUTE_CONTROL, 0x01); //connect I2S serial port input (SDATA_I) to ADCsAudioWriteToReg(R65_CLOCK_ENABLE_0, 0x7F); //Enable clocksAudioWriteToReg(R66_CLOCK_ENABLE_1, 0x03); //Enable rest of clocks
}/* ---------------------------------------------------------------------------- ** LineinLineoutConfig() ** ---------------------------------------------------------------------------- ** Configures Line-In input, ADC's, DAC's, Line-Out and HP-Out.* ---------------------------------------------------------------------------- */
void LineinLineoutConfig() {AudioWriteToReg(R17_CONVERTER_CONTROL_0, 0x05);//48 KHzAudioWriteToReg(R64_SERIAL_PORT_SAMPLING_RATE, 0x05);//48 KHzAudioWriteToReg(R19_ADC_CONTROL, 0x13);AudioWriteToReg(R36_DAC_CONTROL_0, 0x03);AudioWriteToReg(R35_PLAYBACK_POWER_MANAGEMENT, 0x03);AudioWriteToReg(R58_SERIAL_INPUT_ROUTE_CONTROL, 0x01);AudioWriteToReg(R59_SERIAL_OUTPUT_ROUTE_CONTROL, 0x01);AudioWriteToReg(R65_CLOCK_ENABLE_0, 0x7F);AudioWriteToReg(R66_CLOCK_ENABLE_1, 0x03);AudioWriteToReg(R4_RECORD_MIXER_LEFT_CONTROL_0, 0x01);AudioWriteToReg(R5_RECORD_MIXER_LEFT_CONTROL_1, 0x05);//0 dB gainAudioWriteToReg(R6_RECORD_MIXER_RIGHT_CONTROL_0, 0x01);AudioWriteToReg(R7_RECORD_MIXER_RIGHT_CONTROL_1, 0x05);//0 dB gainAudioWriteToReg(R22_PLAYBACK_MIXER_LEFT_CONTROL_0, 0x21);AudioWriteToReg(R24_PLAYBACK_MIXER_RIGHT_CONTROL_0, 0x41);AudioWriteToReg(R26_PLAYBACK_LR_MIXER_LEFT_LINE_OUTPUT_CONTROL, 0x03);//0 dBAudioWriteToReg(R27_PLAYBACK_LR_MIXER_RIGHT_LINE_OUTPUT_CONTROL, 0x09);//0 dBAudioWriteToReg(R29_PLAYBACK_HEADPHONE_LEFT_VOLUME_CONTROL, 0xE7);//0 dBAudioWriteToReg(R30_PLAYBACK_HEADPHONE_RIGHT_VOLUME_CONTROL, 0xE7);//0 dBAudioWriteToReg(R31_PLAYBACK_LINE_OUTPUT_LEFT_VOLUME_CONTROL, 0xE6);//0 dBAudioWriteToReg(R32_PLAYBACK_LINE_OUTPUT_RIGHT_VOLUME_CONTROL, 0xE6);//0 dB
}

下载完成后测试效果:采集的音频信号,再次输出
红色的线是音频输入,白色的是耳机输出
这里写图片描述

  相关解决方案