@[toc](CS43L12 DAC芯片驱动)
音频数据通过MIC采集上来后有的的PDM数据有的直接是PCM数据,CS43L12做的就是将PCM数据播放出来。
CubeMX配置如下
音频数据传输I2S接口
在这里插入图片描述
开DMA双缓冲
在这里插入图片描述
芯片配置I2C通讯
在这里插入图片描述
驱动代码
/**
* @file CS43L12_Driver.c
*
* @date 2021-03-10
*
* @author aron566
*
* @copyright Copyright (c) 2021 aron566 <aron566@163.com>.
*
* @brief CS43L12 DAC芯片驱动接口
*
* @details 1、CS43L12
*
* @version V1.0
*/
#ifdef __cplusplus ///<use C compiler
extern "C" {
#endif
/** Includes -----------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
#include "CS43L12_Driver.h"
#include "main.h"
#include "SAI_Port.h"
/** Private typedef ----------------------------------------------------------*/
/** Private macros -----------------------------------------------------------*/
#define ENABLE_CS43L12_DEBUG 1/**< 启动打印调试*/
/*CS43L12设备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
/*CS43L12设备I2C写操作地址*/
#define DEV_ADDR_WRITE (DEV_ADDR|0x00)
/*CS43L12设备I2C读操作地址*/
#define DEV_ADDR_READ (DEV_ADDR|0x01)
/*CS43L12寄存器地址*/
#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)
/** Private constants --------------------------------------------------------*/
/** Public variables ---------------------------------------------------------*/
extern I2C_HandleTypeDef hi2c1;
/** Private variables --------------------------------------------------------*/
static uint8_t Send_Val_Buf[2];
static uint8_t Reg_Val_Buf[2];
/** Private function prototypes ----------------------------------------------*/
#if ENABLE_CS43L12_DEBUG
static void Display_Chip_ID(void);
#endif
static void Set_Device_AD0(void);
static void Power_On_Off(CS43L12_DRIVER_CH_Typedef_t Ch, CS43L12_DRIVER_POWER_Typedef_t On_Off);
/** Private user code --------------------------------------------------------*/
/** Private application code -------------------------------------------------*/
/*******************************************************************************
*
* Static code
*
********************************************************************************
*/
#if ENABLE_CS43L12_DEBUG
/**
******************************************************************
* @brief CS43L12 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;
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1, 100);
HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, Reg_Val_Buf, 1, 100);
printf("Chip ID REG:%02X, VAL:%02X.\r\n", Send_Val_Buf[0], Reg_Val_Buf[0]);/**< 0xD8 0xD9*/
}
#endif
/**
******************************************************************
* @brief CS43L12 上电初始化
* @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 CS43L12 进入配置模式
* @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;
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1, 100);
HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, Reg_Val_Buf, 1, 100);
/*开启PDN Bit解锁设置*/
Send_Val_Buf[1] = Reg_Val_Buf[0] | (REG_BIT0);
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 2, 100);
#if ENABLE_CS43L12_DEBUG
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1, 100);
HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, Reg_Val_Buf, 1, 100);
printf("Entry DAC Power REG:%02X, VAL:%02X.\r\n", Send_Val_Buf[0], Reg_Val_Buf[0]);
#endif
}
/**
******************************************************************
* @brief CS43L12 推出配置模式
* @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;
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1, 100);
HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, Reg_Val_Buf, 1, 100);
/*关闭PDN Bit上锁*/
Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT0);
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 2, 100);
#if ENABLE_CS43L12_DEBUG
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1, 100);
HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, Reg_Val_Buf, 1, 100);
printf("Exit 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 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(CS43L12_DRIVER_CH_Typedef_t Ch, CS43L12_DRIVER_POWER_Typedef_t On_Off)
{
/*读取电源设置状态*/
Send_Val_Buf[0] = REG_POWER_CTL;
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1, 100);
HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, Reg_Val_Buf, 1, 100);
Send_Val_Buf[1] = Reg_Val_Buf[0];
/*关闭*/
if(On_Off == CS43L12_DRIVER_POWER_OFF)
{
/*左*/
if(Ch == CS43L12_DRIVER_LEFT_CH)
{
Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT5);
}
/*右*/
if(Ch == CS43L12_DRIVER_RIGHT_CH)
{
Send_Val_Buf[1] = Send_Val_Buf[1] | (REG_BIT6);
}
}
/*打开*/
else
{
/*左*/
if(Ch == CS43L12_DRIVER_LEFT_CH)
{
Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT5);
}
/*右*/
if(Ch == CS43L12_DRIVER_RIGHT_CH)
{
Send_Val_Buf[1] = Send_Val_Buf[1] & (~REG_BIT6);
}
}
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 2, 100);
#if ENABLE_CS43L12_DEBUG
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1, 100);
HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, Reg_Val_Buf, 1, 100);
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 inline void Set_Cfg(void)
{
/*读取参数*/
Send_Val_Buf[0] = REG_INTERFACE_CFG;
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1, 100);
HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, Reg_Val_Buf, 1, 100);
#if ENABLE_CS43L12_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);
/*设置数据格式 101*/
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_CS43L12_DEBUG
printf("Set Interface CFG REG:%02X, VAL:%02X.\r\n", Send_Val_Buf[0], Send_Val_Buf[1]);
#endif
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 2, 100);
#if ENABLE_CS43L12_DEBUG
HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1, 100);
HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, Reg_Val_Buf, 1, 100);
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 CS43L12 启动DAC
* @param [in]None
* @return None.
* @author aron566
* @version V1.0
* @date 2021-03-11
******************************************************************
*/
void CS43L12_Driver_DAC_Out(int16_t *Audio_Data, uint32_t len)
{
}
/**
******************************************************************
* @brief CS43L12 驱动初始化
* @param [in]None
* @return None.
* @author aron566
* @version V1.0
* @date 2021-03-10
******************************************************************
*/
void CS43L12_Driver_Init(void)
{
/*设备上电初始化*/
Device_PowerOn_Init();
/*设置设备地址*/
Set_Device_AD0();
/*打印设备ID*/
#if ENABLE_CS43L12_DEBUG
Display_Chip_ID();
#endif
/*进入配置模式*/
Entry_Config_Mode();
/*配置设备为Slave 右对齐16bit*/
Set_Cfg();
/*设置通道电源*/
Power_On_Off(CS43L12_DRIVER_LEFT_CH, CS43L12_DRIVER_POWER_ON);
Power_On_Off(CS43L12_DRIVER_RIGHT_CH, CS43L12_DRIVER_POWER_ON);
/*退出配置模式*/
Exit_Config_Mode();
}
#ifdef __cplusplus ///<end extern c
}
#endif
/******************************** End of file *********************************/
/**
* @file CS43L12_Driver.h
*
* @date 2021-03-10
*
* @author Copyright (c) 2021 aron566 <aron566@163.com>.
*
* @brief CS43L12 DAC芯片驱动接口
*
* @version V1.0
*/
#ifndef CS43L12_DRIVER_H
#define CS43L12_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
{
CS43L12_DRIVER_LEFT_CH = 0,
CS43L12_DRIVER_RIGHT_CH
}CS43L12_DRIVER_CH_Typedef_t;
/*CS43L12声道输出开关*/
typedef enum
{
CS43L12_DRIVER_POWER_OFF = 0,
CS43L12_DRIVER_POWER_ON
}CS43L12_DRIVER_POWER_Typedef_t;
/** Exported constants -------------------------------------------------------*/
/** Exported macros-----------------------------------------------------------*/
/** Exported variables -------------------------------------------------------*/
/** Exported functions prototypes --------------------------------------------*/
/*CS43L12 驱动初始化*/
void CS43L12_Driver_Init(void);
/*CS43L12 启动DAC*/
void CS43L12_Driver_DAC_Out(int16_t *Audio_Data, uint32_t len);
#ifdef __cplusplus ///<end extern c
}
#endif
#endif
/******************************** End of file *********************************/