Skip to main content
PGrin.1
Associate
June 10, 2020
Question

STM32F427 I2C no SCL output and *Very* slow SDA output

  • June 10, 2020
  • 3 replies
  • 2239 views

Hi everyone,

I've been working on a custom PCB with an STM32F427 and a TI audio amp (TAS5825M) that need to communicate using I2C. This is my first time using the STM32 line. I set up the project with STM32CubeMX with the appropriate settings for 100 kHz Master mode I2C on the I2C2 peripheral. Here's a picture of the pin configuration.0693W000001qNX1QAM.png

When I make the first call to the HAL_I2C_Master_Transmit, it runs until the address is sent and then fails. I believe that it fails because there is no clock signal and the receiving slave never acknowledges the presence of data, as shown in this capture of the scoped signals:

0693W000001qNY9QAM.png

It just sends the address over and over as each message fails. In addition, notice how slow the data line is sending data! It takes about a second just to send an 8-bit address.

What am I doing wrong here, with respect to the clock and slow SDA speed?

Here's my code:

/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
 
#include <stdlib.h>
#include "i2c_cfg.h"
 
/* USER CODE END Includes */
 
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
 
/* USER CODE END PTD */
 
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
 
/* USER CODE END PD */
 
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
 
/* USER CODE END PM */
 
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c2;
 
/* USER CODE BEGIN PV */
 
static const uint8_t TAS_I2C_ADDR = 0x4D << 1; // 8-bit address
 
// Variable declarations
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C2_Init(void);
/* USER CODE BEGIN PFP */
 
/* USER CODE END PFP */
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
 
void transmit_registers(cfg_reg *r, int n);
 
/* USER CODE END 0 */
 
/**
 * @brief The application entry point.
 * @retval int
 */
int main(void)
{
 /* USER CODE BEGIN 1 */
 
	// in main
	
 /* USER CODE END 1 */
 
 /* MCU Configuration--------------------------------------------------------*/
 
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 
 /* USER CODE BEGIN Init */
 
 /* USER CODE END Init */
 
 /* Configure the system clock */
 SystemClock_Config();
 
 /* USER CODE BEGIN SysInit */
 
 /* USER CODE END SysInit */
 
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_I2C2_Init();
 /* USER CODE BEGIN 2 */
 
	// Set up the TAS by sending I2C
 // transmit_registers(registers, sizeof(registers)/sizeof(registers[0]));
 transmit_registers(registers, sizeof(registers)/sizeof(registers[0]));
 
 /* USER CODE END 2 */
 
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	// More unrelated code in here sends I2S audio data to the TI amp
 }
 /* USER CODE END 3 */
}
 
/**
 * @brief System Clock Configuration
 * @retval None
 */
void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
 
 /** Configure the main internal regulator output voltage 
 */
 __HAL_RCC_PWR_CLK_ENABLE();
 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
 /** Initializes the CPU, AHB and APB busses clocks 
 */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
 RCC_OscInitStruct.PLL.PLLM = 16;
 RCC_OscInitStruct.PLL.PLLN = 192;
 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
 RCC_OscInitStruct.PLL.PLLQ = 4;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 Error_Handler();
 }
 /** Initializes the CPU, AHB and APB busses clocks 
 */
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4;
 
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
 {
 Error_Handler();
 }
 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
 PeriphClkInitStruct.PLLI2S.PLLI2SN = 192;
 PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
 {
 Error_Handler();
 }
}
 
/**
 * @brief I2C2 Initialization Function
 * @param None
 * @retval None
 */
static void MX_I2C2_Init(void)
{
 
 /* USER CODE BEGIN I2C2_Init 0 */
 
 /* USER CODE END I2C2_Init 0 */
 
 /* USER CODE BEGIN I2C2_Init 1 */
 
 /* USER CODE END I2C2_Init 1 */
 hi2c2.Instance = I2C2;
 hi2c2.Init.ClockSpeed = 100000;
 hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
 hi2c2.Init.OwnAddress1 = 0;
 hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
 hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
 hi2c2.Init.OwnAddress2 = 0;
 hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
 hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
 if (HAL_I2C_Init(&hi2c2) != HAL_OK)
 {
 Error_Handler();
 }
 /** Configure Analogue filter 
 */
 if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
 {
 Error_Handler();
 }
 /** Configure Digital filter 
 */
 if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN I2C2_Init 2 */
 
 /* USER CODE END I2C2_Init 2 */
 
}
 
 
/**
 * @brief GPIO Initialization Function
 * @param None
 * @retval None
 */
static void MX_GPIO_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 
 /* GPIO Ports Clock Enable */
 __HAL_RCC_GPIOB_CLK_ENABLE();
 __HAL_RCC_GPIOA_CLK_ENABLE();
 __HAL_RCC_GPIOD_CLK_ENABLE();
 
 /*Configure GPIO pin : PD0 */
 GPIO_InitStruct.Pin = GPIO_PIN_0;
 GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 
}
 
/* USER CODE BEGIN 4 */
 
void transmit_registers(cfg_reg *r, int n) {
 int i = 0;
 while (i < n) {
 switch (r[i].command) {
 case CFG_META_SWITCH:
 // Used in legacy applications. Ignored here.
 break;
 case CFG_META_DELAY:
 HAL_Delay(r[i].param);
 break;
 case CFG_META_BURST:
 HAL_I2C_Master_Transmit(&hi2c2, TAS_I2C_ADDR, (uint8_t *)&r[i+1], r[i].param, HAL_MAX_DELAY);
 i += (r[i].param / 2) + 1;
 break;
 default:
 HAL_I2C_Master_Transmit(&hi2c2, TAS_I2C_ADDR, (uint8_t *)&r[i], 2, HAL_MAX_DELAY);
 break;
 }
 i++;
 }
}

i2c_cfg.h contains a header file that defines an array of register writes to make to the TI amp. Here's an example of some elements of the array:

cfg_reg registers[] = {
 { 0x00, 0x00 },
 { 0x7f, 0x00 },
 { 0x03, 0x02 },
 { 0x01, 0x11 },
 { 0x00, 0x00 },
 { 0x00, 0x00 },
 { 0x00, 0x00 },
 { 0x00, 0x00 },
 { 0x00, 0x00 },
 { 0x00, 0x00 },
 { 0x7f, 0x00 },
 { 0x46, 0x09 },
 
etc...

Any help is appreciated!

Thanks,

Andrew

This topic has been closed for replies.

3 replies

waclawek.jan
Super User
June 10, 2020

Bad solder joint on the SCK pin?

In debugger, check the respective GPIO settings. Then change the respective GPIO_MODER setting from AF to Out, wiggle the pin in GPIO_ODR and observe.

JW

PGrin.1
PGrin.1Author
Associate
June 13, 2020

Hello Jan,

Thank you for the reply. You are entirely correct. When I had initially probed for continuity I had only contacted the pad, not the MCU pin. I have since secured the SCK pin and it worked perfectly.

Thank you so much!!!

Best,

Andrew

Piranha
Principal III
June 13, 2020

And just for clarity - SDA was slow because of clock stretching feature. Turning it off would make it fast irrespective of actual clock signal.