在学习F28335时,发现关于AIC23芯片的资料比较少,且有些资料和例程还存在错误,所以将自己学习AIC23芯片的经验和例程分享出来,如果有错误还请大佬能够指点,一起学习交流。
程序实现的功能比较简单,对着麦克风说话时耳机会听到自己的声音并且会保存录音,如果按下按键时循环播放录音,供初学者参考。
AIC23芯片
引脚
主要用到的引脚就是图中标出的,配置接口用来完成初始化,本文使用GPIO模拟SPI传输配置数据,在SPI模式下CS端负责锁存数据;在IIC模式下CS端为可编程地址位,MODE用来选择模式,MODE=0时为IIC,MODE=1时为SPI。音频数据接口从上到下为数据接收发送的时钟、数据接收、数据发送、接收帧同步、发送帧同步,本文配置AIC23为主模式,时钟以及同步信号均由AIC23产生。
寄存器
按照手册的寄存器顺序,前两个左右声道线入控制本程序用不到,所以不做说明。
LRS左右声道音量同步更新,LZC左声道过零检测,LHV音量控制。
我的设置为关闭同步更新,打开过零检测。
同上
STA是侧音的衰减,STE是侧音是否打开,DAC为是否使用DAC,BYP是旁路模式,INSEL选择ADC的输入。MICM是麦克风静音。MICB为麦克风增强。如果打开侧音可能会覆盖你DSP发送给AIC23的音频,所以我设置为关闭。
该寄存器设置为关闭侧音,选择DAC,禁用旁路模式,ADC输入为麦克风,打开麦克风增强。
DACM为DAC静音控制,如果使能,会停止DAC,输出就没有声音了。DEEMP为去加重控制寄存器。ADCHP为ADC高通滤波器。
该寄存器设置为禁用DAC静音,44.1kHz的去加重。禁用ADC高通滤波器。
电源控制寄存器,全部打开即可。
MS设置AIC23工作在主或从模式,LRSWAP为DAC左右声道交换,LRP设置数据在什么时间有效,IWL设置输入的长度。FOR设置数据格式。
该寄存器设置为:AIC23工作在主模式,禁用DAC左右交换,数据在帧同步信号到来后第一个BCLK上升沿就有效,设置输入数据长度为16位,数据格式为DSP格式,一帧包括两个数据字,一个数据字包括16位。数据长度我自己理解为ADC的转换精度了,不知道对不对。
采样率设置根据数据手册设置。
激活接口就可以开始传输数据了。
在程序一开始要对寄存器初始化。
程序
SPI
初始化SPI
void Init_SPI()
{
EALLOW;
SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK=1;
GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0;//SDA
GpioCtrlRegs.GPADIR.bit.GPIO12 = 1;
GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0;
GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO13 = 1;
GpioCtrlRegs.GPAPUD.bit.GPIO13 = 0;
GpioCtrlRegs.GPBMUX2.bit.GPIO61 = 0;//SCL
GpioCtrlRegs.GPBDIR.bit.GPIO61 = 1;
GpioCtrlRegs.GPBPUD.bit.GPIO61 = 0;
EDIS;
}
12引脚为SPI数据线;61引脚为SPI时钟线;13引脚为使能端。
GPIO模拟SPI发送数据
void WriteAIC23Reg(Uint16 addr,Uint16 dat)//配置AIC23寄存器
{
Uint16 i,Temp;
Temp = addr<<9;
dat = dat | Temp;//AIC23的前7个bit为寄存器地址,后9个bit为数据
AIC23_CS=0;
DELAY_US(200);
for(i=0;i<16;i++)
{
SPI_SCL_L;
DELAY_US(200);
Temp = dat<<i;
Temp = Temp & 0x8000;
if (Temp)
{
SPI_SDA_H;
}
else
{
SPI_SDA_L;
}
DELAY_US(100);
SPI_SCL_H; //SCLK=1;
DELAY_US(100);
}
AIC23_CS=1;//CS的上升沿将数据锁存到寄存器
DELAY_US(200);
}
初始化AIC23芯片
void InitAIC23()
{
WriteAIC23Reg(RESET,0);
WriteAIC23Reg(D_INTERFACE_ACT,0x01);
WriteAIC23Reg(L_LINE_VOLUME,0x0097);
WriteAIC23Reg(R_LINE_VOLUME,0x0097);
WriteAIC23Reg(L_HEADPHONE_VOLUME,0x00F0);//设置耳机输出音量
WriteAIC23Reg(R_HEADPHONE_VOLUME,0x00F0);
WriteAIC23Reg(A_AUDIO_PATH,0x0015);//关闭侧音
WriteAIC23Reg(D_AUDIO_PATH,0x04);
WriteAIC23Reg(POWER_CON,0);
WriteAIC23Reg(D_AUDIO_INTERFACE,0x043);//工作在主模式,DSP模式为一帧包括两个16位数据字
// WriteAIC23Reg(SAMPLE_RATE,0x023);//44.1kHz
WriteAIC23Reg(SAMPLE_RATE,0x00d);//8kHz
}
采样率如果太高的话,数据量变多,录音的时间就会变短,所以设置了8kHz。
初始化Mcbsp
void InitMcbspa(void)
{
McbspaRegs.SPCR1.all=0x0000;
McbspaRegs.SPCR2.all=0x0000;
McbspaRegs.PCR.all=0x01;
McbspaRegs.XCR1.all =0x00A0;//发送单帧16位串行字。
McbspaRegs.XCR2.all =0x00;
McbspaRegs.RCR1.all=0x0040;//接收单帧1个32位串行字高位为左声道
McbspaRegs.RCR2.all=0x00;//1bit的数据延时
McbspaRegs.MFFINT.bit.RINT=1;
McbspaRegs.SPCR1.bit.RRST = 1;//接收器使能
McbspaRegs.SPCR2.bit.XRST = 1;//发送器使能
}
因为设置的数据为16位。所以设置接收16位。在发送时要注意开始区分左右声道,所以设置为单帧32位。左右声道各占16位。
中断函数
interrupt void ISRMcbspR(void)
{
int RData;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP6;
RData=McbspaRegs.DRR1.all;
Audio[l]=RData;
l++;
McbspaRegs.DXR2.all=RData;
McbspaRegs.DXR1.all=RData;
}
设置l用来每次进入中断时保存音频数据,并把数据发送,此时可以在耳机听到自己的声音。
主函数
#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"
#include "AIC23.h"
#include "Key.h"
int l=0;
Uint16 Audio[8000];
void main(void)
{
int i;
EALLOW;
InitSysCtrl();
EDIS;
InitXintf16Gpio();
InitMcbspaGpio();
Init_SPI();
DINT;
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();//禁止所有PIE中断,清楚标志位
InitMcbspa();
InitAIC23();
Init_Key();
EALLOW;
PieVectTable.MRINTA = &ISRMcbspR;
EDIS;
PieCtrlRegs.PIECTRL.bit.ENPIE = 1;//打开PIE
PieCtrlRegs.PIEIER6.bit.INTx5=1;//打开6.5中断,McbspA接收中断
IER |= M_INT6;//使能CPU中断6 INT6
EINT;
while(1)
{
if(Key==0)
{
DINT;
l=0;
for(i=0;i<8000;i++)
{
McbspaRegs.DXR2.all=Audio[i];
McbspaRegs.DXR1.all=Audio[i];
DELAY_US(125);
}
EINT;
}
}
}
因为设置AIC23采样率为8kHz,采样间隔为125us。所以在发送录音数据时保持这个采样间隔发送。数组定义的越大录音的时间越久。可能会出现内存不够用的情况,需要自己去调整cmd的设置。循环中加入了一个按键,如果按键按下才会循环播放录音,按键比较简单,不做说明。