STM32F103 ADC DMA takıldığım bir nokta

Başlatan magnetron, 19 Mart 2018, 16:20:28

magnetron

merhaba forum

STM32F103 ADC yi DMA ile kullanıyorum - SP Library deki örneklerden bir kod oluşturdum
istiyorum ki ADC yi ben dışardan bir input 1 olduğu zaman başlatayım ve 50 çevrim yaptıktan sonra dursun

istediğim oluyor ama ben 50 çevrim yapsın sonra dursun istiyorum ADC tek bir çevrim yapıyor duruyor
onu da nereden anlıyorum - ADC girişine VREF/2 verip 50 cevrimin ortalamasını alıyorum ama
her start edişimde 2048 değerinin 50 de biri kadar değişiyor

nerede yanlış yapıyorum

teşekkür

kodlar şöyle

void init_adc1(void)
{
//    ADC_InitTypeDef  ADC_InitStructure;

GPIO_InitStructure.GPIO_Pin = /*GPIO_Pin_4|*/GPIO_Pin_5 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
//  RCC_ADCCLKConfig(RCC_PCLK2_Div2); 
  ADC_DeInit(ADC1);

  ADC_InitStructure.ADC_ScanConvMode = ENABLE; // tarama modu açık
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; 
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 2; // 
  ADC_Init(ADC1, &ADC_InitStructure);

    adc_channel_config();
    ADC_DMACmd(ADC1,ENABLE);
  ADC_Cmd(ADC1, ENABLE); 

  ADC_ResetCalibration(ADC1);
  while(ADC_GetResetCalibrationStatus(ADC1));

  ADC_StartCalibration(ADC1);
  while(ADC_GetCalibrationStatus(ADC1));
      
}


void ADC1_DMAConfig(void){
DMA_InitTypeDef DMA_InitStructure;

  DMA_Cmd(DMA1_Channel1,DISABLE);
  DMA_DeInit ( DMA1_Channel1);

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x4001244C; // ADC->DR Adresi
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) ADC_ValArray; // hedef adresimiz
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // ADC kaynak. Veri yönü ADC -> Hafıza 
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // ADC adresi sabit kalacak
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // Her değer alındığına memory adresi 1 artırılacak
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  // Kaynaktan alınacak veri 16 bit
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // Hedef büyüklüğü 16 bit
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //veri alındıktan sonra başa dönülecek.
  DMA_InitStructure.DMA_Priority = DMA_Priority_High ; // Kanal Önceliği yüksek. ( bu bize kalmış)
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // hafızadan hafızaya transfer kapalı. 
  DMA_InitStructure.DMA_BufferSize = 100; // 
  
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
  DMA_Cmd(DMA1_Channel1,ENABLE);

}


        if (GPIOB->IDR&GPIO_Pin_9) RAM[0]=0;else RAM[0]=1;
        if(RAM[0]&&!RAM[20])ADC_ExternalTrigConvCmd(ADC1, ENABLE);
        RAM[20]=RAM[0];

GreeN

  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;


Bu enable olmalı sanırım.


Terörü Lanetliyoruz.

magnetron

hocam onu ENABLE yapınca
bir kere start aldımı sürekli ADConversion yapıyor
--------------------------------------------------------
ST nin kendi STM32 formuna da sordum
o da TIM ile trigger et dedi


demekki benim istediğim gibi tamamen kendi kontrolümde ADC yi
start edemiyoruz




Mucit23

Yapacağın işlem şudur. Dedikleri gibi ADC'yi timer ile tetiklemen gerekiyor. ADC ve DMAyı 50 adet örnek alıp kesme oluşturacak şekilde kurmalısın. DMA TC kesmesi işini görür burada.


Ölçüm almak istediğinde Timeri çalıştıracaksın, DMA_TC kesmesi oluştuğunda Timeri Durduracaksın Tekrar örnek almak istediğinde sadece Timeri çalıştırman gerekecek.

magnetron

hocam SP Library deki örneği çalıştıramadım


F103 için Timer triggerli ADC+DMA çalışan kod örneği var mı paylaşabilecek ?


teşekkür

marecrisium

ADC Continuous modu Enable yapıp, DMA Transfer Complete İnterrupt ı aktif getirerek interrupt içinde bir sayıcı ile sayarak
istediğin kadar çevrim yapıldıktan sonra ADC yi Stop moduna alabilirsn.

GreeN

Terörü Lanetliyoruz.


magnetron

hatamı buldum
bu şekilde çalıştı

  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;


  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 1000;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

  TIM_CtrlPWMOutputs(TIM2, ENABLE);


yalnız gene istediğim gibi olmadı

TIM2 den tetikleniyor tamam ama tek bir ölçüm yapıyor
onu da osiloskopla bakınca DMA_TC kesmesi TIM2_CC2' den 4.6 uS uzakta
yani 12 MHZ ADC clock ve 28.5 clock sampling ile yaklaşık o değer çıkıyor

ben DMA bufferi tek kanal için 50 veriyorum oysa

  ADC_InitStructure.ADC_ScanConvMode = DISABLE ; 
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;//ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 2; 
  ADC_Init(ADC1, &ADC_InitStructure);


bu yukarda nasıl bir değişiklik yapmam gerek ?
1 kere tetik ile tek bir değil bir dizi ölçüm nasıl yaptırıcam ?

teşekkür

GreeN

#9
A15 ten her butona basıldığında 50 ornek alır ve durur.

#include "main.h"
#include "stm32f1xx_hal.h"

ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;


void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC1_Init(void);
static uint16_t adc_value[50];

int main(void)
{

  
  HAL_Init();

 
  SystemClock_Config();

 
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();

  
  while (1)
  {
 
  }
 

}
void DMA1_Channel1_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_adc1);
  HAL_ADC_Stop_DMA(&hadc1);
}


void EXTI15_10_IRQHandler(void)
{
 
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15);
  HAL_ADC_Start(&hadc1);
  HAL_ADC_Start_DMA(&hadc1,(uint32_t*)adc_value,50); //50 ornek alıyoruz
}


Konfigrasyon kısmı ;

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInit;

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

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

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time 
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* ADC1 init function */
static void MX_ADC1_Init(void)
{

  ADC_ChannelConfTypeDef sConfig;

    /**Common config 
    */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure Regular Channel 
    */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

}

/** Configure pins as 
        * Analog 
        * Input 
        * Output
        * EVENT_OUT
        * EXTI
*/
static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);

  /*Configure GPIO pin : PC13 */
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PA15 */
  GPIO_InitStruct.Pin = GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
void _Error_Handler(char * file, int line)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  while(1) 
  {
  }
  /* USER CODE END Error_Handler_Debug */ 
}

#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */

}

#endif

/**
  * @}
  */ 

/**
  * @}
*/ 

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Terörü Lanetliyoruz.