Örnek:STM32 ST_Lib ADC + DMA (Çok kanal)

Başlatan Klein, 18 Kasım 2012, 23:08:00

Klein

DMA ayarla,
ADC çalıştır
çevirimi başlat. bu sıralamaya dikkat ettin mi?.

magnetron

hocam merhaba,
sizin örneğinizdeki ADC DMA çalıştırdım ( işlemcim STM32F103 )
2 kanal ADC ölçüyorum
potans bağladım ama sanki ADC girişleri floating bırakmışım gibi ikisinde de 2000 değeri etrafında oynayan bir değer alıyorum

değiştirdiğim yerler şunlar

main{} başında 
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

    adc_channel_config();
    init_adc1();
    ADC1_DMAConfig();
    ADC_DMACmd(ADC1,ENABLE);
    ADC_SoftwareStartConvCmd(ADC1,ENABLE); // çevirimi başlatıyoruz.
********
    ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_28Cycles5);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 2, ADC_SampleTime_28Cycles5); 
********
  DMA_InitStructure.DMA_BufferSize = 2; // Alacağımız verisayısı 8 ( 8 kanal adc okuyacağız) 
********
  ADC_InitStructure.ADC_NbrOfChannel = 2; // sekiz kanal tarayacağız.
********
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
********
main döngü içinde kendi değişkenime aktarıyorum
        uint16_t *RAMptr=&RAM[PARAMETERS+100*2];
        *RAMptr=ADC_ValArray[0];
********


GPIO clockları da açtım
sorun nerde olabilir ? teşekkür

Klein

Yaptığınız değişikliklerde bir sorun göremedim.  çalışmaması için bir sebep görünmüyor.
Ölçüm sonucunun  Tam skala / 2 gibi bir değer gösteriyor olmasından bir şeyler çıkarabilir miyim diye bakındım , çıkaramadım.
Donanım sorunu olabileceğinden kuşkuluyum.  Girişi VCC ve GND'ye çekip sonucu yazar mısınız?
Bir de AVDD ve AVSS bağlantılarında bir sorun olup olmadığını gözden geçirirseniz iyi olur.

ea

Merhaba. Bu ölçüm değerlerinin 2000 civarında olması benimde başıma geldi stm32f0 da adc girişlerine pot bağladım potu cevirsemde değişmedi fakat potun bi ucunu + ya orta ucu da pine bağlamıştım daha sonra boşta olan ucu gnd ye bağlayınca duzeldi.Bu ara da benimde bir sorum olacak. daha once dma ile adc cok detaylı kullanmadım ama  su anda 4 kanaldan veriyi dma ile okuyup dizye yazıyorum.cevrim sonunda degerleri görüyorum fakat ben diyelim ki kanallardan 10 ar tane örnek alsın ve dma sırasısı ile dizi adreslerini artırarak toplamda 40 adet adc ölcümünü dizide bulundursun istiyorum. bunu dma ile yapabilir miyim.. teşekkürler.
www.gstelektronik.com.tr  |  www.inohom.com

Klein

Yaparsınız fakat veriler sıralı olmaz.  Dizideki sıralama şu şekilde olur
Kanal 0 1. örnek
Kanal 1 1. örnek
Kanal 2 1. örnek
Kanal 3 1. örnek
..
..
..
..
Kanal 0 10. örnek
Kanal 1 10. örnek
Kanal 2 10. örnek
Kanal 3 10. örnek

Bu şekilde olması işinizi görüyorsa, dizi boyunu kanal sayısı*örnek sayısı olarak ayarlayıp , DMA'ya da bu boyu verirseniz olur.

magnetron

Klein hocam merhaba ,

dma ile ölçüm yaparken

benim verdiğim komutla başlamasını
ve diyelim 100 örnek aldıktan sonra durup interrupt vermesini nasıl sağlarım ?

teşekkür


usahin

Hocam Selamlar,

stm32f103cbt6  mikrodenetleyicisini kullanıyorum. Yazılımı denediğimde tüm kanallarda birinci kanalın değerini görüyorum. Diğer kanallar boşta değil. Bazılarını GND'ye çektim bir kaçına da pot bağladım. Biraz kurcaladım ama bir şey çıkaramadım. Sorun ne olabilir ?

Klein

@magnetron.
ContiniousConversion yerine SingleConversion seç.
DMA  veriuzunluğunu 100 seç. 
çevirim  zaten senin komutunla başlıyor.

ADC_SoftwareStartConvCmd(ADC1,ENABLE);


@usahin
aşağıdaki bölümleri bir kontrol et. Taranacak kanal sayısını yanlış girmiş oılabilirsin. Veya kanalk konfigürasyonunda hata olabilir.

ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_28Cycles);
...
...
ADC_RegularChannelConfig(ADC1, ADC_Channel_n, 8, ADC_SampleTime_28Cycles);

ADC_InitStructure.ADC_NbrOfChannel = 8; // sekiz kanal tarayacağız.

usahin

Klein Hocam,

Geri dönüşünüz için teşekkürler, yazılımı register seviyesinde kendim yazmayı denemiştim çalışmayınca sizin örneği birebir kopyaladım derledim ancak bahsettiğim gibi bir sorun oluştu. Buffer boyutundan bağımsız tüm kanallarda +-2(4096 üzerinden) ilk kanalın değeri görünüyor o da gürültüdendir diye düşündüm.

usahin

Sorunu çözdüm, bir başka arkadaşın da başına gelirse izlediğim adımlar aşağıda :

Sistem Clock'unu 72MHz'e ayarladım.
ADC Prescaler 6
Çevrim zamanı 28.5 saykıl.
Çevrim başlangıcını T1 CC1 event tetiklemeli olarak yaptım.

Zamanlamayla ilgili bir sıkıntı vardı sanırım. Şu an sorunsuz bir şekilde 64 verilik buffer ile 8 kanal okuyorum.

magnetron

#40
Klein hocam merhaba ,

DMA ile ölçüm yaparken

benim verdiğim komutla başlamasını anladım ( yukarda verdiğiniz cevap )
ama diyelim 100 örnek aldıktan sonra durup interrupt vermesini nasıl sağlarım ?

teşekkür

skara1214

Alıntı yapılan: magnetron - 17 Eylül 2016, 16:24:28
Klein hocam merhaba ,

DMA ile ölçüm yaparken

benim verdiğim komutla başlamasını anladım ( yukarda verdiğiniz cevap )
ama diyelim 100 örnek aldıktan sonra durup interrupt vermesini nasıl sağlarım ?

teşekkür
sağlayamazsın.  her iş bitişte dma bitti interruptina girip 1 artırdıktan sonra  100 sefer işlem yapacaksın. Ama 100 seferde interrupta gir diye bir şey yok
Herkes ölür ama herkes gerçekten yaşamaz

Mucit23

Bildiğim kadarıyla dma buffer boyutu kadar veriyi aktardiktan kesme oluşturur. Buna dma transfer complete kesmesi deniyor. Buffer boyutu 100 ise dma 100 kez tetiklendikden sonra kesme oluşturur.  Birde half transfer complete var oda buffer boyutunun yarısına ulaştığında kesme olusturuyordu yanılmıyorsam.

Eğer her bir transfer işleminde kesme oluşturulması isteniyorsa kesme vektörü dma yı tetikleyen donanıma bağlanır.

skara1214

Alıntı yapılan: Mucit23 - 17 Eylül 2016, 20:53:01
Bildiğim kadarıyla dma buffer boyutu kadar veriyi aktardiktan kesme oluşturur. Buna dma transfer complete kesmesi deniyor. Buffer boyutu 100 ise dma 100 kez tetiklendikden sonra kesme oluşturur.  Birde half transfer complete var oda buffer boyutunun yarısına ulaştığında kesme olusturuyordu yanılmıyorsam.

Eğer her bir transfer işleminde kesme oluşturulması isteniyorsa kesme vektörü dma yı tetikleyen donanıma bağlanır.
hocam sizin dediğinizde 1 kanalı 100 kere taşıdıktan sonra interrupt oluştur demektir. arkadaş 5(temsili multikanal) kanalı 100 kere çevirdikten sonra  interrupta girmek istiyor.yani dma  işini 100 kere bitirip yeniden başlatması gerekiyor.Öyle bir opsiyonun olduğunu zannetmiyorum.
Herkes ölür ama herkes gerçekten yaşamaz

magnetron

hocam tek kanal

100 kere ölçüm yapılacak

yani  DMA_InitStructure.DMA_BufferSize = 100;

bitince ADC duracak interrupt verecek

interrupt nasıl kuracağım ? kod örneği verebilir misiniz ?