如题,使用STM32单片机开发板控制AIC3254EVM评估板,走I2C总线,只链接了SCL SDA和地线三根线:
首先确认了单片机那边的I2C接口是没有问题的,I2C时序是软件模拟的。AIC3254功能板的WCLK BCLK悬空,MCLK接底板母板。
然后使用PPS生成初始化代码头文件并加入到工程中:
现在的问题是,程序访问AIC3254的各个寄存器都没有问题的,都能正常读写,但是就是【无法听到声音,也就是AIC3254的配置没有完全正确】,这也是我这次发帖求助的原因,请各位看下是哪里配置错了,是硬件问题还是软件问题?
STM32 I2C驱动代码贴出来:
void I2C_Init()
{ I2C_GPIO_CLKEN;
GPIO_Initure.Pin=I2C_SCL_PIN|I2C_SDA_PIN;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(I2C_GPIO,&GPIO_Initure);
I2C_SDA_SET;
I2C_SCL_SET;}
void IIC_Start()
{
SDA_OUT();
I2C_SDA_SET; I2C_SCL_SET;
Delay_us(4);
I2C_SDA_CLR;
Delay_us(4);
I2C_SCL_CLR;
}
void IIC_Stop()
{
SDA_OUT();
I2C_SCL_CLR;
I2C_SDA_CLR;
Delay_us(4);
I2C_SCL_SET; I2C_SDA_SET;
Delay_us(4);}
unsigned char IIC_Wait_Ack()
{
unsigned char ucErrTime=0;
SDA_IN(); I2C_SDA_SET;
Delay_us(1); I2C_SCL_SET;
Delay_us(1); while(I2C_SDA_READ)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
I2C_SCL_CLR; return 0;}
void IIC_Ack()
{
I2C_SCL_CLR;
SDA_OUT();
I2C_SDA_CLR;
Delay_us(2);
I2C_SCL_SET;
Delay_us(2);
I2C_SCL_CLR;
}
void IIC_NAck()
{
I2C_SCL_CLR;
SDA_OUT();
I2C_SDA_SET;
Delay_us(2);
I2C_SCL_SET;
Delay_us(2);
I2C_SCL_CLR;
}//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答void IIC_Send_Byte(unsigned char txd)
{ unsigned char t; SDA_OUT(); I2C_SCL_CLR;
//拉低时钟开始数据传输
for(t=0;t<8;t++)
{ if((txd&0x80)==0x80)
I2C_SDA_SET;
else if((txd&0x80)==0)
I2C_SDA_CLR;
txd<<=1; Delay_us(2);
I2C_SCL_SET;
Delay_us(2); I2C_SCL_CLR; Delay_us(2);
}}//读1个字节,ack=1时,发送ACK,ack=0,发送nACKunsigned char IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();
for(i=0;i<8;i++ )
{
I2C_SCL_CLR; Delay_us(2);
I2C_SCL_SET;
receive<<=1;
if(I2C_SDA_READ)receive++; Delay_us(1); } if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK return receive;
}
unsigned char AIC3254_ReadOneRes(int addr)
{ unsigned char temp=0; IIC_Start(); IIC_Send_Byte(0x30); IIC_Wait_Ack(); IIC_Send_Byte(addr);
IIC_Wait_Ack(); IIC_Start(); IIC_Send_Byte(0x31); IIC_Wait_Ack(); temp=IIC_Read_Byte(0); IIC_Stop(); return temp;
}
void AIC3254_WriteOneRes(int addr,unsigned char data)
{ IIC_Start(); IIC_Send_Byte(0x30);
IIC_Wait_Ack(); IIC_Send_Byte(addr); IIC_Wait_Ack(); IIC_Send_Byte(data); IIC_Wait_Ack(); IIC_Stop();
//Delay_ms(1);}
void AIC3254_WriteMultiRes(int addr,unsigned char data[],int size)
{ int i=0;
IIC_Start(); IIC_Send_Byte(0x30);
IIC_Wait_Ack(); for(i=0;i<size;i++)
{
IIC_Send_Byte(data[i]); IIC_Wait_Ack();
} IIC_Stop();
Delay_ms(1);}
void minidsp_get_burst(const reg_value * program_ptr, int program_size, minidsp_parser_data * parse_data)
{
int index = parse_data->current_loc;
int burst_write_count = 0;
/* check if first location is page register, and populate page addr */
if (program_ptr[index].reg_off == 0){parse_data->page_num = program_ptr[index].reg_val;
parse_data->reg_num = program_ptr[index].reg_off;
parse_data->burst_array[burst_write_count++] = program_ptr[index].reg_val;
index++;
goto finish_out;
}
/* if it’s not page register, store the reg_off and val into array */
parse_data->reg_num = program_ptr[index].reg_off;
parse_data->burst_array[burst_write_count++] = program_ptr[index].reg_val;
index++;
/* check if the reg addr is continue or not */
for (; index < program_size; index++){
if (program_ptr[index].reg_off != (program_ptr[index – 1].reg_off + 1)){
break;
}
else{
parse_data->burst_array[burst_write_count++] = program_ptr[index].reg_val;
}
}
finish_out:
parse_data->burst_size = burst_write_count;
if (index == program_size){
/* parsing completed */
parse_data->current_loc = -1;
}
else{
parse_data->current_loc = index;
}
}
void minidsp_burst_transfer(const reg_value *program_ptr, int program_size)
{
int i;
minidsp_parser_data parse_data;
/* point the current location to start of program array */
parse_data.current_loc = 0;
parse_data.page_num = 0;
parse_data.reg_num = 0;
do {
/* Prepare burst data */
minidsp_get_burst(program_ptr, program_size, &parse_data);
/* Send burst data */
AIC3254_WriteMultiRes(parse_data.reg_num,parse_data.burst_array,parse_data.burst_size);
} while (parse_data.current_loc != -1);
}
void process_flow_download(reg_value *REG_Section, int program_size)
{
static int reg_index = 0;
unsigned char result,page;
for ( ; reg_index < program_size; reg_index++)
{
if (REG_Section[reg_index].reg_off == 254)
{
Delay_ms(REG_Section[reg_index].reg_val);
continue;
}
else if (REG_Section[reg_index].reg_off == 255)
{
if (REG_Section[reg_index].reg_val == 0)
{
// Program_miniDSP_A;
printf("对miniDSP_A编程\n");
minidsp_burst_transfer(miniDSP_A_reg_values, miniDSP_A_reg_values_COEFF_SIZE + miniDSP_A_reg_values_INST_SIZE);
}
if (REG_Section[reg_index].reg_val == 1)
{
// Program_miniDSP_D;
printf("对miniDSP_D编程\n");
minidsp_burst_transfer (miniDSP_D_reg_values, miniDSP_D_reg_values_COEFF_SIZE + miniDSP_D_reg_values_INST_SIZE);
}
continue;
}
else if(REG_Section[reg_index].reg_off==0)
page=REG_Section[reg_index].reg_val;
AIC3254_WriteOneRes(REG_Section[reg_index].reg_off,REG_Section[reg_index].reg_val);
result=AIC3254_ReadOneRes(REG_Section[reg_index].reg_off);
if(result!=REG_Section[reg_index].reg_val)
printf("写入不正确 %d页 %d 0x%x 0x%x\n",page,REG_Section[reg_index].reg_off,REG_Section[reg_index].reg_off,result);
}
}
main函数:
I2C_Init();
process_flow_download(REG_Section_program,sizeof(REG_Section_program)/sizeof(REG_Section_program[0]));
printf("全部写入完成\n");
AIC3254_WriteOneRes(0,0);
//AIC3254_WriteOneRes(1,0×04); AIC3254_WriteOneRes(81,0xc0);
AIC3254_WriteOneRes(63,0xd4);
//printf("0x%x\n",AIC3254_ReadOneRes(1)); printf("第0页第81个寄存器 ADC通道启动寄存器值:0x%x\n",AIC3254_ReadOneRes(81));
printf("第0页第63个寄存器 DAC通道启动寄存器值:0x%x\n",AIC3254_ReadOneRes(63));
AIC3254_WriteOneRes(0,8);
AIC3254_WriteOneRes(1,0×04); printf("第8页第1个寄存器 ADC滤波寄存器值:0x%x\n",AIC3254_ReadOneRes(1));
AIC3254_WriteOneRes(0,44);
AIC3254_WriteOneRes(1,0×04); printf("第8页第1个寄存器 DAC滤波寄存器值:0x%x\n",AIC3254_ReadOneRes(1));
user5195566:
回复 user151383853:
昨天已经修复该问题,STM32单片机可以与EVM评估板正常通信且有声音,修改相应的DSP寄存器也有效果了,经查明,STM32单片机那边必须提供一路PWM方波脉冲给评估板的mclk引脚用,一路5V供电和一路3V供电给评估板用,并且最重要的是,两个板子必须共地。