STM32F103 ADC DMA Interrupt Problemi

Başlatan kimlenbu, 22 Haziran 2020, 12:56:57

kimlenbu

Selamlar,

Fırçalı DC Motor sürücüsü kartımda ADC'den bazen hatalı veri okunduğu için Circular modda işi DMA'ya pasladım, DMA Transfer Complete Interruptı ile bütün ADC değerleri tanımladığım diziye atılınca da okuma gerçekleştirdim.

Eskiden çalışan program çakıldı kaldı, bazen 3-5dk sıkıntısız çalışıyor ama sonra mcu bütün peripheralları kapatıyor, gpio'ların kontrolünü kaybediyor, timer kontrollerini kaybediyor ve belirsiz bir durumda kalıyor. Debug için kullandığım usart devre dışı kalıyor.

HardFault,BusFault, UsageFault interruptlarına kontroller koydum, oralarda bir sıkıntı görünmüyor.

SWD ile debug edemiyorum, gürültü yüzünden keil'de debugger kısa süre sonra iletişim hatası verip debug modunu kapatıyor.

Fault Reports penceresini aktif ettiğimde ise binbir tane hata flag'ı set edilmiş durumda görünüyor. DMA interruptını devre dışı bıraktım, program çakılmıyor ama nedir bu sıkıntıların sebebi ?



void ADC1_Conf(void){
	
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
	
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //clock for ADC (max 14MHz, 72/6=12MHz)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //Enable ADC clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //Enable GPIOA Clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //Enable GPIOB Clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //Enable DMA1 Clock

//GPIO configuration	
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);

//ADC1 configuration
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel  = 6;
ADC_Init(ADC1, &ADC_InitStructure);


//  /* NVIC configuration ------------------------------------------------------*/
//  /* Configure and enable ADC interrupt */
//  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
//  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x09;
//  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x09;
//  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//  NVIC_Init(&NVIC_InitStructure);
	
// DMA1 channel1 configuration ----------------------------------------------
DMA_Cmd(DMA1_Channel1, DISABLE);
DMA_DeInit(DMA1_Channel1);

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_DualConvertedValueTab;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; 
DMA_InitStructure.DMA_BufferSize = 6;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; /
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; // 32bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; // 32bit
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low; //DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
//DMA_ITConfig(DMA1_Channel1,DMA1_IT_TC1,ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE); // Enable DMA1 Channel1

ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5); //NTC   //ADC_SampleTime_1Cycles5
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5); //GERI MAX
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_239Cycles5); //ILERI IVME
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_239Cycles5); //GERI IVME
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5, ADC_SampleTime_239Cycles5); //POT
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 6, ADC_SampleTime_239Cycles5); //ACS758
ADC_DMACmd(ADC1, ENABLE);


//ADC Enable
ADC_Cmd(ADC1, ENABLE);

//Calibrate ADC
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	
}


yldzelektronik

Ben olsam, DMA yı ADC başlatıldıktan sonra aktif ederdim. DMA nın veriyi yazdığı değişkenin türü nedir? 32bit değilse sorunun kaynağı olabilir.

Eğer elektromanyetik gürültü kaynaklı ise, benzeri bir sorun yaşamıştım. Dahili flashtaki verilerin değiştiğine bile şahit oldum.

Beslemenin önüne güzel bir filtre, sağlam topraklama sonrasında hiçbir şey kalmadı.
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

kimlenbu

#2
Alıntı yapılan: yldzelektronik - 22 Haziran 2020, 13:57:30Ben olsam, DMA yı ADC başlatıldıktan sonra aktif ederdim. DMA nın veriyi yazdığı değişkenin türü nedir? 32bit değilse sorunun kaynağı olabilir.

Eğer elektromanyetik gürültü kaynaklı ise, benzeri bir sorun yaşamıştım. Dahili flashtaki verilerin değiştiğine bile şahit oldum.

Beslemenin önüne güzel bir filtre, sağlam topraklama sonrasında hiçbir şey kalmadı.

değişken de 32bit, benim korkum da sıkıntıların gürültü kaynaklası olması zaten. Kart üzerindeki trimpotları opamp voltage follower kullanmadan adc'ye girmiştim. Analog/dijital ne kadar giriş çıkış varsa her şeyi izole etmek gerekiyormuş onu gördüm. DMA interruptını devre dışı bırakıp kartı yük altında teste aldım, bana mısın demedi, sıkıntısız çalışıyor. DMA interruptı açıkken kısa sürede kart kararsız hale geçiyor.

RaMu

Stack ve heap için ayrılan alan hatalı olabilir.
Biraz daha büyük alan ayarlayıp deneyebilirsin.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

kimlenbu

Alıntı yapılan: RaMu - 22 Haziran 2020, 14:54:40Stack ve heap için ayrılan alan hatalı olabilir.
Biraz daha büyük alan ayarlayıp deneyebilirsin.

Onu da denedim, ram'i aşmayacak şekilde 2 katına çıkardım, bir değişiklik olmadı.

yldzelektronik

Hocam eğer bir yerde memory leak varsa sonsuza da çıkarsanız sorun devam eder. Öncelikle bellek sızıntısı olmadığını doğrulamanız gerekiyor.

Alakası olmayabilir ama daha evvel at parser yazarken parser debugger da şöyle bir hata yapmışım, yerli yersiz hatalar oluşuyordu:

#if DEBUG == 1
char msg[32];
strcpy(msg, buffer);
print(msg);
#endif

Bu haliyle çoğu zaman sorunsuz çalışırdı.Ancak bazen gelen cevap uzun oluyor ve alakasız sorunlar oluşuyordu. Ve bu sorunun kaynağını bulmak sanırım 1 haftamı almıştı.

Benzeri bir şeyi gözden kaçırmış olabilirsiniz. O hatayı bulana kadar byte byte her taskın stack alanına bakmıştım.

Anladığım kadarıyla sizin kesmeyi açmanızla birlikte tetiklenen bir durum var.
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.