Настройка ADC с DMA на Nucleo-F401RE дает ошибочные значения

Я хочу настроить ADC с DMA на STM32 (Nucleo-F401RE) и передать значения через SPI в Basys 3 FPGA. Перед передачей через SPI, когда я читаю значения в памяти в реальном времени с помощью STMSTudio, они ошибочны.

Раньше я пытался увеличить циклы выборки, но проблема не исчезла. Сконфигурировал АЦП без DMA с функцией HAL_ADC_Start и передавал значения на ПК через UART, не имея возможности получить исходный сигнал. Я не могу понять, в чем проблема.

uint32_t ADC1ConvertedValues[100];

int main(void) {
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_SPI1_Init();


  while (1) {
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_SET);
    if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC1ConvertedValues, 100) ==         HAL_OK) {

      HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_RESET);   
      HAL_SPI_Transmit(&hspi1,(uint8_t*)(ADC1ConvertedValues),4,1);
      HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_SET);
    }
  }
}

void SystemClock_Config(void) {
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};


  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

  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 = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
    Error_Handler();
  }

  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_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
    Error_Handler();
  }
}

static void MX_ADC1_Init(void) {
  ADC_ChannelConfTypeDef sConfig = {0};


  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  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 = 1;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK) {
    Error_Handler();
  }

  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
    Error_Handler();
  }  
}

static void MX_SPI1_Init(void) {

  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK) {
    Error_Handler();
  }
}


static void MX_DMA_Init(void)  {

  __HAL_RCC_DMA2_CLK_ENABLE();
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}


static void MX_GPIO_Init(void) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};  
  __HAL_RCC_GPIOA_CLK_ENABLE();
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);


  GPIO_InitStruct.Pin = GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}
void Error_Handler(void) {
}

#ifdef  USE_FULL_ASSERT

void assert_failed(uint8_t *file, uint32_t line) { 

#endif /* USE_FULL_ASSERT */

РЕДАКТИРОВАТЬ 1: Я использовал IDE arduino для программирования NUCLEO-f401 RE, и ниже используется код:

 #include <f401reMap.h>

float analogPin = pinMap(31); //PA0

float val = 0;  // variable to store the value read

void setup() {
  Serial.begin(115200); //  setup serial
  analogReadResolution(12);

}

void loop() {
  val = analogRead(analogPin);  // read the input pin
  Serial.println(val);          // debug value
}

Работает при частоте входного сигнала ниже 100 Гц. Как увеличить пропускную способность? Мой проект требует преобразования аналогового сигнала от 500 кГц до 900 кГц.


person Archana Narayanan    schedule 28.04.2019    source источник


Ответы (1)


Пытался изменить размер / скорость буфера DMA uint32_t ADC1ConvertedValues ​​[100]; читая о DMA для этого чипа для моего проекта, я обнаружил, что это устанавливает размер выделенных выборок для прямого доступа к памяти за такт? Если это был I2C, или если вы хотите прочитать о концепциях синхронизации, продолжайте читать. Вам нужно найти регистры АЦП, которые устанавливают скорость передачи SPI, и учитывать требования настройки или повторной инициализации.

hadc1.Instance = ADC1; // это выбирает аналоговую схему в цифровую. hasc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // «пропускаем» 3 из 4 тактовых шагов синхронно со шкалой времени, считанной на ... hadc1.Init.Resolution = ADC_RESOLUTION_8B; // использовать 8 битов для упаковки чисел для отправки на интегрированный ЦП f401. Фон математического АЦП и прямого доступа к памяти часто классифицируются по скорости чтения на уровне spi, а не на аналоговом уровне. Итак, если микросхема может выполнять spi 8 кГц с использованием 8 бит, тогда мы можем рассчитать за время bigO (8n + n), что мы должны получить скорость чтения чуть ниже 1 кГц. ОДНАКО вам нужно записать 8 бит, чтобы получить 8 бит, поэтому время bigO теперь равно bigO (n16 + n). Но из-за непрерывного регистра я считаю, что он может быть таким низким, как bigO (8n + n + 8) или (8n + n + 8setupbits). Таким образом, используя то, что мы знаем время, затрачиваемое на промежуточные операции с точки зрения тактовых циклов, обратите внимание, что только термин n должен учитывать предположения о неизвестных условиях запуска внутренних часов и должен иметь скаляр, который относительно тета, если разрешение шкалы является абсолютным требованием. . Также имейте в виду, что на этих частотах вы можете испытывать шум из-за сопротивления импеданса и емкости.

person Community    schedule 22.12.2019