0

How do I make sense of this STM32F4 data that's being sent over I2C? I'm sending this I2C stream from one STM32F4 to another STM32F4.

I'm getting the ACKs I expect, but the data itself looks a little unusual.

I have a 12bit ADC that I'm getting managed by a DMA. Here's the setup code:

  volatile uint32_t ADCValue[2];
 if(HAL_ADC_Start(&hadc1) != HAL_OK)
        HAL_GPIO_WritePin(GPIOC, LED3_Pin, SET);
 if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADCValue,4) != HAL_OK)
        HAL_GPIO_WritePin(GPIOC, LED4_Pin, SET);
 while(1){
 while(HAL_I2C_Master_Transmit(&hi2c3, 252, (uint8_t*) ADCValue[1], 4, 10000) != HAL_OK)
}

And, here's the ADC setup

ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

/* ADC1 init function */
void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig;

    /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
    */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
  hadc1.Init.Resolution = ADC_RESOLUTION_8B;
  hadc1.Init.ScanConvMode = ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 2;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
    */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_144CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
    */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = 2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

So, naturally, the most ballsy thing I think I'm doing here is trying to break up a single ADCValue element into 4 8-bit values, since it's defined as a 32-bit int...

I'm getting 4 bytes after the address byte, but I'm not sure if this thing that I'm doing with the DMA and casting types is fundamentally flawed.

Any C experts got any insight on how to send 32-bit values over I2C with the HAL libraries?

phuclv
  • 37,963
  • 15
  • 156
  • 475
testname123
  • 1,061
  • 3
  • 20
  • 43

1 Answers1

0

I think that you are sending an invalid pointer to the I2C:

 while(HAL_I2C_Master_Transmit(&hi2c3, 252, (uint8_t*) ADCValue[1], 4, 10000) != HAL_OK)

I don't understand what do you want to send via I2C, this mean that the value of ADCValue[1] is a pointer to the data to transmit, maybe you should change by:

 while(HAL_I2C_Master_Transmit(&hi2c3, 252, (uint8_t*) ADCValue, 4, 10000) != HAL_OK)

If you want to send the value of ADCValue, or if you want to shift 1 byte:

 while(HAL_I2C_Master_Transmit(&hi2c3, 252, &((uint8_t*) ADCValue)[1], 4, 10000) != HAL_OK)

In this case it would be easier if you do an union between uin32 array and uint8 array.

JMA
  • 494
  • 2
  • 13
  • Pointers confuse me...Thank you, I'll give this a go – testname123 Jan 11 '18 at 14:53
  • Are you sure that this code is protected against benign races? – JMA Jan 12 '18 at 07:50
  • What do you mean? – testname123 Jan 12 '18 at 09:15
  • Imagine that I2C starts a transmision, when 2 bytes have been send, ADC ends the conversion and updates the value, then I2C transmit the other 2 bytes. The value transmited is half of the old value and half of the new value. – JMA Jan 12 '18 at 09:23
  • There are many solutions, If I2C transmision is faster than the ADC conversion you can use 2 variables and a pointer that points to the last value. When conversion ends change the pointer to the current value, start a new conversion with the other variable. I2C always works with the pointer to the last value. – JMA Jan 12 '18 at 09:59
  • How do you mean a Union of uint32 and uint8? Sometimes I'll want to send element 0 only and sometimes I'll want to send element 1 only over the bus....how can a union of those two help, and what sort of pseudo code are you thinking of? – testname123 Jan 12 '18 at 16:29
  • When you say "element 1", do you mean the second uint32 of the array, or the second, third and fourth bytes of a uint32? Union helps in the second case. You can take a look to the second answer of this post: https://stackoverflow.com/questions/3784263/converting-an-int-into-a-4-byte-char-array-c – JMA Jan 15 '18 at 08:05