STM32 – Register ile ADC
Herkese merhabalar , bu bloğumuzda Regsiter ile nasıl ADC sürülür onu göreceğiz.
Bu bloğk’da Registerları kullandık fakat and(&) ,or(|) veya kaydırma(<<,>>) bitlerini kullanmadık bunun yerine Registerları Hexdecimal atamalar ile kullandık.
PA0 pinine bir potansiyometre bağlayın ve aşağıdaki kodları inceleyin , yazının sonunda tüm kodlar bir verilecektir.
İlk olarak dökümanda bize verilen diagram bilgisine bakalım . Aşağıdaki diagramın kısaca bir özeti;
-ADC Clock Aktif
-ADON Aktif
-SWSTART Aktif, ADC okuma başlatıldı
-Okumadan 1 cycle kadar sonra ADC CONVERSION işlemi başladı
-ADC Conversion işlemi bitikten hemen sonra EOC başlıyor.

1- Kütüphane ekleyerek başlıyoruz.
#include "stm32f4xx.h"
2- Debug ekranında okumak için bir değişken oluşturuyoruz. Okuyacağımız değer 12 bit bunun için değişkenimizi 16 bitlik seçtik.
uint16_t adc_value;
3- void RCC_Config(void) adında bir değişken oluşturuyoruz ve içerisini kodluyoruz. Bu işlemi daha önceki yazılarımda ayrıntılı anlatım
[button text=”Tıkla ve git” new_tab=”yes” size=”small” icon=”” url=”https://samettasoglu.com/2023/03/14/stm32f407vg-register-ile-system-clock-ayari/”]
4- GPIO_Config(void) adında bir değişken oluşturuyoruz ve içerisini GPIO ile ilgili işlemleri kodluyoruz.
a) RCC->AHB1ENR |= 0x00000001;
Bu kod, GPIOA portunun Saatini (Clock) Aktif edecek.
b) GPIOA->MODER |= 0x00000003;
Bu kod, A portunu 0. Pinini seçip Analog Giriş olarak ayarlar.
c) GPIOA->OSPEEDR |= 0x000000003;
Bu kod, PA0 Pininin Hızını ayarlar , Biz burda “very high / 100Mhz” olarak ayarladık.
5- void ADC_Config(void) adında bir değişken oluşturuyoruz ve içerisini ADC ile ilgili işlemleri kodluyoruz.
a) RCC->APB2ENR |= 0x00000100;
Bu kod, ADC1 Saatini (Clock) aktif eder.
b) ADC1->CR1 |= 0x00000000;
Bu kod, Okuma işleminin kaç Çözünürlükte olduğunu belirler , biz burda 12 bit olarak belirledik.
c) ADC1->CR2 |= 0x00000001;
Bu kod, ADC1 ‘i Açar ” ADC = ON ”
d) ADC2->SMPR2 |= 0x00000004;
Bu kod, Sample Tıme /Örnekleme değerini ayarlar biz burda 84 Cycle olarak ayarladık.Burda Cycle yükseltilirse daha kaliteli işlemler yapılabilir.
e) ADC->CCR |= 0x00010000;
Bu kod, Sistemizde bulunan 168Mhz frekans sinyali APB2 Faz hatına 84 Mhz frekans verir biz bu 84 Mhz uygun değerlere bözler ve ADC kanalarına dağıtırız. Dökümanın bize söylediği değer Max 36 Mhz ‘dir. O halde bizde bu 84Mhz sinyali böleriz. Biz burda 4ê böldük yani “Div4” işlemine tabi tutuk. 84/4 = 21 , 21Mhz lik frekans sinyali ile ADC’yi besleyeceğiz. (Burdaki 84 sayısının ukardaki Cycle ile bir alakası yok.)
6- uint16_t Read_ADC() adında bir fonksiyon oluşturuyoruz. Bu fonksiyon ADC den gelen değerleri okumak için işlemlerin yapıldığı fonksiyon.
a) uint16_t value;
Bu kod, değer döndürmek için tanımlanan bir değişken.
b) ADC1->CR2 |= 0x40000000;
Bu kod, ADC okuma işlemini başlatıyor. (For Regular Channels)
c) while(!(ADC1->SR & 0x00000002));
Bu kod, EOC Bayrağı kalkana kadar bekler.
d) value = ADC1->DR;
Bu kod, Data Registar’ından bilgiyi al ve değişkene yolla.
e) return value;
Bu kod, değikeni dışarıya döndür.
7- En sonunda int main() içerisinde tüm fonksiyonları çağırıyoruz fakat Read_ADC() fonksiyonunu while(1) içerisinde çağırıyoruz çünkü sürekli olarak ADC okuması yapmamız lazım.
int main(void) {
RCC_Config();
GPIO_Config();
ADC_Config();
while (1) {
adc_value = Read_ADC();
}
}
Tüm Kod:
#include “stm32f4xx.h”
uint16_t adc_value;
void RCC_Config(void) {
RCC->CR &= ~(1 << 0);
RCC->CR |= (1 << 16);
while (!(RCC->CR & (1 << 17)))
;
RCC->CR |= (1 << 19);
//———————————
RCC->PLLCFGR = 0;
RCC->PLLCFGR |= (1 << 22);
RCC->PLLCFGR |= (1 << 2);
RCC->PLLCFGR |= (168 << 6);
RCC->PLLCFGR |= (0 << 24);
RCC->CR |= (1 << 24);
while ((RCC->CR & (1 << 25)) == 0)
;
RCC->CFGR &= ~(3 << 0);
RCC->CFGR &= ~(0xF << 4);
RCC->CFGR |= (101 << 10);
RCC->CFGR |= (100 << 13);
//———————————
RCC->CIR |= (1 << 19);
RCC->CIR |= (1 << 20);
//———————————
}
void GPIO_Config(void){
RCC->AHB1ENR |= 0x00000001; // GPIO A Port Clock Enable
GPIOA->MODER |= 0x00000003; // A Portu Analog Giriş Olarak ayarladık
GPIOA->OSPEEDR |= 0x000000003; // Hızını “Very high” olarak ayarladık
}
void ADC_Config(void){
RCC->APB2ENR |= 0x00000100; // ADC1 Clock Enable
ADC1->CR1 |= 0x00000000; // 12 bit solution(çözünürlülük)
ADC1->CR2 |= 0x00000001; // ADC On
ADC2->SMPR2 |= 0x00000004; // Sample time değerini 84 cycle olarak ayarlandı “100”
ADC->CCR |= 0x00010000; // Div4 (84 /4)
}
uint16_t Read_ADC(){
uint16_t value;
ADC1->CR2 |= 0x40000000; // SWSTART(30.bit) Enable
while(!(ADC1->SR & 0x00000002)); // EOC Bayrağı kalkana kadar bekler
value = ADC1->DR; // Data Registerındaki bilgiyi al ve değişkene ata
return value;
}
int main(void) {
RCC_Config();
GPIO_Config();
ADC_Config();
while (1) {
adc_value = Read_ADC();
}
}













