Picproje Elektronik Sitesi

MİKRODENETLEYİCİLER => ARM => Cortex ARM => Konuyu başlatan: Enginar - 08 Mart 2013, 14:43:46

Başlık: Stm32f4 ADC problemi
Gönderen: Enginar - 08 Mart 2013, 14:43:46
Basit bir ADC uygulaması yapmaya çalışıyorum kodlarım şu şekilde

#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_tim.h"
#include "misc.h"
#include "stm32f4xx_flash.h"
#include "stm32f4xx_adc.h"

uint16_t adc_val[2];
uint8_t ch_index =0;



/*void SystemLibInits()
{

RCC_DeInit();

RCC_HSEConfig(RCC_HSE_ON);
while(RCC_WaitForHSEStartUp()!=SUCCESS)
RCC_PLLConfig(RCC_PLLSource_HSE,4,168,2,7);
RCC_PLLCmd(ENABLE);
FLASH_SetLatency(FLASH_Latency_5);
FLASH_PrefetchBufferCmd(ENABLE);
FLASH_DataCacheCmd(ENABLE);
FLASH_InstructionCacheCmd(ENABLE);

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(0x08!=RCC_GetSYSCLKSource());


} */

void SystemInits()
{
unsigned int i;
    for (i=0;i<0x00100000;i++);          // OSC oturtma ve kurtarma rutini
    RCC->CFGR |= 0x00009400;         // AHB ve APB hizlarini max degerlere set edelim
    RCC->CR |= 0x00010000;            // HSE Xtal osc calismaya baslasin
    while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
    RCC->PLLCFGR = 0x07405408;      // PLL katsayilarini M=8, N=336, P=2 ve Q=7 yapalim
//  RCC->PLLCFGR = 0x07402A04;     // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
    RCC->CR |= 0x01000000;            // PLL calismaya baslasin  (Rehber Sayfa 95)
    while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
//  FLASH->ACR = 0x00000705;        // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
    FLASH->ACR = 0x00000605;        // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
    RCC->CFGR |= 0x00000002;        // Sistem Clk u PLL uzerinden besleyelim
    while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle

}

/*********************************ADC KESME **********************************************************/

void ADC_IRQHandler()
{
if (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==SET) {
ADC_ClearFlag(ADC1,ADC_FLAG_EOC);
adc_val[ch_index]=ADC_GetConversionValue(ADC1);
ch_index++;
if (ch_index>1) {
ch_index=0;
}

}
}

/************************************************************************************************/
void GPIOD_Inits()
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);

GPIO_InitTypeDef GPIO_InitStructure ;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT ;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Pin=(GPIO_Pin_15 | GPIO_Pin_14 | GPIO_Pin_13 | GPIO_Pin_12);
GPIO_Init(GPIOD, &GPIO_InitStructure);


}


void rcc_gpio_config()
{

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);

GPIO_InitTypeDef GPIO_B_InitStructure ;

GPIO_B_InitStructure.GPIO_Mode=GPIO_Mode_AN;               // Anolog input
GPIO_B_InitStructure.GPIO_Pin=(GPIO_Pin_0 | GPIO_Pin_1);   //PB0 PB1
GPIO_B_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_B_InitStructure);


}
void ADC1_Inits()
{

    ADC_InitTypeDef ADC_InitStructure ;
    ADC_CommonInitTypeDef ADC_CommonStructure;

    ADC_CommonStructure.ADC_Mode=ADC_Mode_Independent;
    ADC_CommonStructure.ADC_Prescaler=ADC_Prescaler_Div4;
    ADC_CommonStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;
    ADC_CommonInit(&ADC_CommonStructure);


    ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;
    ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;
    ADC_InitStructure.ADC_ScanConvMode=ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;
    ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion=2;
    ADC_Init(ADC1,&ADC_InitStructure);

    ADC_RegularChannelConfig(ADC1,ADC_Channel_8,1,ADC_SampleTime_480Cycles); //PBO
    ADC_RegularChannelConfig(ADC1,ADC_Channel_9,2,ADC_SampleTime_480Cycles); //PB1

    ADC_Cmd(ADC1,ENABLE);
    ADC_EOCOnEachRegularChannelCmd(ADC1,ENABLE);
    ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);

}

void NVIC_Inits()
{
NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel=ADC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);

}


int main()
{

SystemInits();
GPIOD_Inits();
NVIC_Inits();
rcc_gpio_config();
ADC1_Inits();


ADC_SoftwareStartConv(ADC1);

while(1)
      {

if (adc_val[0]>1500) {
GPIO_SetBits(GPIOD,GPIO_Pin_15);
}
else {
GPIO_ResetBits(GPIOD,GPIO_Pin_15);
}

      }

}





2 kanalın verilerini okumaya çalışıyorum ama overrun bayrağı set oluyo veriyi kaybediyorum ve program kesmeye girmiyo.Bu problemi nasıl aşabilirim ?
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: muhittin_kaplan - 09 Mart 2013, 12:14:16
Hocam şuraya Açıklık Getirirmisiniz
İki ADC yimi kullanmak istiyorsunuz 2 PIN (PB0 ve PB1)den okumamı yapmak istiyorsunuz.
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: Enginar - 09 Mart 2013, 13:07:40
Evet 2 çevrim yapmak istiyorum while içinde bi tanesini okuduğuma bakmayın hocam debugdan gözlemliyorum 2 kanalıda ayrı çıkışlara bağlayıp.Sorunum çevrim yaparken overrun flagının set olması  ???
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: muhittin_kaplan - 09 Mart 2013, 14:35:27
Hocam Malum üç adet ADC modülü var. siz her bir pini bu ADC modüllerine bağlamışsınız.
Hiç 2. Modülü kullanmadım. Bir Modülde 2 kanal kullandım.


Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: Enginar - 09 Mart 2013, 15:06:54
Evet hocam ADC1 modülünü kullanıyorum sadece .2 kanal tarayacağım ADC1 üzerinden scan ve continious conversion modda.Klein hocanın yaptığı örnekten yola cıktım. swstart bitini 1 yaptıktan sonra kesme geldikçe taranan kanalları adc_val dizisinde saklayacağım .kesme olmadan yaptım sıkıntı yok ama bu şekilde denediğimde veriyi okuyamadan program çakılıyo :-\

Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: Klein - 09 Mart 2013, 17:22:02
2 kanal continious modda kesme olmadan okuyamazsın. Daha ilk çevirimin verisini okumadan ikinci çevirimin verisi gelir Overrun bayrağı çekilir.

Interrup  pending bitini temizlemeyi dener misin?
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: Enginar - 09 Mart 2013, 20:37:41
Evet o biti temizleyince stabil çalıştı program hocam teşekkür ederim.Sonradan o satırı kaldırıp derledim gene çalıştı :) garip :) Bu bitin görevi tam olarak nedir hocam ? anladığım kadarıyla kesme bekleyen biti temizlemek için kullanılıyo. mesela ovr set oldu ama kesmesi acık değil bu yüzden kesmeye gidemiyo bu biti temizlemek için kullanılıyo ?
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: Klein - 09 Mart 2013, 21:00:04
Evet kesme bayrağını temizliyor.
Benim önerim ADC'yi DMA ile kullanman yönünde olur.
ADC çok hızlı örneklediği için, program büyüyünce ADC kesmesini işletmekten,  programı işletmeye zaman bulamıyosun. 
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: muhittin_kaplan - 09 Mart 2013, 21:08:40
Burada benimde takıldığım noktalar var.

407 için konuşursam. 3 adet ADC modülü var neden ?
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: Klein - 09 Mart 2013, 21:22:08
Her ADC'nin birden fazla kanalı var. Ancak bu kanalların hepsini aynı anda okuyamıyoruz. Belirli bir sıra ile peş peşe okuyabiliyoruz. Bu bir çok uygulama için yeterli. 
Ama düşün ki 3 fazlı bir sürücü yapıyorsun  eş zamanlı olarak tüm fazların akım veya voltaj bilgisine ihtiyacın var. Eğer tek ADC olursa kanalları sırasıyla okuyacaksın ve aldığın bilgiler eş zamanlı olmayacak. Bu da veriyi işlemenive kontrolünü zorlaştıracak.
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: muhittin_kaplan - 09 Mart 2013, 21:23:37
Anladım. Eş Zamanlı Okuma Yapacağımızda Kullanabiliriz.

Hocam Yoruyorum Ama

Şu Modlardan Bahsedebilirmisiniz Biraz. Odc Okuma Modları.
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: Klein - 09 Mart 2013, 21:50:09
Single conversion, continious conversion , scan mod ve discontinious olmak üzere 4 çevirim modu var.

Scan modunda  iken:
çevirimi başlattığınızda ADC_SQRx  registeri ile bildirdiğiniz sayıda kanalı , aynı register ile bildirdiğiniz sırada tarıyor. her çevirimden sonra değeri registere atıyor ve conversion tamam bayrağını çekiyor. Tüm kanallar taranana kadar işlem böyle devam ediyor.
Tüm kanallar bittikten sonra, eğer Single conversion modundaysak duruyor. Takrar için yeniden çevirim başlatmamız gerekiyor. Continious conversion modundaysak, bizim yeniden çevirimi başlatmamıza gerek olmadan , çevirim kendi kendine yeniden başlıyor.

Scan modunda değilsek :
ADC_SQRx registerinde seçilmiş ilk kanal hangisi ise o kanalın verisinialıyoruz. Başka bir kanal seçeceksek, conversion bittikten sonra ADC_SQRx registerine Her zaman aynı kanalın bilgisini kesintisiz olarak alıyoruz. Continious modda iken kanal değiştirmek istersek, çevirim bittikten sonra, çevirimi durdurup kanal değiştiriyoruz. Çevirimi tekrar başlatıyoruz.


Discontinious mod scan modu gibi. Ancak biraz farklı. Yine tarama yapılıyor. Ancak tarama alt guruplara bölünüyor.
Diyelim ki   sıralamamız 1,3,2,7,9,4,2,5,8,10,11,5,6,9
taranacak kanal sayısı 4:
ADC_CR1 ->DISCNUM registerinden çevirimi her başlatmada kaç kanal taranacağını bildiriyoruz.
Örneğin bu değerimiz 2 olsun.
çevirimi başlattığımızda ilk iki kanal (1,3) taranıyor.
çevirimi tekrar başlattığımızda  ikinci iki kanal (2,7)
bir sonraki çevirimde (9,4)
bir sonrakinde (2,5)
kanallar taranıyor.
ADC_SQRx registerinde tarama sayısına 4 verdiğimiz için. 4. taramanın sonunda EOC(End of conversion) bayrağı kaldırılır.
Çevirimi tekrar başlattığımızda yine ilk sıradan çevirime başlar.

Bu modda çevirimi elle mi başlatıyoruz, başka kaynaklardan mı başlatmak gerekiyor tam emin değilim. Muhtemelen DMA gibi tetikleyiciler tarafından başlatılan çevirimleri için düşünülmüş bir özellik.
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: EMP_Otto - 19 Temmuz 2013, 11:25:05
Merhabalar ADC ile benimde bir sorum olacak :)
Vref+ ve Vref- voltajları ne acaba?Yani kaç volt.Bir türlü bulamadım :(
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: EMP_Otto - 22 Temmuz 2013, 19:42:25
Ben sordum cevabınıda ben veriyim.
Hard dökümanı sayfa 63(hard dokumanı:Doc ID 022152 Rev 2)
Vref+  Vdd ye Vref- de Vss ye bağlı.Vdd=3.3 V Vss=0 :)
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: camby - 22 Temmuz 2013, 20:32:08
Daha doğrusu küçük kılıflarda dışarı çıkarmıyorlar , direk beslemelere bağlıyorlar. Büyük paketlerde ise dışarı çıkıyor. Şöyle de bir sonuç çıkıyor aslında , vref kullanmak istiyorsak büyük paket kullanmak zorundayız.
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: muhittin_kaplan - 23 Temmuz 2013, 01:12:49
@EMP_Otto
Kavram Kargaşası Yaşama, Muhtemelen Yanlış Anlıyorsun Konuyu
Vref+ ve Vref- ADC modülün çalışması için gerekli olan besleme uçları değildir

Herhangi bir ölçüm yapacağında bir referansın olması gerekir. Örneğin 100m Uzak yada 100m Yakın, Ne göre Uzak Neye Göre Yakın ?
Yada 100Derece neye göre 100Derece ? cevabı Suyun Donma Noktasına Göre Celcius dur. Bu tanım Referans Tanımdır.

şimdi ADC ölçmü yapacağız
1,25V neye göre 1,25V işte burada eğer "Besleme Gerilimine Göre" dersen Ona göre Ölçüm Yaparsın. Ama Yok Vref+ ve Vref- yi kullanırsan ona göre bir değer çıkar.
Eğer VDD VSS yi ref olarak alır ve sonuçta 2,15v görürsek,
Vref+ ya 1V luk bir gerilim verdiğimizde ölçeceğimiz değer 1,15 olur.
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: EMP_Otto - 23 Temmuz 2013, 13:48:57
@muhittin_kaplan
Açıklaman için cok sagol hocam.Kavram karmaşası yok çok şükür.ADC ye pic,msp430 ve arduinodan aşinalığım var :)
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: muhittin_kaplan - 23 Temmuz 2013, 13:50:24
Saygıyla.
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: EMP_Otto - 02 Ağustos 2013, 17:17:28
@Klein
Merhaba hocam.Aynı sorun bendede var sürekli overrun set oluyor.Tam olarak hangi interrupt bayrağını silmem gerekiyor acaba?
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: EMP_Otto - 03 Ağustos 2013, 09:48:29
Yok mu bir yardım edecek :D
Başlık: Ynt: Stm32f4 ADC problemi
Gönderen: Klein - 05 Ağustos 2013, 17:13:32
Alıntı yapılan: EMP_Otto - 02 Ağustos 2013, 17:17:28
@Klein
Merhaba hocam.Aynı sorun bendede var sürekli overrun set oluyor.Tam olarak hangi interrupt bayrağını silmem gerekiyor acaba?
overrun bayrağı çekiliyorsa, bir veriyi okumadan diğeri geliyordur.  Veriyi kesme içinde veya benim önerim DMA ile okuyun.
Eğer bunları yapmak istemiyorsanız, continious mode kullanmayın. Veriyi okuyun, diğer kanaı set edip çevirimi yeniden başlatın.