/* * @Author: CTW * @Date: 2025-11-07 14:37:55 * @FilePath: \PhoenixSMGT_Testproject\Drivers\AD85050\Drv_AD85020B.c * @note: 从 STM32 HAL 库移植到 AT32F403A。 * 同时保留硬件 I2C1(官方 i2c_application 库)与软件 GPIO I2C 两套实现, * 由头文件 AD85020B_I2C_USE_HW 宏选择(1=硬件,0=软件)。 * - HAL_I2C_Mem_Write -> i2c_memory_write / 软件时序 * - HAL_Delay -> wk_delay_ms * - HAL_StatusTypeDef -> AD85020B_StatusTypeDef */ #include "Drv_AD85020B.h" #include "wk_system.h" #include /* ===================================================================== * 硬件 I2C1 实现(AD85020B_I2C_USE_HW = 1) * 依赖官方 i2c_application 库(middlewares/i2c_application_library) * ===================================================================== */ #if AD85020B_I2C_USE_HW #include "i2c_application.h" #include "includes.h" static void AD85020B_I2C_InitImpl(void) { wk_i2c1_init(); // gpio_init_type g; // // /* 使能 GPIOB / I2C1 时钟 */ // crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE); // crm_periph_clock_enable(CRM_I2C1_PERIPH_CLOCK, TRUE); // // /* PB6=SCL, PB7=SDA:复用开漏 + 上拉 */ // gpio_default_para_init(&g); // g.gpio_mode = GPIO_MODE_MUX; // g.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN; // g.gpio_pull = GPIO_PULL_UP; // g.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; // g.gpio_pins = AD85020B_SCL_PIN; // gpio_init(AD85020B_I2C_PORT, &g); // g.gpio_pins = AD85020B_SDA_PIN; // gpio_init(AD85020B_I2C_PORT, &g); // // /* I2C1 主机 100kHz */ // i2c_init(I2C1, I2C_FSMODE_DUTY_2_1, 100000); // i2c_own_address1_set(I2C1, I2C_ADDRESS_MODE_7BIT, 0x0); // i2c_ack_enable(I2C1, TRUE); // i2c_clock_stretch_enable(I2C1, TRUE); // i2c_general_call_enable(I2C1, FALSE); // i2c_enable(I2C1, TRUE); } static AD85020B_StatusTypeDef AD85020B_I2C_WriteImpl(uint8_t reg, uint8_t data) { i2c_handle_type hi2c; i2c_status_type status; uint8_t buf = data; hi2c.i2cx = I2C1; /* i2c_memory_write: START → 器件地址+W → 寄存器(8bit) → 数据 → STOP 地址传 8 位写地址 0x60(库内部 &0xFE 保持为写) */ status = i2c_memory_write(&hi2c, I2C_MEM_ADDR_WIDIH_8, AD85020B_I2C_ADDR_W, reg, &buf, 1, AD85020B_I2C_TIMEOUT); if (status != I2C_OK) { printf("[AD85020B] HW_Write fail ret=0x%X inner=0x%X\r\n", (unsigned)status, (unsigned)hi2c.error_code); return AD85020B_ERROR; } return AD85020B_OK; } static AD85020B_StatusTypeDef AD85020B_I2C_ReadImpl(uint8_t reg, uint8_t *data) { i2c_handle_type hi2c; i2c_status_type status; if (data == 0) return AD85020B_ERROR; hi2c.i2cx = I2C1; /* i2c_memory_read: START → 地址+W → 寄存器 → RESTART → 地址+R → 数据 → STOP 地址传 8 位写地址 0x60,库内部读阶段自动 |0x01 成 0x61 */ status = i2c_memory_read(&hi2c, I2C_MEM_ADDR_WIDIH_8, AD85020B_I2C_ADDR_W, reg, data, 1, AD85020B_I2C_TIMEOUT); if (status != I2C_OK) { printf("[AD85020B] HW_Read fail ret=0x%X inner=0x%X\r\n", (unsigned)status, (unsigned)hi2c.error_code); return AD85020B_ERROR; } return AD85020B_OK; } /* ===================================================================== * 软件 I2C 实现(AD85020B_I2C_USE_HW = 0) * 不依赖硬件 I2C 外设,纯 GPIO 位翻转 * ===================================================================== */ #else #define I2C_DELAY() { volatile uint32_t i = 8; while (i--); } static void SCL_High(void) { gpio_bits_set(AD85020B_I2C_PORT, AD85020B_SCL_PIN); } static void SCL_Low(void) { gpio_bits_reset(AD85020B_I2C_PORT, AD85020B_SCL_PIN); } static void SDA_High(void) { gpio_bits_set(AD85020B_I2C_PORT, AD85020B_SDA_PIN); } static void SDA_Low(void) { gpio_bits_reset(AD85020B_I2C_PORT, AD85020B_SDA_PIN); } static uint8_t SDA_Read(void) { return (gpio_input_data_bit_read(AD85020B_I2C_PORT, AD85020B_SDA_PIN) == SET) ? 1 : 0; } static void I2C_Start(void) { SDA_High(); SCL_High(); I2C_DELAY(); SDA_Low(); I2C_DELAY(); SCL_Low(); I2C_DELAY(); } static void I2C_Stop(void) { SDA_Low(); SCL_High(); I2C_DELAY(); SDA_High(); I2C_DELAY(); } static uint8_t I2C_SendByte(uint8_t data) { uint8_t i, ack; for (i = 0; i < 8; i++) { if (data & 0x80) SDA_High(); else SDA_Low(); data <<= 1; I2C_DELAY(); SCL_High(); I2C_DELAY(); SCL_Low(); I2C_DELAY(); } SDA_High(); I2C_DELAY(); SCL_High(); I2C_DELAY(); ack = SDA_Read(); SCL_Low(); I2C_DELAY(); return ack; } static uint8_t I2C_RecvByte(uint8_t ack) { uint8_t i, data = 0; SDA_High(); for (i = 0; i < 8; i++) { SCL_High(); I2C_DELAY(); data = (data << 1) | SDA_Read(); SCL_Low(); I2C_DELAY(); } if (ack) SDA_High(); else SDA_Low(); I2C_DELAY(); SCL_High(); I2C_DELAY(); SCL_Low(); I2C_DELAY(); SDA_High(); I2C_DELAY(); return data; } static void AD85020B_I2C_InitImpl(void) { gpio_init_type g; gpio_default_para_init(&g); g.gpio_mode = GPIO_MODE_OUTPUT; g.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN; g.gpio_pull = GPIO_PULL_UP; g.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; g.gpio_pins = AD85020B_SCL_PIN; gpio_init(AD85020B_I2C_PORT, &g); g.gpio_pins = AD85020B_SDA_PIN; gpio_init(AD85020B_I2C_PORT, &g); SDA_High(); SCL_High(); } static AD85020B_StatusTypeDef AD85020B_I2C_WriteImpl(uint8_t reg, uint8_t data) { I2C_Start(); if (I2C_SendByte(AD85020B_I2C_ADDR_W)) { printf("[AD85020B] SW ADDR_NACK\r\n"); return AD85020B_ERROR; } if (I2C_SendByte(reg)) { printf("[AD85020B] SW REG_NACK reg=0x%02X\r\n", reg); return AD85020B_ERROR; } if (I2C_SendByte(data)) { printf("[AD85020B] SW DATA_NACK\r\n"); return AD85020B_ERROR; } I2C_Stop(); return AD85020B_OK; } static AD85020B_StatusTypeDef AD85020B_I2C_ReadImpl(uint8_t reg, uint8_t *data) { if (data == 0) return AD85020B_ERROR; I2C_Start(); if (I2C_SendByte(AD85020B_I2C_ADDR_W)) return AD85020B_ERROR; if (I2C_SendByte(reg)) return AD85020B_ERROR; I2C_Start(); if (I2C_SendByte(AD85020B_I2C_ADDR_R)) return AD85020B_ERROR; *data = I2C_RecvByte(1); I2C_Stop(); return AD85020B_OK; } #endif /* AD85020B_I2C_USE_HW */ /* ===================================================================== * 对外统一接口(按宏分发到硬件/软件实现) * ===================================================================== */ void AD85020B_I2C_Init(void) { AD85020B_I2C_InitImpl(); } AD85020B_StatusTypeDef AD85020B_I2C_Write(uint8_t reg, uint8_t data) { return AD85020B_I2C_WriteImpl(reg, data); } AD85020B_StatusTypeDef AD85020B_I2C_Read(uint8_t reg, uint8_t *data) { return AD85020B_I2C_ReadImpl(reg, data); } /** * @brief AD85020B 初始化 * @retval AD85020B_StatusTypeDef: 初始化结果 */ AD85020B_StatusTypeDef AD85020B_Init(void) { AD85020B_StatusTypeDef status; uint8_t vol = 0x2c; AD85020B_I2C_Init(); wk_delay_ms(1); // 文档要求 AMP_SDB 拉高后延时≥20ms /* 步骤2:软件复位(文档SCTL6寄存器,BIT5=0) */ status = AD85020B_I2C_Write(AD85020B_REG_SCTL6, AD85020B_SW_RESET); if (status != AD85020B_OK) return status; wk_delay_ms(20); // 等待复位完成(文档未明确,建议10~50ms) /* 步骤3:复位后恢复正常模式(BIT5=1) */ status = AD85020B_I2C_Write(AD85020B_REG_SCTL6, AD85020B_SW_NORMAL); if (status != AD85020B_OK) return status; wk_delay_ms(10); /* 步骤4:配置输入格式(文档SCTL1,默认I2S格式,0x00) */ status = AD85020B_I2C_Write(AD85020B_REG_SCTL1, 0x00); if (status != AD85020B_OK) return status; wk_delay_ms(10); // /* 步骤5:配置采样率(文档SCTL2,默认0x91:44.1/48kHz,64x BCLK) */ // status = AD85020B_I2C_Write(AD85020B_REG_SCTL2, 0x91); // if (status != AD85020B_OK) return status; // wk_delay_ms(10); /* 步骤7:设置主音量(文档MVOL,0x18对应0dB,避免过载) */ status = AD85020B_I2C_Write(AD85020B_REG_MVOL, vol); if (status != AD85020B_OK) return status; wk_delay_ms(10); status = AD85020B_I2C_Write(AD85020B_REG_MVOL, vol); if (status != AD85020B_OK) return status; wk_delay_ms(10); status = AD85020B_I2C_Write(AD85020B_REG_MVOL, vol); if (status != AD85020B_OK) return status; wk_delay_ms(10); status = AD85020B_I2C_Write(AD85020B_REG_HEADPHONEVOL, vol); if (status != AD85020B_OK) return status; wk_delay_ms(10); /* 步骤8:设置通道音量(0x04~0x09,0x18对应0dB,避免过载) */ status = AD85020B_I2C_Write(0x04, vol); if (status != AD85020B_OK) return status; wk_delay_ms(10); status = AD85020B_I2C_Write(0x05, vol); if (status != AD85020B_OK) return status; wk_delay_ms(10); status = AD85020B_I2C_Write(0x06, vol); if (status != AD85020B_OK) return status; wk_delay_ms(10); status = AD85020B_I2C_Write(0x07, vol); if (status != AD85020B_OK) return status; wk_delay_ms(10); status = AD85020B_I2C_Write(0x08, vol); if (status != AD85020B_OK) return status; wk_delay_ms(10); status = AD85020B_I2C_Write(0x09, vol); if (status != AD85020B_OK) return status; wk_delay_ms(10); /* 步骤6:解除静音(文档SCTL3,MMUTE=0,0x00) */ status = AD85020B_I2C_Write(AD85020B_REG_SCTL3, 0x00); if (status != AD85020B_OK) return status; wk_delay_ms(10); return AD85020B_OK; }