TI中文支持网
TI专业的中文技术问题搜集分享网站

TLV320AIC26: 使用这个芯片,通过spi对它进行配置。在linux应用层对它写寄存器,报错。

Part Number:TLV320AIC26

#include "tlv.h"




int fd;// SPI设备文件描述符
int mode = SPI_MODE_0;  // SPI模式
int bits = 16;// 每字比特数
int speed = 10000000;// 最大SPI总线速度(Hz)
int delay;// 延迟时间(微秒)
 
/*
 * 初始化SPI通信.
 * 返回0表示成功,-1表示失败.
 */
int spi_init(void){int ret;// 打开SPI设备文件fd = open("/dev/spidev7.0", O_RDWR);if(fd < 0){printf("打开 /dev/spidev7.0 错误\n");return -1;}/** 设置SPI模式*/ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);if (ret == -1)printf("无法设置SPI模式\n");ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);if (ret == -1)printf("无法获取SPI模式\n");/** 设置每字比特数*/ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);if (ret == -1)printf("无法设置每字比特数\n");ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);if (ret == -1)printf("无法获取每字比特数\n");/** 设置最大传输速度*/ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);if (ret == -1)printf("无法设置最大传输速度\n");ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);if (ret == -1)printf("无法获取最大传输速度\n");printf("SPI模式: 0x%x\n", mode);printf("每字比特数: %d\n", bits);printf("最大速度: %d Hz (%d KHz)\n", speed, speed / 1000);return 0;
}
 
/*
 * 执行SPI数据传输.
 * 参数:
 *fd - SPI设备文件描述符
 *tx - 发送缓冲区
 *rx - 接收缓冲区
 *len - 数据长度
 * 返回0表示成功,-1表示失败.
 */
int transfer(int fd, u_int16_t *tx, u_int16_t *rx, int len)
{int ret;struct spi_ioc_transfer tr = {.tx_buf = (unsigned long)tx,.rx_buf = (unsigned long)rx,.len = len,.delay_usecs = delay,.speed_hz = speed,.bits_per_word = bits,};ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);if (ret < 1){printf("无法发送SPI消息\n");return -1;}return 0;
}





u_int16_t tvWriteRegister(u_int16_t reg, u_int16_t value)
{
	u_int16_t txdata[2];
	txdata[0]=reg;
	txdata[1]=value;transfer(fd, txdata, NULL, sizeof(txdata));

	return  0;			

}


u_int16_t tvReadRegister(u_int16_t reg)
{
	u_int16_t txdata[2]={0},rxdata[2]={0};
	txdata[0]=reg;
	txdata[1]=0;transfer(fd, txdata, rxdata, sizeof(rxdata));


	return(rxdata[1]);
}



void tvInit(void)
{u_int16_treg = 0;u_int16_tdata = 0;tvWriteRegister(AIC26_REG_RESET, 0xbb00);//Writing the code OxBBOO, Reset all registertvWriteRegister(AIC26_REG_AUX_ADC, 0x3e0);tvWriteRegister(AIC26_REG_REFERENCE, 0x17);data = tvReadRegister(AIC26_REG_REFERENCE);if(data != 0x17)printf("init audio codec failed\n\n");elseprintf("init codec success\n\n");tvWriteRegister(AIC26_REG_AUDIO_CTRL1, 0x013f); //DSP mode//tvWriteRegister(AIC26_REG_AUDIO_CTRL1,0x003f);//I2S modetvWriteRegister(AIC26_REG_ADC_GAIN, 0x3400);//tvWriteRegister(AIC26_REG_ADC_GAIN,0x2800);//tvWriteRegister(AIC26_REG_ADC_GAIN,0x0);//tvWriteRegister(AIC26_REG_DAC_GAIN,0x8080);tvWriteRegister(AIC26_REG_DAC_GAIN, 0x0202);tvWriteRegister(AIC26_REG_SIDETONE, 0x8080);tvWriteRegister(AIC26_REG_POWER_CTRL, 0xa700);tvWriteRegister(AIC26_REG_AUDIO_CTRL2, 0x0);#if 0tvWriteRegister(AIC26 REG AUDIO CTRL3,0x09fb);//Master bit11-1printf(“init codec Master mode\n”);#elsetvWriteRegister(AIC26_REG_AUDIO_CTRL3,0x01fb); //Slave bit11-0printf("init codec Slave mode\n");#endiftvWriteRegister(AIC26_REG_FILTER_COEFF_L_N0, 0x7fff);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_N0, 0x7fff);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_N1, 0x81a6);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_N1, 0x81a6);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_N2, 0x7cb5);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_N2, 0x7cb5);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_N3, 0x7fff);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_N3, 0x7fff);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_N4, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_N4, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_N5, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_N5, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_D1, 0x7fe2);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_D1, 0x7fe2);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_D2, 0x803c);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_D2, 0x803c);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_D4, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_D4, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_D5, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_D5, 0x0);tvWriteRegister(AIC26_REG_AUDIO_CTRL4, 0x1000);tvWriteRegister(AIC26_REG_AUDIO_CTRL5, 0xedb0);tvWriteRegister(AIC26_REG_PLL_PROG1, 0x8120);tvWriteRegister(AIC26_REG_PLL_PROG2, 0x1e00);//tvWriteRegister(AIC26_REG_POWER_CTRL_0x3191);tvWriteRegister(AIC26_REG_POWER_CTRL, 0x3091);reg = tvReadRegister(AIC26_REG_ADC_GAIN);reg = reg & (~(0x1f << 15));tvWriteRegister(AIC26_REG_ADC_GAIN, reg);


}
int main(int argc, char *argv[])
{spi_init();tvInit();return 0;
}

       执行这个代码报错了,能不能帮忙看一下是我transfer,tvReadRegister,tvWriteRegister这些函数哪里错误了,导致初始化音频驱动报错了。

Alice:

您好,

      这个FAQ中有驱动代码,请参考。

      [FAQ] Linux Drivers: Device drivers for AIC31xx/DAC31xx/AIC325x/AIC320x/AIC326x/AIC321x – Audio forum – Audio – TI E2E support forums

,

jorks:

我用的是linux5.10代码,需要配置dts文件。使用了spi接口,请问这样配置可以吗   &spi7 { status = "okay"; mcpdevy:mcpdevy@0 { compatible = "tlv320aic26-codec"; reg = <0>; spi-max-frequency = <10000000>; status = "okay"; }; };

,

Alice:

您好,

      FAQ中有DTS的配置示例。

,

jorks:

faq中是使用i2c接口的芯片,aic26是使用spi接口的,可以按照那样配置吗?

,

jorks:

另外能不能找技术人员帮忙看看我贴的代码里spi通讯问题。是不是哪里不对?因为我们使用aic26芯片是直接连接的卫星通讯模块,不是连的soc。直接配置寄存器使用更好。如果使用linux驱动也是不知道怎么设置了。

,

Alice:

您好,

      请确认卫星通讯模块的可作为SPI master,因为TLV320AIC26的只能是SPI slave,TLV320AIC26寄存器配置请参考datasheet P36的register map。        SPI 与I2C只是通讯接口的区别,接口的驱动取决于您使用的平台,很遗憾,我们无法提供更多支持。

,

jorks:

就是把TLV320AIC26当作SPI slave配置的,参考datasheet配置的寄存器,只是读取的数据报错,不确定哪里问题,就想找你们支持定位一下。

,

Alice:

您好,

       

         不是读失败,是没有写入成功。

          请通过读取寄存器的“RESET VALUE”来验证SPI读时序。

          然后再通过写入再回读的方法验证SPI写时序。

          请参考数据手册Figure 29确认数据帧格式及R/W位,寄存器寻址采用page+addr形式(Table 6. Memory Map)。

,

jorks:

我试了把读到的值打印出来,全是0xffff。这个说明读取了,只是值不对?   数据帧格式我确认对比过。  使用了几个宏  

#define AIC26_READ_COMMAND_WORD(addr)     ((1 << 15) | (addr << 5))
#define AIC26_WRITE_COMMAND_WORD(addr)    ((0 << 15) | (addr << 5))
#define AIC26_PAGE_ADDR(page, offset)     ((page << 6) | offset)   。

#ifndef APPLICATIONS_TLV320AIC26_H_
#define APPLICATIONS_TLV320AIC26_H_/* AIC26 Registers */#define AIC26_READ_COMMAND_WORD(addr)((1 << 15) | (addr << 5))
#define AIC26_WRITE_COMMAND_WORD(addr)((0 << 15) | (addr << 5))
#define AIC26_PAGE_ADDR(page, offset)((page << 6) | offset)
#define AIC26_NUM_REGSAIC26_PAGE_ADDR(3, 0)/* Page 0: Auxiliary data registers */#define AIC26_REG_BAT1AIC26_PAGE_ADDR(0, 0x05)
#define AIC26_REG_BAT2AIC26_PAGE_ADDR(0, 0x06)
#define AIC26_REG_AUXAIC26_PAGE_ADDR(0, 0x07)
#define AIC26_REG_TEMP1AIC26_PAGE_ADDR(0, 0x09)
#define AIC26_REG_TEMP2AIC26_PAGE_ADDR(0, 0x0A)/* Page 1: Auxiliary control registers */#define AIC26_REG_AUX_ADCAIC26_PAGE_ADDR(1, 0x00)
#define AIC26_REG_STATUSAIC26_PAGE_ADDR(1, 0x01)
#define AIC26_REG_REFERENCEAIC26_PAGE_ADDR(1, 0x03)
#define AIC26_REG_RESETAIC26_PAGE_ADDR(1, 0x04)/* Page 2: Audio control registers */#define AIC26_REG_AUDIO_CTRL1AIC26_PAGE_ADDR(2, 0x00)
#define AIC26_REG_ADC_GAINAIC26_PAGE_ADDR(2, 0x01)
#define AIC26_REG_DAC_GAINAIC26_PAGE_ADDR(2, 0x02)
#define AIC26_REG_SIDETONEAIC26_PAGE_ADDR(2, 0x03)
#define AIC26_REG_AUDIO_CTRL2AIC26_PAGE_ADDR(2, 0x04)
#define AIC26_REG_POWER_CTRLAIC26_PAGE_ADDR(2, 0x05)
#define AIC26_REG_AUDIO_CTRL3AIC26_PAGE_ADDR(2, 0x06)#define AIC26_REG_FILTER_COEFF_L_N0 AIC26_PAGE_ADDR(2, 0x07)
#define AIC26_REG_FILTER_COEFF_L_N1 AIC26_PAGE_ADDR(2, 0x08)
#define AIC26_REG_FILTER_COEFF_L_N2 AIC26_PAGE_ADDR(2, 0x09)
#define AIC26_REG_FILTER_COEFF_L_N3 AIC26_PAGE_ADDR(2, 0x0A)
#define AIC26_REG_FILTER_COEFF_L_N4 AIC26_PAGE_ADDR(2, 0x0B)
#define AIC26_REG_FILTER_COEFF_L_N5 AIC26_PAGE_ADDR(2, 0x0C)
#define AIC26_REG_FILTER_COEFF_L_D1 AIC26_PAGE_ADDR(2, 0x0D)
#define AIC26_REG_FILTER_COEFF_L_D2 AIC26_PAGE_ADDR(2, 0x0E)
#define AIC26_REG_FILTER_COEFF_L_D4 AIC26_PAGE_ADDR(2, 0x0F)
#define AIC26_REG_FILTER_COEFF_L_D5 AIC26_PAGE_ADDR(2, 0x10)
#define AIC26_REG_FILTER_COEFF_R_N0 AIC26_PAGE_ADDR(2, 0x11)#define AIC26_REG_FILTER_COEFF_R_N1 AIC26_PAGE_ADDR(2, 0x12)
#define AIC26_REG_FILTER_COEFF_R_N2 AIC26_PAGE_ADDR(2, 0x13)
#define AIC26_REG_FILTER_COEFF_R_N3 AIC26_PAGE_ADDR(2, 0x14)
#define AIC26_REG_FILTER_COEFF_R_N4 AIC26_PAGE_ADDR(2, 0x15)
#define AIC26_REG_FILTER_COEFF_R_N5 AIC26_PAGE_ADDR(2, 0x16)
#define AIC26_REG_FILTER_COEFF_R_D1 AIC26_PAGE_ADDR(2, 0x17)
#define AIC26_REG_FILTER_COEFF_R_D2 AIC26_PAGE_ADDR(2, 0x18)
#define AIC26_REG_FILTER_COEFF_R_D4 AIC26_PAGE_ADDR(2, 0x19)
#define AIC26_REG_FILTER_COEFF_R_D5 AIC26_PAGE_ADDR(2, 0x1A)#define AIC26_REG_PLL_PROG1AIC26_PAGE_ADDR(2, 0x1B)
#define AIC26_REG_PLL_PROG2AIC26_PAGE_ADDR(2, 0x1C)
#define AIC26_REG_AUDIO_CTRL4AIC26_PAGE_ADDR(2, 0x1D)
#define AIC26_REG_AUDIO_CTRL5AIC26_PAGE_ADDR(2, 0x1E)#endif /* APPLICATIONS_TLV320AIC26_H_ */#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>#include "tlv.h"int fd;// SPI设备文件描述符
int mode = SPI_MODE_0;// SPI模式
int bits = 16;// 每字比特数
int speed = 1000000;// 最大SPI总线速度(Hz)
int delay = 10;// 延迟时间(微秒)/** 初始化SPI通信.* 返回0表示成功,-1表示失败.*/
int spi_init(void){int ret;// 打开SPI设备文件fd = open("/dev/spidev7.0", O_RDWR);if(fd < 0){printf("打开 /dev/spidev7.0 错误\n");return -1;}/** 设置SPI模式*/ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);if (ret == -1)printf("无法设置SPI模式\n");ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);if (ret == -1)printf("无法获取SPI模式\n");/** 设置每字比特数*/ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);if (ret == -1)printf("无法设置每字比特数\n");ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);if (ret == -1)printf("无法获取每字比特数\n");/** 设置最大传输速度*/ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);if (ret == -1)printf("无法设置最大传输速度\n");ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);if (ret == -1)printf("无法获取最大传输速度\n");printf("SPI模式: 0x%x\n", mode);printf("每字比特数: %d\n", bits);printf("最大速度: %d Hz (%d KHz)\n", speed, speed / 1000);return 0;
}/** 执行SPI数据传输.* 参数:*fd - SPI设备文件描述符*tx - 发送缓冲区*rx - 接收缓冲区*len - 数据长度* 返回0表示成功,-1表示失败.*/
int transfer(int fd, u_int16_t *tx, u_int16_t *rx, int len)
{int ret;struct spi_ioc_transfer tr = {.tx_buf = (unsigned long)tx,.rx_buf = (unsigned long)rx,.len = len,.delay_usecs = delay,.speed_hz = speed,.bits_per_word = bits,};ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);if (ret < 1){printf("无法发送SPI消息\n");return -1;}return 0;
}u_int16_t tvWriteRegister(u_int16_t reg, u_int16_t value)
{u_int16_t txdata[2]={0};txdata[0]=AIC26_WRITE_COMMAND_WORD(reg);txdata[1]=value;txdata[0] = __bswap_16(txdata[0]);// 使用字节序转换函数txdata[1] = __bswap_16(txdata[1]);// 使用字节序转换函数transfer(fd, txdata, NULL, 4);return0;}u_int16_t tvReadRegister(u_int16_t reg)
{u_int16_t txdata[2]={0},rxdata[2]={0};printf("len%d\n",sizeof(rxdata));txdata[0]=AIC26_READ_COMMAND_WORD(reg);txdata[1]=0;txdata[0] = __bswap_16(txdata[0]);// 使用字节序转换函数transfer(fd, txdata, rxdata, sizeof(rxdata));printf("recvdat0x%x0x%x\n",rxdata[0],rxdata[1]);return(rxdata[1]);}void tvInit(void)
{u_int16_treg = 0;u_int16_tdata = 0;tvWriteRegister(AIC26_REG_RESET, 0xbb00);//Writing the code OxBBOO, Reset all registerusleep(5000);// 延时1ms等待复位完成tvWriteRegister(AIC26_REG_AUX_ADC, 0x3e0);tvWriteRegister(AIC26_REG_REFERENCE, 0x17);data = tvReadRegister(AIC26_REG_REFERENCE);if(data != 0x17)printf("init audio codec failed\n\n");elseprintf("init codec success\n\n");tvWriteRegister(AIC26_REG_AUDIO_CTRL1, 0x013f); //DSP mode//tvWriteRegister(AIC26_REG_AUDIO_CTRL1,0x003f);//I2S modetvWriteRegister(AIC26_REG_ADC_GAIN, 0x3400);//tvWriteRegister(AIC26_REG_ADC_GAIN,0x2800);//tvWriteRegister(AIC26_REG_ADC_GAIN,0x0);//tvWriteRegister(AIC26_REG_DAC_GAIN,0x8080);tvWriteRegister(AIC26_REG_DAC_GAIN, 0x0202);tvWriteRegister(AIC26_REG_SIDETONE, 0x8080);tvWriteRegister(AIC26_REG_POWER_CTRL, 0xa700);tvWriteRegister(AIC26_REG_AUDIO_CTRL2, 0x0);#if 0tvWriteRegister(AIC26 REG AUDIO CTRL3,0x09fb);//Master bit11-1printf(“init codec Master mode\n”);#elsetvWriteRegister(AIC26_REG_AUDIO_CTRL3,0x01fb); //Slave bit11-0printf("init codec Slave mode\n");#endiftvWriteRegister(AIC26_REG_FILTER_COEFF_L_N0, 0x7fff);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_N0, 0x7fff);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_N1, 0x81a6);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_N1, 0x81a6);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_N2, 0x7cb5);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_N2, 0x7cb5);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_N3, 0x7fff);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_N3, 0x7fff);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_N4, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_N4, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_N5, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_N5, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_D1, 0x7fe2);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_D1, 0x7fe2);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_D2, 0x803c);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_D2, 0x803c);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_D4, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_D4, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_L_D5, 0x0);tvWriteRegister(AIC26_REG_FILTER_COEFF_R_D5, 0x0);tvWriteRegister(AIC26_REG_AUDIO_CTRL4, 0x1000);tvWriteRegister(AIC26_REG_AUDIO_CTRL5, 0xedb0);tvWriteRegister(AIC26_REG_PLL_PROG1, 0x8120);tvWriteRegister(AIC26_REG_PLL_PROG2, 0x1e00);//tvWriteRegister(AIC26_REG_POWER_CTRL_0x3191);tvWriteRegister(AIC26_REG_POWER_CTRL, 0x3091);reg = tvReadRegister(AIC26_REG_ADC_GAIN);reg = reg & (~(0x1f << 15));tvWriteRegister(AIC26_REG_ADC_GAIN, reg);}int main(int argc, char *argv[])
{spi_init();tvInit();return 0;
}

,

jorks:

启动后读取 

AIC26_PAGE_ADDR(1, 0x00) 的值还是0xffff。是不是说明读取异常?

,

Alice:

您好,

jorks 说:

启动后读取 

AIC26_PAGE_ADDR(1, 0x00) 的值还是0xffff。是不是说明读取异常?

     是的, 建议用示波器参考Figure 31监测一下SPI信号。

     

,

jorks:

好的,稍后直接用示波器试试。

赞(0)
未经允许不得转载:TI中文支持网 » TLV320AIC26: 使用这个芯片,通过spi对它进行配置。在linux应用层对它写寄存器,报错。
分享到: 更多 (0)