Hi everybody, I new here and I need your experience and assistance. I'm in a new project (Audio control by TM4C129XNCZA) and I'm having many troubles with I2C module. In the first instance I want to write and read data from a register of TLV320AIC3107 for initing device. I base on code driver of TI (dac.c). But it always loop for waiting byte transfer.
//
// Wait until the current byte has been transferred.
//
while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false))
{
I2CMasterIntClear(DAC_I2C_MASTER_BASE);
}
KIT I am using DK-129x for TM4C and TLV320AIC3107EVM kit for TLV320AIC3107. And I use i2c 1 to control.
Link for DK-129x : www.ti.com/.../spmu360.pdf
Link for TLV320AIC3107EVM : www.ti.com/.../slau261.pdf
And here is my code.
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_ssi.h"
#include "driverlib/ssi.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/systick.h"
#include "driverlib/sysctl.h"
#include "driverlib/udma.h"
#include "driverlib/interrupt.h"
#include "driverlib/timer.h"
#include "dac.h"
//*****************************************************************************
//
//! \addtogroup dac_api
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
// The I2C and reset pins that are used by this application.
//
//*****************************************************************************
#define DAC_I2C_PERIPH (SYSCTL_PERIPH_I2C1)
#define DAC_I2C_GPIO_PERIPH (SYSCTL_PERIPH_GPIOG)
#define DAC_I2CSCL_GPIO (GPIO_PG0_I2C1SCL)
#define DAC_I2CSDA_GPIO (GPIO_PG1_I2C1SDA)
#define DAC_I2C_BASE (GPIO_PORTG_BASE)
#define DAC_I2CSDA_PIN (GPIO_PIN_1)
#define DAC_I2CSCL_PIN (GPIO_PIN_0)
#define DAC_I2C_MASTER_BASE (I2C1_BASE)
#define DAC_RESET_GPIO_PERIPH (SYSCTL_PERIPH_GPIOE)
#define DAC_RESET_GPIO_PORT (GPIO_PORTE_BASE)
#define DAC_RESET_PIN (GPIO_PIN_4)
//*****************************************************************************
//
// The current volume of the DAC.
//
//*****************************************************************************
unsigned long g_ucHPVolume;
extern uint32_t g_ui32SysClock;
//****************************************************************************
//***************************************************************************** #include <stdbool.h> #include <stdint.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_ssi.h" #include "driverlib/ssi.h" #include "driverlib/debug.h" #include "driverlib/gpio.h" #include "driverlib/i2c.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/systick.h" #include "driverlib/sysctl.h" #include "driverlib/udma.h" #include "driverlib/interrupt.h" #include "driverlib/timer.h" #include "dac.h" //***************************************************************************** // //! \addtogroup dac_api //! @{ // //***************************************************************************** //***************************************************************************** // // The I2C and reset pins that are used by this application. // //***************************************************************************** #define DAC_I2C_PERIPH (SYSCTL_PERIPH_I2C1) #define DAC_I2C_GPIO_PERIPH (SYSCTL_PERIPH_GPIOG) #define DAC_I2CSCL_GPIO (GPIO_PG0_I2C1SCL) #define DAC_I2CSDA_GPIO (GPIO_PG1_I2C1SDA) #define DAC_I2C_BASE (GPIO_PORTG_BASE) #define DAC_I2CSDA_PIN (GPIO_PIN_1) #define DAC_I2CSCL_PIN (GPIO_PIN_0) #define DAC_I2C_MASTER_BASE (I2C1_BASE) #define DAC_RESET_GPIO_PERIPH (SYSCTL_PERIPH_GPIOE) #define DAC_RESET_GPIO_PORT (GPIO_PORTE_BASE) #define DAC_RESET_PIN (GPIO_PIN_4) //***************************************************************************** // // The current volume of the DAC. // //***************************************************************************** unsigned long g_ucHPVolume; extern uint32_t g_ui32SysClock; //***************************************************************************** // //! Writes a register in the TLV320AIC3107 DAC. //! //! \param ucRegister is the offset to the register to write. //! \param ulData is the data to be written to the DAC register. //! //! This function will write the register passed in ucAddr with the value //! passed in to ulData. The data in ulData is actually 9 bits and the //! value in ucAddr is interpreted as 7 bits. //! //! \return True on success or false on error. // //***************************************************************************** bool DACWriteRegister(unsigned char ucRegister, unsigned long ulData) { IntMasterDisable(); // // Set the slave address. // I2CMasterSlaveAddrSet(DAC_I2C_MASTER_BASE, TI_TLV320AIC3107_ADDR, false); // // Write the first byte to the controller (register) // I2CMasterDataPut(DAC_I2C_MASTER_BASE, ucRegister); // // Continue the transfer. // I2CMasterControl(DAC_I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START); // // Wait until the current byte has been transferred. // while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false) == 0) { } if(I2CMasterErr(DAC_I2C_MASTER_BASE) != I2C_MASTER_ERR_NONE) { I2CMasterIntClear(DAC_I2C_MASTER_BASE); return(false); } // // Wait until the current byte has been transferred. // while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false)) { I2CMasterIntClear(DAC_I2C_MASTER_BASE); } //while(I2CMasterBusy(DAC_I2C_MASTER_BASE)) //{} // // Write the data byte to the controller. // I2CMasterDataPut(DAC_I2C_MASTER_BASE, ulData); // // End the transfer. // I2CMasterControl(DAC_I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH); // // Wait until the current byte has been transferred. // while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false) == 0) { } if(I2CMasterErr(DAC_I2C_MASTER_BASE) != I2C_MASTER_ERR_NONE) { return(false); } while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false)) { I2CMasterIntClear(DAC_I2C_MASTER_BASE); } IntMasterEnable(); return(true); } //***************************************************************************** // // Reads a register in the TLV320AIC3107 DAC. // // \param ucRegister is the offset to the register to write. // \param pucData is a pointer to the returned data. // // \return \b true on success or \b false on error. // //***************************************************************************** static bool DACReadRegister(unsigned char ucRegister, unsigned char *pucData) { // // Set the slave address and "WRITE" // I2CMasterSlaveAddrSet(DAC_I2C_MASTER_BASE, TI_TLV320AIC3107_ADDR, false); // // Write the first byte to the controller (register) // I2CMasterDataPut(DAC_I2C_MASTER_BASE, ucRegister); // // Continue the transfer. // I2CMasterControl(DAC_I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START); // // Wait until the current byte has been transferred. // while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false) == 0) { } if(I2CMasterErr(DAC_I2C_MASTER_BASE) != I2C_MASTER_ERR_NONE) { I2CMasterIntClear(DAC_I2C_MASTER_BASE); return(false); } // // Wait until the current byte has been transferred. // while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false)) { I2CMasterIntClear(DAC_I2C_MASTER_BASE); } // // Set the slave address and "READ"/true. // I2CMasterSlaveAddrSet(DAC_I2C_MASTER_BASE, TI_TLV320AIC3107_ADDR, true); // // Read Data Byte. // I2CMasterControl(DAC_I2C_MASTER_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE); // // Wait until the current byte has been transferred. // while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false) == 0) { } if(I2CMasterErr(DAC_I2C_MASTER_BASE) != I2C_MASTER_ERR_NONE) { I2CMasterIntClear(DAC_I2C_MASTER_BASE); return(false); } // // Wait until the current byte has been transferred. // while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false)) { I2CMasterIntClear(DAC_I2C_MASTER_BASE); } // // Read the value received. // *pucData = I2CMasterDataGet(DAC_I2C_MASTER_BASE); return(true); } //***************************************************************************** // //! Initializes the TLV320AIC3107 DAC. //! //! This function initializes the I2C interface and the TLV320AIC3107 DAC. It //! must be called prior to any other API in the DAC module. //! //! \return Returns \b true on success or \b false on failure. // //***************************************************************************** bool DACInit(void) { bool bRetcode; unsigned char ucTest; uint8_t ucread; // // Enable the GPIO port containing the I2C pins and set the SDA pin as a // GPIO input for now and engage a weak pull-down. If the daughter board // is present, the pull-up on the board should easily overwhelm // the pull-down and we should read the line state as high. // SysCtlPeripheralReset(DAC_I2C_PERIPH); SysCtlPeripheralEnable(DAC_I2C_PERIPH); // // Enable the I2C peripheral. // SysCtlPeripheralReset(DAC_I2C_GPIO_PERIPH); SysCtlPeripheralEnable(DAC_I2C_GPIO_PERIPH); // // Delay a while to ensure that we read a stable value from the SDA // GPIO pin. If we read too quickly, the result is unpredictable. // This delay is around 2mS. // SysCtlDelay(g_ui32SysClock / (3 * 500)); // // Configure the pin mux. // GPIOPinConfigure(DAC_I2CSCL_GPIO); GPIOPinConfigure(DAC_I2CSDA_GPIO); // // Configure the I2C SCL and SDA pins for I2C operation. // GPIOPinTypeI2C(DAC_I2C_BASE, DAC_I2CSDA_PIN); GPIOPinTypeI2CSCL(DAC_I2C_BASE, DAC_I2CSCL_PIN); // // Initialize the I2C master. // I2CMasterInitExpClk(DAC_I2C_MASTER_BASE, g_ui32SysClock, false); SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1); // // Enable the I2C peripheral. // //SysCtlPeripheralEnable(DAC_RESET_GPIO_PERIPH); // // Configure the PD0 as a GPIO output. // GPIOPinTypeGPIOOutput(DAC_RESET_GPIO_PORT, DAC_RESET_PIN); // // Reset the DAC // GPIOPinWrite(DAC_RESET_GPIO_PORT , DAC_RESET_PIN, 0); GPIOPinWrite(DAC_RESET_GPIO_PORT , DAC_RESET_PIN, DAC_RESET_PIN); // // Reset the DAC. Check the return code on this call since we use it to // indicate whether or not the DAC is present. If the register write // fails, we assume the I2S daughter board and DAC are not present and // return false. // bRetcode = DACWriteRegister(TI_SOFTWARE_RESET_R, 0x80); if(!bRetcode) { return(bRetcode); } // // Codec Data Path Register // ---------------------- // Fsref = 44.1kHz. // Left DAC datapath plays left channel input data. // Right DAC datapath plays right channel input data. // ---------------------- // D[7:0] = 1000 1010 // DACWriteRegister(7, 0x8A); // // Audio Serial Data Interface Control Register A // ---------------------- // BCLK is an output (master mode) // WCLK is an output (master mode) // BCLK/WCLK will continue to be transmitted when running in master mode. // ---------------------- // D[7:0] = 1101 0000 // DACWriteRegister(8, 0xD0); DACReadRegister(8, &ucread); // // Audio Serial Data Interface Control Register B // ---------------------- // Serial data bus uses I2S mode. // Audio data word length = 16-bits. // ---------------------- // D[7:0] = 0000 0000 // DACWriteRegister(9, 0x00); // // PLL Programming Register A // ---------------------- // PLL Disabled (Enable Later) // Q = 2 // P = 2 // ---------------------- // D[7:0] = 0001 0010 // DACWriteRegister(3, 0x12); // // PLL Programming Register B // ---------------------- // J = 7 // ---------------------- // D[7:0] = 0001 1100 // DACWriteRegister(4, 0x1C); // // PLL Programming Register C // ---------------------- // D most significant bits // ---------------------- // D[7:0] = 0010 0011 // DACWriteRegister(5, 0x23); // // PLL Programming Register D // ---------------------- // D least significant bits // ---------------------- // D[7:0] = 0011 0100 // DACWriteRegister(6, 0x34); // // PLL Programming Register A // ---------------------- // PLL is enabled. // Q = 2. // P = 2. // ---------------------- // D[7:0] = 1001 0010 // DACWriteRegister(3, 0x92); // // Headset/Button Press Detection Register A // ---------------------- // Headset detection enabled. // ---------------------- // D[7:0] = 1000 0000 // DACWriteRegister(13, 0x80); // // Headset/Button Press Detection Register B // ---------------------- // Configure to stereo fully-differential output // ---------------------- // D[7:0] = 0100 0000 // DACWriteRegister(14, 0x40); // // DAC Output Switching Control Register // ---------------------- // Left DAC output selects DAC_L1 path // Right DAC output selects DAC_R1 path // Left and right DAC channels have independent volume controls. // ---------------------- // D[7:0] = 0000 0000 // DACWriteRegister(41, 0x00); // // Left DAC Digital Volume Control Register // ---------------------- // The left DAC is not muted. // Gain = 0.0dB. // ---------------------- // D[7:0] = 0000 0000 // DACWriteRegister(43, 0x00); // // Right DAC Digital Volume Control Register // ---------------------- // The right DAC channel is not muted. // Gain = 0.0dB. // ---------------------- // D[7:0] = 0000 0000 // DACWriteRegister(44, 0x00); // // Codec Sample Rate Select Register // ---------------------- // DAC Fs = Fsref/4. // ---------------------- // D[7:0] = 0000 0110 // DACWriteRegister(2, 0x06); // // DAC_L1 to HPLOUT Volume Control Register // ---------------------- // DAC_L1 is routed to HPLOUT. // ---------------------- // D[7:0] = 1000 0000 // DACWriteRegister(47, 0x80); // // DAC_R1 to HPROUT Volume Control Register // ---------------------- // DAC_R1 is routed to HPROUT. // ---------------------- // D[7:0] = 1000 0000 // DACWriteRegister(64, 0x80); // // DAC Power and Output Driver Control Register // ---------------------- // Left DAC is powered up. // Right DAC is powered up. // ---------------------- // D[7:0] = 1100 0000 // DACWriteRegister(37, 0xC0); // // Using L2/R2 bypasses the analog volume controls & mixing networks. This // output provides the highest quality DAC playback performance with // reduced power dissipation. Note: This can only be utilized if the DAC // output does not need to route to multiple output drivers simultaneously, // and if mixing of the DAC output with other analog signals is not needed. // If mixing isdesired, L1/R2 would be utilized. However, for our // differential headpones/speakers, this will suffice. // // DAC Output Switching Control Register // ---------------------- // Left DAC output selects DAC_L2 path to left high power output drivers. // Right DAC output selects DAC_R2 path to right high power output drivers. // ---------------------- // D[7:0] = 1010 0000 // DACWriteRegister(41, 0xA0); // // Output Driver Pop Reduction Register // ---------------------- // Driver power-on time = 400mS. // Driver ramp-up step time = 0mS. // ---------------------- // D[7:0] = 1000 0000 // DACWriteRegister(42, 0x80); // // HPROUT Output Level Control Register // ---------------------- // Output level control = 0dB. // HPROUT is not muted. // HPROUT is weakly driven to a common-mode when powered down. // HPROUT is fully powered up. // ---------------------- // D[7:0] = 0000 1101 // DACWriteRegister(65, 0x0D); // // HPLOUT Output Level Control Reigster // ---------------------- // Output level control = 0dB. // HPLOUT is not muted. // HPLOUT is weakly driven to a common-mode when powered down. // HPLOUT is fully powered up. // ---------------------- // D[7:0] = 0000 1101 // DACWriteRegister(51, 0x0D); // // Left DAC Digital Volume Control Register // ---------------------- // Gain = -30dB. // ---------------------- // D[7:0] = 0010 1100 // DACWriteRegister(43, pucVolumeTable[50 / 10 - 1]); // // Right DAC Digital Volume Control Register // ---------------------- // Gain = -30dB. // ---------------------- // D[7:0] = 0011 1100 // DACWriteRegister(44, pucVolumeTable[3]); // // Codec Datapath Setup Register // ---------------------- // Fsref = 44.1kHz. // DAC dual rate mode is enabled. // LEFT DAC datapath plays left channel input data. // RIGHT DAC datapath plays right channel input data. // ---------------------- // D[7:0] = 1010 1010 // DACWriteRegister(7, 0xAA); // // Codec Sample Rate Select Register // ---------------------- // DAC Fs = Fsref/2 // ---------------------- // D[7:0] = 0000 0010 // DACWriteRegister(2, 0x02); // //Read Module Power Status Register // bRetcode = DACReadRegister(TI_MODULE_PWR_STAT_R, &ucTest); if(!bRetcode) { return(bRetcode); } return(true); }