CS43L21 DAC芯片驱动

CS43L12 DAC芯片驱动

音频数据通过MIC采集上来后有的的PDM数据有的直接是PCM数据,CS43L21做的就是将PCM数据播放出来。

CubeMX配置如下

音频数据传输I2S接口
在这里插入图片描述
开DMA双缓冲
在这里插入图片描述

芯片配置I2C通讯
在这里插入图片描述

驱动代码

/**
 *  @file CS43L21_Driver.c
 *
 *  @date 2021-03-10
 *
 *  @author aron566
 *
 *  @copyright Copyright (c) 2021 aron566 <aron566@163.com>.
 *
 *  @brief CS43L21 DAC芯片驱动接口
 *
 *  @details 1、CS43L21
 *
 *  @version V1.0
 */
#ifdef __cplusplus ///<use C compiler
extern "C" {
#endif
/** Includes -----------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
#include "CS43L21_Driver.h"
#include "main.h"
#include "SAI_Port.h"
/** Private typedef ----------------------------------------------------------*/
/** Public variables ---------------------------------------------------------*/
extern I2C_HandleTypeDef hi2c1;
/** Private macros -----------------------------------------------------------*/
#define ENABLE_CS43L21_DEBUG    0/**< 启动打印调试*/
/*CS43L21设备I2C地址,7Bit地址模式[即:100101<AD0><R/W>],最后一位由AD0引脚控制*/
#define AD0_PIN_LOW_LEVEL       1   /**< 初始化为下拉低电平状态*/  
#if AD0_PIN_LOW_LEVEL
  #define DEV_ADDR              0x94
#else
  #define DEV_ADDR              0x96
#endif
/*CS43L21设备I2C写操作地址*/
#define DEV_ADDR_WRITE          (DEV_ADDR|0x00)
/*CS43L21设备I2C读操作地址*/
#define DEV_ADDR_READ           (DEV_ADDR|0x01)

#define BLOCK_TIME_MS_MAX       1000U/**< 最大1000ms阻塞通讯*/

/*CS43L21寄存器地址*/
#define REG_CHIP_ID             0x01
#define REG_POWER_CTL           0x02
#define REG_SPEED_CTL           0x03
#define REG_INTERFACE_CFG       0x04
#define REG_DAC_OUT_CTL         0x08
#define REG_DAC_CTL             0x09/**< default:bit7:0 bit6:0 PCM数据直接DAC输出 01b则通过处理引擎*/

/*The DATA_SEL[1:0] bit in Reg09h must be set to 01b to enable function control in this register.*/
#define REG_PCMA_MIXER_CTL      0x10
#define REG_PCMB_MIXER_CTL      0x11

#define REG_BEEP_FQ_TIMG_CFG    0x12
#define REG_BEEP_OFF_TIME_VOL   0x13

#define REG_BEEP_CFG_TONE_CFG   0x14

#define REG_TONE_CTL            0x15
        
#define REG_A_OUT_VOL_CTL       0x16/**< 输出音量控制*/
#define REG_B_OUT_VOL_CTL       0x17

#define REG_PCM_MIXER_CH_SEL    0x18

#define REG_LIMIT_THRESHOLD_SZC 0x19

#define REG_LIMIT_RELEASE_RATE  0x1A
#define REG_LIMIT_ATTACK_RATE   0x1B

#define REG_STATUS_READ_ONLY    0x20

#define REG_CHARGE_PUMP_FQ      0x21
        
/*16BIT位*/        
#define REG_BIT0                (1U<<0)
#define REG_BIT1                (1U<<1)
#define REG_BIT2                (1U<<2)
#define REG_BIT3                (1U<<3)
#define REG_BIT4                (1U<<4)
#define REG_BIT5                (1U<<5)
#define REG_BIT6                (1U<<6)
#define REG_BIT7                (1U<<7)
#define REG_BIT8                (1U<<8)
#define REG_BIT9                (1U<<9)
#define REG_BIT10               (1U<<10)
#define REG_BIT11               (1U<<11)
#define REG_BIT12               (1U<<12)
#define REG_BIT13               (1U<<13)
#define REG_BIT14               (1U<<14)
#define REG_BIT15               (1U<<15)

#define CS43L21_DAC_HANDLE      &hi2c1
/** Private constants --------------------------------------------------------*/

/** Private variables --------------------------------------------------------*/
static uint8_t Send_Val_Buf[2];
static uint8_t Reg_Val_Buf[2];
/** Private function prototypes ----------------------------------------------*/
#if ENABLE_CS43L21_DEBUG
static void Display_Chip_ID(void);
#endif
static void Set_Device_AD0(void);
static void Power_On_Off(CS43L21_DRIVER_CH_Typedef_t Ch, CS43L21_DRIVER_POWER_Typedef_t On_Off);
/** Private user code --------------------------------------------------------*/

/** Private application code -------------------------------------------------*/
/*******************************************************************************
*
*       Static code
*
********************************************************************************
*/
/**
  ******************************************************************
  * @brief   I2C 异常状态恢复
  * @param   [in]None.
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-03-09
  ******************************************************************
  */
static inline void I2C_State_Reset(void)
{
  __HAL_I2C_DISABLE(CS43L21_DAC_HANDLE);
  HAL_Delay(1);
  __HAL_I2C_ENABLE(CS43L21_DAC_HANDLE);
}

/**
  ******************************************************************
  * @brief   CS43L21 I2C发送通讯接口
  * @param   [in]DevAddress 设备地址.
  * @param   [in]pData 发送数据地址.
  * @param   [in]Size 发送大小字节数.
  * @param   [in]Timeout 等待超时时间.
  * @return  -1 错误.
  * @author  aron566
  * @version V1.0
  * @date    2021-04-29
  ******************************************************************
  */
static int I2C_Master_Transmit_Port(uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
  if(HAL_OK != HAL_I2C_Master_Transmit(CS43L21_DAC_HANDLE, DevAddress, pData, Size, 0xFFFF))
  {
    while(1);
    return -1;
  }
  return 0;
}

/**
  ******************************************************************
  * @brief   CS43L21 I2C接收通讯接口
  * @param   [in]DevAddress 设备地址.
  * @param   [in]pData 接收数据地址.
  * @param   [in]Size 接收大小字节数.
  * @param   [in]Timeout 等待超时时间.
  * @return  -1 错误.
  * @author  aron566
  * @version V1.0
  * @date    2021-04-29
  ******************************************************************
  */
static int I2C_Master_Receive_Port(uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
  if(HAL_OK != HAL_I2C_Master_Receive(CS43L21_DAC_HANDLE, DevAddress, pData, Size, 0xFFFF))
  {
    I2C_State_Reset();
    while(1);
    return -1;
  }
  return 0;
}

#if ENABLE_CS43L21_DEBUG
/**
  ******************************************************************
  * @brief   CS43L21 chip id打印
  * @param   [in]None.
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-03-10
  ******************************************************************
  */
static inline void Display_Chip_ID(void)
{
  Send_Val_Buf[0] = REG_CHIP_ID;
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  printf("Chip ID REG:%02X, VAL:%02X.\r\n", Send_Val_Buf[0], Reg_Val_Buf[0]);/**< 0xD8 0xD9*/
}
#endif

/**
  ******************************************************************
  * @brief   CS43L21 上电初始化
  * @param   [in]None.
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-03-11
  ******************************************************************
  */
static inline void Device_PowerOn_Init(void)
{
  /*HOLD RESET PIN LOW LEVEL 10ms*/
  HAL_GPIO_WritePin(DAC_RST_GPIO_Port, DAC_RST_Pin, GPIO_PIN_RESET);
  HAL_Delay(10);
  HAL_GPIO_WritePin(DAC_RST_GPIO_Port, DAC_RST_Pin, GPIO_PIN_SET);
}


/**
  ******************************************************************
  * @brief   CS43L21 进入配置模式
  * @param   [in]None.
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-03-11
  ******************************************************************
  */
static inline void Entry_Config_Mode(void)
{
  /*读取电源设置状态*/
  Send_Val_Buf[0] = REG_POWER_CTL;
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  
  /*开启PDN Bit解锁设置*/
  Send_Val_Buf[1] = Reg_Val_Buf[0] | (REG_BIT0);
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
  
#if ENABLE_CS43L21_DEBUG
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  printf("Entry DAC Power REG:%02X, VAL:%02X.\r\n", Send_Val_Buf[0], Reg_Val_Buf[0]);
#endif
}

/**
  ******************************************************************
  * @brief   CS43L21 退出配置模式
  * @param   [in]None.
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-03-11
  ******************************************************************
  */
static inline void Exit_Config_Mode(void)
{
  /*读取电源设置状态*/
  Send_Val_Buf[0] = REG_POWER_CTL;
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  
  /*关闭PDN Bit上锁*/
  Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT0);
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);

#if ENABLE_CS43L21_DEBUG
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  printf("Exit DAC Power REG:%02X, VAL:%02X.\r\n", Send_Val_Buf[0], Reg_Val_Buf[0]);
#endif
}

/**
  ******************************************************************
  * @brief   CS43L21 断电
  * @param   [in]None.
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-03-11
  ******************************************************************
  */
static inline void Device_PowerDown_Init(void)
{
  /*MUTE DAC*/
  Power_On_Off(CS43L21_DRIVER_LEFT_CH, CS43L21_DRIVER_POWER_OFF);
  Power_On_Off(CS43L21_DRIVER_RIGHT_CH, CS43L21_DRIVER_POWER_OFF);

  /*禁用斜坡改为立即响应*/

  /*SET PDN BIT 1*/
  Entry_Config_Mode();

  /*WAIT 100us*/
  HAL_Delay(1);

  /*HOLD RESET PIN LOW LEVEL*/
  HAL_GPIO_WritePin(DAC_RST_GPIO_Port, DAC_RST_Pin, GPIO_PIN_RESET);
}

/**
  ******************************************************************
  * @brief   设置设备地址
  * @param   [in]None
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-03-10
  ******************************************************************
  */
static inline void Set_Device_AD0(void)
{
#if AD0_PIN_LOW_LEVEL
  HAL_GPIO_WritePin(DAC_ADDR_GPIO_Port, DAC_ADDR_Pin, GPIO_PIN_RESET);
#else
  HAL_GPIO_WritePin(DAC_ADDR_GPIO_Port, DAC_ADDR_Pin, GPIO_PIN_SET);
#endif
}

/**
  ******************************************************************
  * @brief   启停设备DACx电源
  * @param   [in]Ch 声道编号
  * @param   [in]On_Off 启动或关闭
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-03-10
  ******************************************************************
  */
static void Power_On_Off(CS43L21_DRIVER_CH_Typedef_t Ch, CS43L21_DRIVER_POWER_Typedef_t On_Off)
{
  /*读取电源设置状态*/
  Send_Val_Buf[0] = REG_POWER_CTL;
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  Send_Val_Buf[1] = Reg_Val_Buf[0];
  
  /*关闭*/
  if(On_Off == CS43L21_DRIVER_POWER_OFF)
  {
    /*左*/
    if(Ch == CS43L21_DRIVER_LEFT_CH)
    {
      Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT5);
    }
    /*右*/
    if(Ch == CS43L21_DRIVER_RIGHT_CH)
    {
      Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT6);
    }
  }
  /*打开*/
  else
  {
    /*左*/
    if(Ch == CS43L21_DRIVER_LEFT_CH)
    {
      Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT5);
    }
    /*右*/
    if(Ch == CS43L21_DRIVER_RIGHT_CH)
    {
      Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT6);
    }
  }
  
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
  
#if ENABLE_CS43L21_DEBUG
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  printf("DAC Power REG:%02X, VAL:%02X.\r\n", Send_Val_Buf[0], Reg_Val_Buf[0]);
#endif
}

/**
  ******************************************************************
  * @brief   设置主时钟速率
  * @param   [in]None.
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-03-10
  ******************************************************************
  */
static void DAC_CLKSpeed_Set(void)
{
  /*读取参数*/
  Send_Val_Buf[0] = REG_SPEED_CTL;
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  Send_Val_Buf[1] = Reg_Val_Buf[0];

  /*设置MCLK/2*/
  Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT0);
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
}

/**
  ******************************************************************
  * @brief   设置DAC输出
  * @param   [in]Gain_dB 增益值 0 - 7,0xFF时静音使能
  * @param   [in]Channel 通道号
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-04-29
  ******************************************************************
  */
static void DAC_Volume_Set(uint8_t Gain_dB, CS43L21_DRIVER_CH_Typedef_t Channel)
{
  /*读取参数*/
  Send_Val_Buf[0] = REG_DAC_OUT_CTL;
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  Send_Val_Buf[1] = Reg_Val_Buf[0];

  /*静音使能控制*/
  if(Gain_dB == 0xFF)
  {
    if(Channel == CS43L21_DRIVER_LR_CH)
    {
      Send_Val_Buf[1] = Send_Val_Buf[1] | ((REG_BIT0) | (REG_BIT1));
    }
    else if(Channel == CS43L21_DRIVER_LEFT_CH)
    {
      Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT0);
    }
    else if(Channel == CS43L21_DRIVER_RIGHT_CH)
    {
      Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT1);
    }
    I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
    return;
  }

  /*左右通道音量独立控制*/
  Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT4);

  /*左右通道静音关闭*/
  Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT0);
  Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT1);
  
  /*设置耳机模拟增益Bit7-5:110b 即 1倍 ,Datasheet:Page 42*/
  Gain_dB = ((Gain_dB << 5)&0xE0);
  Send_Val_Buf[1] |= Gain_dB;
  // Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT7);
  // Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT6);
  // Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT5);
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
}

/**
  ******************************************************************
  * @brief   设置DAC功能启用
  * @param   [in]None.
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-04-29
  ******************************************************************
  */
static void DAC_Config(void)
{
  /*读取参数*/
  Send_Val_Buf[0] = REG_DAC_CTL;
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  Send_Val_Buf[1] = Reg_Val_Buf[0];

  /*DAC数据通道:00透传 ,01经过调节*/
  Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT7);
  Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT6);

  /*冻结参数修改:0允许参数修改立即保存,1允许参数修改暂不保存*/
  Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT5);

  /*44.4Khz数字滤波器使能:失能*/
  Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT3);

  /*启用自动静音:启用*/
  Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT2);
  
  /*调节响应过程:默认10立即响应设置, 01输出过0时响应, 10平滑缓慢响应,11过零及平滑缓慢响应*/
  Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT1);
  Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT0);
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
}

/**
  ******************************************************************
  * @brief   设置混响器输出增益
  * @param   [in]Gain_dB 增益 -51.5 ~ +12dB
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-04-29
  ******************************************************************
  */
static void MIXPath_Volume_Set(float Gain_dB)
{
  if(Gain_dB >= 0 && Gain_dB <= 12.f)
  {
    Send_Val_Buf[1] = (uint8_t)(Gain_dB * 2.f);
  }
  else if(Gain_dB < 0 && Gain_dB >= -51.5f)
  {
    Send_Val_Buf[1] = (uint8_t)(128.f + Gain_dB * 2.f);
  }

  /*混频静音使能:使能*/
  Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT7);

  Send_Val_Buf[0] = REG_PCMA_MIXER_CTL;
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);

  Send_Val_Buf[0] = REG_PCMB_MIXER_CTL;
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
}

/**
  ******************************************************************
  * @brief   设置音效输出增益
  * @param   [in]Treble_FQ 高音频率 5、7、10、15kHz
  * @param   [in]Bass_FQ 低音频率 50、100、200、250Hz
  * @param   [in]Treble_dB 高音增益 -10.5 ~ +12dB
  * @param   [in]Bass_dB 低音增益 -10.5 ~ +12dB
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-04-29
  ******************************************************************
  */
static void Tone_EQ_Set(uint16_t Treble_FQ, uint16_t Bass_FQ, float Treble_dB, float Bass_dB)
{
  /*读取参数*/
  Send_Val_Buf[0] = REG_BEEP_CFG_TONE_CFG;
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  Send_Val_Buf[1] = Reg_Val_Buf[0];

  /*使能音效控制*/
  Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT0);

  /*设置高音频率*/
  switch(Treble_FQ)
  {
  case 5000:
    Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT4);
    Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT3);
    break;
  case 7000:
    Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT4);
    Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT3);
    break;
  case 10000:
    Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT4);
    Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT3);
    break;
  case 15000:
    Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT4);
    Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT3);
    break;
  default:
    break;
  }
  /*设置低音频率*/
  switch(Bass_FQ)
  {
  case 50:
    Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT2);
    Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT1);
    break;
  case 100:
    Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT2);
    Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT1);
    break;
  case 200:
    Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT2);
    Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT1);
    break;
  case 250:
    Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT2);
    Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT1);
    break;
  default:
    break;
  }
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);

  /*设置高音增益*/
  if(Treble_dB >= 0 && Treble_dB <= 12.f)
  {
    Send_Val_Buf[1] = (((uint8_t)(8.f - Treble_dB / 1.5f))&0x0F);
  }
  else if(Treble_dB < 0 && Treble_dB >= -10.5f)
  {
    Send_Val_Buf[1] = (((uint8_t)(8.f + Treble_dB / -1.5f))&0x0F);
  }
  Send_Val_Buf[1] <<= 4;

  /*设置低音增益*/
  if(Bass_dB >= 0 && Bass_dB <= 12.f)
  {
    Send_Val_Buf[1] |= (((uint8_t)(8.f - (Bass_dB / 1.5f)))&0x0F);
  }
  else if(Bass_dB < 0 && Bass_dB >= -10.5f)
  {
    Send_Val_Buf[1] |= (((uint8_t)(8.f + Bass_dB / -1.5f))&0x0F);
  }

  /*混频静音使能:使能*/
  Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT7);

  Send_Val_Buf[0] = REG_TONE_CTL;
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
}

/**
  ******************************************************************
  * @brief   设置模拟输出增益
  * @param   [in]db 增益 -102 ~ +12dB
  * @param   [in]Channel 通道号
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-04-29
  ******************************************************************
  */
static void AOutPath_Volume_Set(float Gain_dB, CS43L21_DRIVER_CH_Typedef_t Channel)
{
  if(Gain_dB >= 0 && Gain_dB <= 12.f)
  {
    Send_Val_Buf[1] = (uint8_t)(Gain_dB * 2.f);
  }
  else if(Gain_dB < 0 && Gain_dB >= -102.f)
  {
    Send_Val_Buf[1] = (uint8_t)(256.f + Gain_dB * 2.f);
  }

  if(Channel == CS43L21_DRIVER_LEFT_CH)
  {
    Send_Val_Buf[0] = REG_A_OUT_VOL_CTL;
    I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
  }
  else if(Channel == CS43L21_DRIVER_RIGHT_CH)
  {
    Send_Val_Buf[0] = REG_B_OUT_VOL_CTL;
    I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
  }
  else if(Channel == CS43L21_DRIVER_LR_CH)
  {
    Send_Val_Buf[0] = REG_A_OUT_VOL_CTL;
    I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
    Send_Val_Buf[0] = REG_B_OUT_VOL_CTL;
    I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
  }
}

/**
  ******************************************************************
  * @brief   设置设备参数
  * @param   [in]None
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-03-10
  ******************************************************************
  */
static inline void Set_Cfg(void)
{  
  /*读取参数*/
  Send_Val_Buf[0] = REG_INTERFACE_CFG;
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
#if ENABLE_CS43L21_DEBUG
  printf("Interface CFG REG:%02X, VAL:%02X.\r\n", Send_Val_Buf[0], Reg_Val_Buf[0]);
#endif
  
  /*设置为Slave*/
  Send_Val_Buf[1] = Reg_Val_Buf[0] & (~REG_BIT6);
  /*设置数据格式 001*/
  Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT5);
  Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT4);
  Send_Val_Buf[1] = Send_Val_Buf[1] | REG_BIT3;
#if ENABLE_CS43L21_DEBUG
  printf("Set Interface CFG REG:%02X, VAL:%02X.\r\n", Send_Val_Buf[0], Send_Val_Buf[1]);
#endif
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 2, BLOCK_TIME_MS_MAX);
  
#if ENABLE_CS43L21_DEBUG
  I2C_Master_Transmit_Port(DEV_ADDR_WRITE, Send_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  I2C_Master_Receive_Port(DEV_ADDR_READ, Reg_Val_Buf, 1, BLOCK_TIME_MS_MAX);
  printf("After Interface CFG REG:%02X, VAL:%02X.\r\n", Send_Val_Buf[0], Reg_Val_Buf[0]);
#endif
}

/** Public application code --------------------------------------------------*/
/*******************************************************************************
*
*       Public code
*
********************************************************************************
*/

/**
  ******************************************************************
  * @brief   设置左右耳音量
  * @param   [in]Vol 音量值 0-100 对应 -102 - +12dB
  * @param   [in]Channel 通道号
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-05-06
  ******************************************************************
  */
void CS43L21_Driver_Vol_Set(uint8_t Vol, CS43L21_DRIVER_CH_Typedef_t Channel)
{
  float Gain_dB = (float)Vol*114.f/100.f-102.f;
  AOutPath_Volume_Set(Gain_dB, Channel);
}

/**
  ******************************************************************
  * @brief   设置前置放大
  * @param   [in]Preamp_Factor 前置放大系数 1-100 对应0 - 7,0xFF时静音使能
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-05-06
  ******************************************************************
  */
void CS43L21_Driver_Preamp_Set(float Preamp_Factor)
{
  uint8_t Gain_dB = (uint8_t)(Preamp_Factor*7.f/100.f);
  DAC_Volume_Set(Gain_dB, CS43L21_DRIVER_LR_CH);
}

/**
  ******************************************************************
  * @brief   CS43L21 设备断电
  * @param   [in]None
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-04-30
  ******************************************************************
  */
void CS43L21_Driver_PowerDown_Init(void)
{
  Device_PowerDown_Init();
}

/**
  ******************************************************************
  * @brief   CS43L21 驱动初始化
  * @param   [in]None
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-03-10
  ******************************************************************
  */
void CS43L21_Driver_Init(void)
{
  /*设备上电初始化*/
  Device_PowerOn_Init();
  
  /*设置设备地址*/
  Set_Device_AD0();
  
  /*打印设备ID*/
#if ENABLE_CS43L21_DEBUG
  Display_Chip_ID();
#endif
  
  /*进入配置模式*/
  Entry_Config_Mode();

  /*配置设备为Slave 右对齐16bit*/
  Set_Cfg();
  
  /*设置通道电源*/
  Power_On_Off(CS43L21_DRIVER_LEFT_CH, CS43L21_DRIVER_POWER_ON);
  Power_On_Off(CS43L21_DRIVER_RIGHT_CH, CS43L21_DRIVER_POWER_ON);
  
  /*DAC速率设置*/
  DAC_CLKSpeed_Set();

  /*DAC功能配置*/
  DAC_Config();
  
  /*设置DAC输出增益*/
  DAC_Volume_Set(0, CS43L21_DRIVER_LR_CH);
  
  /*设置混响增益*/
  MIXPath_Volume_Set(0);
  
  /*设置EQ增益*/
  Tone_EQ_Set(5000, 50, 0, 0);
    
  /*调节音量增益*/
  AOutPath_Volume_Set(12.f, CS43L21_DRIVER_LR_CH);
    
  /*退出配置模式*/
  Exit_Config_Mode();
}

#ifdef __cplusplus ///<end extern c
}
#endif
/******************************** End of file *********************************/

/**
 *  @file CS43L21_Driver.h
 *
 *  @date 2021-03-10
 *
 *  @author Copyright (c) 2021 aron566 <aron566@163.com>.
 *
 *  @brief CS43L21 DAC芯片驱动接口
 *  
 *  @version V1.0
 */
#ifndef CS43L21_DRIVER_H
#define CS43L21_DRIVER_H
#ifdef __cplusplus ///<use C compiler
extern "C" {
#endif
/** Includes -----------------------------------------------------------------*/
#include <stdint.h> /**< need definition of uint8_t */
#include <stddef.h> /**< need definition of NULL    */
#include <stdbool.h>/**< need definition of BOOL    */
#include <stdio.h>  /**< if need printf             */
#include <stdlib.h>
#include <string.h>
#include <limits.h> /**< need variable max value    */
/** Private includes ---------------------------------------------------------*/

/** Private defines ----------------------------------------------------------*/

/** Exported typedefines -----------------------------------------------------*/
/*CS43L12声道编号*/
typedef enum
{
  CS43L21_DRIVER_LEFT_CH = 0,
  CS43L21_DRIVER_RIGHT_CH,
  CS43L21_DRIVER_LR_CH
}CS43L21_DRIVER_CH_Typedef_t;

/*CS43L12声道输出开关*/
typedef enum
{
  CS43L21_DRIVER_POWER_OFF = 0,
  CS43L21_DRIVER_POWER_ON
}CS43L21_DRIVER_POWER_Typedef_t;

/** Exported constants -------------------------------------------------------*/

/** Exported macros-----------------------------------------------------------*/
/** Exported variables -------------------------------------------------------*/
/** Exported functions prototypes --------------------------------------------*/

/*CS43L21 驱动初始化*/
void CS43L21_Driver_Init(void);
/*CS43L21 设备断电*/
void CS43L21_Driver_PowerDown_Init(void);
/*CS43L21 设置左右耳音量*/
void CS43L21_Driver_Vol_Set(uint8_t Vol, CS43L12_DRIVER_CH_Typedef_t Channel);
/*CS43L21 设置前置放大*/
void CS43L21_Driver_Preamp_Set(float Preamp_Factor);

#ifdef __cplusplus ///<end extern c
}
#endif
#endif
/******************************** End of file *********************************/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aron566

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值