求助,因为项目用stm32f030f4芯片控制wm8950芯片,然后怎么配置都配置不出来ADCDAT数据,在这请教下,有人知道怎么弄么?

2019-08-22 14:16发布

stm32跟wm8950通信是,采用两线控制方式,然后IIC是用模拟IIC的方式,然后配置了好多东西都不见ADCDAT有数据产生,请求大神指点下。。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
6条回答
LSP
1楼-- · 2019-08-22 17:35
////////////////////////////////////////////////////// /  代码  / //////////////////////////////////////////////////////////////////////////////////

#include "wm8950.h"
#include "delay.h"

#define DevAddr 0x34 //0011 0100

static void i2c_delay(void)
{
    u8 i=255; //这里可以优化速度
    while(i)
    {
        i--;
    }
}

//初始化IIC
static void IIC_Init(void)
{             
GPIO_InitTypeDef GPIO_InitF;

//开PF时钟
RCC->AHBENR |= (0X1<<22);

GPIO_InitF.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
  GPIO_InitF.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitF.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitF.GPIO_OType = GPIO_OType_OD;//开漏
  GPIO_Init(GPIOF, &GPIO_InitF);

GPIO_SetBits(GPIOF,GPIO_Pin_0);
GPIO_SetBits(GPIOF,GPIO_Pin_1);

printf("wm8950 IO 配置完成!! ");
printf("F0 F1 Set high!! ");
}

static void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitF;

GPIO_InitF.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitF.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitF.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitF.GPIO_OType = GPIO_OType_OD;//开漏
  GPIO_Init(GPIOF, &GPIO_InitF);
}

static void SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitF;

GPIO_InitF.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitF.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitF.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitF);
}



//产生IIC起始信号
static void IIC_Start(void)
{
SDA_OUT();     //sda线输出
SDA_1();                    
CLK_1();
Delay_us(4);
        SDA_0();//START:when CLK is high,DATA change form high to low
Delay_us(4);
CLK_0();//钳住I2C总线,准备发送或接收数据
}          

//产生IIC停止信号
static void IIC_Stop(void)
{
SDA_OUT();//sda线输出
SDA_0();
CLK_0();//STOP:when CLK is high DATA change form low to high
        Delay_us(4);
SDA_1();
CLK_1();//发送I2C总线结束信号
Delay_us(4);
}



//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
static u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
u8 ack;       

Delay_us(4);
SDA_IN();      //SDA设置为输入  
Delay_us(4);
CLK_1();
Delay_us(4);

ack = GPIOF->IDR & (0X1<<0);

while(GPIOF->IDR & (0X1<<0))
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();

printf("wm8950 无应答,通信失败!! ack = %d ", ack);
return 1;
}
}
ack = GPIOF->IDR & (0X1<<0);

CLK_0();//时钟输出0          
  printf("wm8950 接收到应答,成功!!  ack = %d ", ack);  
return 0;  
}



//产生ACK应答
static void IIC_Ack(void)
{
CLK_0();
SDA_OUT();
SDA_0();
Delay_us(4);
CLK_1();
Delay_us(4);
CLK_0();
}


//不产生ACK应答            
static void IIC_NAck(void)
{
CLK_0();
SDA_OUT();
SDA_1();
Delay_us(4);
CLK_1();
Delay_us(4);
CLK_0();
}       



//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答          
static void IIC_Send_Byte(u8 txd)
{                        
  u8 t, DATA;   

SDA_OUT();          

printf("Send_Data=%X ",txd);
printf("SDA线的状态如下: ",txd);
for (t=0;t<8;t++)
{
if(txd&0x80)
{
SDA_1();
if(GPIOF->IDR & (0X1<<0))
{
printf("1");
}

}
else
{
SDA_0();
if(!(GPIOF->IDR & (0X1<<0)))
{
printf("0");
}

}

txd<<=1;

CLK_1();
Delay_us(1);
CLK_0();       
Delay_us(2);   //对TEA5767这三个延时都是必须的
}
printf(" ");         
}             
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
static u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
   
for (i=0;i<8;i++ )
{
    CLK_0();
    Delay_us(4);
CLK_1();
    receive<<=1;
    if(GPIOA->IDR & (0X1<<3))receive++;   
Delay_us(1);
  }         
   
if (!ack)
     IIC_NAck();//发送nACK
  else
     IIC_Ack(); //发送ACK   

  return receive;
}



//------------------------ AT24C02 一次8位 ------------------------------------------

//初始化IIC接口
void WM8950_Init(void)
{
u8 i = 1;
u8 sda = 0;

IIC_Init();

WM8950_WriteOneByte(0x06, 0x0008);
WM8950_WriteOneByte(0x2C, 0x0003);
WM8950_WriteOneByte(0x2D, 0x0010);
  WM8950_WriteOneByte(0X2F, 0x0177);
  WM8950_WriteOneByte(0X02, 0x0015);
  WM8950_WriteOneByte(0X01, 0x00FF);
  WM8950_WriteOneByte(0X04, 0x0002);       
}

//WriteAddr  :写入数据的目的地址   
//DataToWrite:要写入的数据
void WM8950_WriteOneByte(u8 WriteAddr,u16 DataToWrite)
{       
u8 Write_bit8;
u8 t;

WriteAddr <<= 1;

Write_bit8 = WriteAddr;

Write_bit8 |= (u8)(((u16)DataToWrite&0x100)>>8); //芯片是七位寄存器地址和一个数据的B8位

  IIC_Start();

IIC_Send_Byte(DevAddr);            //发送写命令

IIC_Wait_Ack();

IIC_Send_Byte(Write_bit8);//发送地址          

IIC_Wait_Ack();         

t = (u8)(DataToWrite&0xff);

IIC_Send_Byte(t);     //发送字节        低八位数据

IIC_Wait_Ack();           

  IIC_Stop();        //产生一个停止条件

Delay_ms(5);                

}


//WriteAddr :开始写入的地址
//pBuffer   :数据数组首地址
//NumToWrite:要写入数据的个数
void WM8950_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
while(NumToWrite--)
{
WM8950_WriteOneByte(WriteAddr,*pBuffer);
WriteAddr++;
pBuffer++;
}
}
LSP
2楼-- · 2019-08-22 23:21
我这边贴下,我写的程序


//-------------------------------------------------------------------------------------
#define DevAddr 0x34 //0011 0100

//初始化IIC
static void IIC_Init(void)
{                                             
        GPIO_InitTypeDef GPIO_InitA;
       
        //开PA时钟
        RCC->AHBENR |= (0X1<<17);
       
        GPIO_InitA.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4;
  GPIO_InitA.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitA.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitA.GPIO_OType = GPIO_OType_PP;//推挽
  GPIO_InitA.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitA);
       
        GPIO_SetBits(GPIOA,GPIO_Pin_3);
        GPIO_SetBits(GPIOA,GPIO_Pin_4);
}

static void SDA_OUT(void)
{
        GPIO_InitTypeDef GPIO_InitA;
       
        GPIO_InitA.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitA.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitA.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitA.GPIO_OType = GPIO_OType_PP;//推挽
  GPIO_InitA.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitA);
}

static void SDA_IN(void)
{
        GPIO_InitTypeDef GPIO_InitA;
       
        GPIO_InitA.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitA.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitA.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitA);
}

//产生IIC起始信号
static void IIC_Start(void)
{
        SDA_OUT();     //sda线输出
        SDA_1();                    
        CLK_1();
        Delay_us(1);
        SDA_0();//START:when CLK is high,DATA change form high to low
        Delay_us(1);
        CLK_0();//钳住I2C总线,准备发送或接收数据
}          

//产生IIC停止信号
static void IIC_Stop(void)
{
        SDA_OUT();//sda线输出
        SDA_0();
        CLK_0();//STOP:when CLK is high DATA change form low to high
        Delay_us(1);
        SDA_1();
        CLK_1();//发送I2C总线结束信号
        Delay_us(1);                                                                  
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
static u8 IIC_Wait_Ack(void)
{
        u8 ucErrTime=0;
       
        SDA_IN();      //SDA设置为输入  
          
        CLK_1();Delay_us(1);
       
        while(GPIOA->IDR & (0X1<<3))
        {
                ucErrTime++;
                if(ucErrTime>250)
                {
                        IIC_Stop();
                        return 1;
                }
        }
        CLK_0();//时钟输出0           
        return 0;  
}
//产生ACK应答
static void IIC_Ack(void)
{
        CLK_0();
        SDA_OUT();
        SDA_0();
        Delay_us(1);
        CLK_1();
        Delay_us(1);
        CLK_0();
}
//不产生ACK应答                    
static void IIC_NAck(void)
{
        CLK_0();
        SDA_OUT();
        SDA_1();
        Delay_us(1);
        CLK_1();
        Delay_us(1);
        CLK_0();
}                                                                              
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答                          
static void IIC_Send_Byte(u8 txd)
{                        
  u8 t, DATA;   
       
        SDA_OUT();          
       
        CLK_0();//拉低时钟开始数据传输
       
        for (t=0;t<8;t++)
        {              
                DATA=(txd&0x80)>>7;
               
                if(DATA)
                {
                        SDA_1();
                }
                else
                {
                        SDA_0();
                }
                       
                txd<<=1;
          
                Delay_us(1);   //对TEA5767这三个延时都是必须的
                CLK_1();
                Delay_us(1);
                CLK_0();
                Delay_us(1);
  }         
}             
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
static u8 IIC_Read_Byte(unsigned char ack)
{
        unsigned char i,receive=0;
        SDA_IN();//SDA设置为输入
   
        for (i=0;i<8;i++ )
        {
    CLK_0();
    Delay_us(1);
                CLK_1();
    receive<<=1;
    if(GPIOA->IDR & (0X1<<3))receive++;   
                Delay_us(1);
  }                                         
   
        if (!ack)
     IIC_NAck();//发送nACK
  else
     IIC_Ack(); //发送ACK   
       
  return receive;
}



//------------------------ AT24C02 一次8位 ------------------------------------------

//初始化IIC接口
void WM8950_Init(void)
{
        IIC_Init();
       
        WM8950_WriteOneByte(0x00, 0x000);
        //AUXEN-6, MICEN-4,PLLEN-5,BIASEN-3,1111101
       
        Delay_ms(10);
       
        WM8950_WriteOneByte(0x01, 0x07D);
       
        Delay_ms(10);
       
        WM8950_WriteOneByte(0x02, 0x015);
       
        Delay_ms(10);
       
//        //设置R6 bit0=1 1=BCLK and FRAME clock are outputs
//  //             bit8=0 时钟源=MCLK
//        WM8950_WriteOneByte(0x06, 0x032);
       
        Delay_ms(10);
}

//WriteAddr  :写入数据的目的地址   
//DataToWrite:要写入的数据
void WM8950_WriteOneByte(u8 WriteAddr,u16 DataToWrite)
{               
        u8 Write_bit8;
               
        Write_bit8 <<= 1;
       
        Write_bit8 |= (DataToWrite&0x100)>>8; //芯片是七位寄存器地址和一个数据的B8位
               
  IIC_Start();
       
        IIC_Send_Byte(DevAddr);            //发送写命令
       
        IIC_Wait_Ack();
       
        IIC_Send_Byte(Write_bit8);//发送高地址          
       
        IIC_Wait_Ack();         
                                                                                                               
        IIC_Send_Byte(DataToWrite*0xff);     //发送字节        低八位数据
       
        IIC_Wait_Ack();                   
       
  IIC_Stop();                                                //产生一个停止条件
       
        Delay_ms(10);                                         //EEPROM的写入速度比较慢,加入延迟
}


//WriteAddr :开始写入的地址
//pBuffer   :数据数组首地址
//NumToWrite:要写入数据的个数
void WM8950_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
        while(NumToWrite--)
        {
                WM8950_WriteOneByte(WriteAddr,*pBuffer);
                WriteAddr++;
                pBuffer++;
        }
}
正点原子
3楼-- · 2019-08-23 05:15
帮顶
LSP
4楼-- · 2019-08-23 08:36
 精彩回答 2  元偷偷看……
LSP
5楼-- · 2019-08-23 10:57
虽然在这个论坛提的问题都没有得到大神的帮助,但是也很感谢网上那些热心的人儿,毕竟网上很多帖子也解决了自己不少的问题。最终是自己多次修改调试,搞出来了,在此也分享出来,希望能帮助到有需要的人,毕竟有些资源网上很少,自己也发出来给需要的人参考一下...

正点原子
6楼-- · 2019-08-23 15:32
LSP 发表于 2017-4-11 16:05
虽然在这个论坛提的问题都没有得到大神的帮助,但是也很感谢网上那些热心的人儿,毕竟网上很多帖子也解决了 ...

谢谢分享

一周热门 更多>