CooCox ile ADC ve PWM

timing_10[1]Bu yazıda uygulayacağımız programı, stm32vl kartını kullanacağız. Analog kanaldan ölçtüğümüz değer ile PWM duty değerini değiştirerek, karta bağlı olan ledlerin parlaklıklarını değiştireceğiz.
Önce ADC den bahsedelim. Stm32F100RB işlemcisi 16kanal ve 12bitlik Analog Digital Convertore sahip. İşlemci nin çeşitli portları adc olarak kullanabiliyoruz. Bu pinlerin neler olduğunu  dökümanınınTable 4. Low & medium-density STM32F100xx pin definitions Bölümünden ulaşabilirsiniz.

ADC yi kullanabilmek için kanalın belirlenmesi gerekir. Biz GPIOC.0 ı giriş olarak kullanacağız. Yukarıda bahsedilen tabloya bakacak olursanız bu pin ADCnin 10. kanalına denk geliyor. yani biz okumalarımızı 10. kanaldan yapacağız. Daha sonra ölçtüğümüz bu değeri Timer3 ile hazırlanmış olan 4 kalan PWM in 3 ve 4. kanallarına vererek (GPIOG.8 ve GPIOC.9) ledleri n parlaklığını ayarlayacağız.
önce sistemin saat sinyalini ayarlamamız gerekecek. bunun için daha önce kullandığımız fonksiyonu kullanabiliriz.

void SetSysClockTo24(void)
{
    int i;
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------------------*/
  /* RCC system reset(for debug purpose) */
    RCC_DeInit();                        /* Sistem reset Durumuna getiriliyor */
    RCC_HSEConfig(RCC_HSE_ON);            /* High Speed External OSC Çalıştırılıyor */
    for(i=0;i<0x000FFFF;i++);                /* HSE Stabil Olana Kadar Bekleniyor */
      FLASH_SetLatency(FLASH_Latency_0);    /* 0 wait state*/
    RCC_HCLKConfig(RCC_SYSCLK_Div1);     /* HCLK = SYSCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1);        /* PCLK2 = HCLK */
    RCC_PCLK1Config(RCC_HCLK_Div1);        /* PCLK1 = HCLK */
    /* PLLCLK = (8MHz/1) * 3 = 24 MHz */
    RCC_PREDIV1Config(RCC_PREDIV1_Source_HSE,RCC_PREDIV1_Div1); /* PLLDIV1 bölme yok */
    RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_3);            /* PLL_in * 3 */
    RCC_PLLCmd(ENABLE); /*Pll Açık */
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)  /* PLL Hazır olana kadar bekle */
    {
    }
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);            /*Sistem Clock için PLL seçildi*/
    while (RCC_GetSYSCLKSource() != 0x08)                 /* PLL sistem Clock u olarak çalışıncaya kadar bekle */
    {
    }
}

Burada Fazla söze gerekyok. Daha sonra ADC ölçümü için gerekli kodları yazıyoruz. Genelde Buarad açıklamaktansa kodların içerisinde açıklama yapmayı tercih ediyorum

void ADC_simple(void)
{
// ADC Pin Ayarlamaları
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//Pin0 seçilecek
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//Alternatif IN olarak düzenlenecek
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//Port 50Mhz de çalışacak
	GPIO_Init(GPIOC, &GPIO_InitStructure);// Yukardaki tümişlemler GPIOC için yapılacak.
	RCC_ADCCLKConfig (RCC_PCLK2_Div2);//ADC freq=PCLK/2 Maximum 12 Mhz olabilir.
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //ADC nin Clock u açık
//ADC tanımlamaları
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStructure.ADC_ScanConvMode = DISABLE; //Scan mod çalışmayacak
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;	// Devamlı mod çalışacak
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // Sonuç Sağa Yanaşık olacak
	ADC_InitStructure.ADC_NbrOfChannel = 10; // Yukardaki ayarlamalar Kanal 10 için yapılacak
	ADC_RegularChannelConfig(ADC1,ADC_Channel_10, 1,ADC_SampleTime_28Cycles5); //
	ADC_Init (ADC1, &ADC_InitStructure);	//set config of ADC1
	ADC_Cmd (ADC1,ENABLE);	//enable ADC1
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
        //AdcDegeri= (ADC_GetConversionValue(ADC1) ); // value from 0 to 4095 *(3.0/4095)
}

Şimdi ise Gerekli olan PWM ayarlamalarımızı yapalım.

void TIM_PWMOutput(void)
{
    PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; //sistem frekansına göre ön bölme işlemi yapalım
    /* Time base configuration */
    TIM_TimeBaseStructure.TIM_Period = 665;//Periyot belirleniyor
    TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;//Ön bölücü değeri
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;//
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//Timer Yukarı saysın
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);//Yukardaki ayarlamalar Timer3 için uygulansın
    /* PWM1 Kanal1 */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = CCR1_Val; //DUTY değeri buradanayarlanıyor
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
    /* PWM1 Kanal2 */
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
    TIM_OC2Init(TIM3, &TIM_OCInitStructure);
    TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
    /* PWM1 Kanal3 */
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
    TIM_OC3Init(TIM3, &TIM_OCInitStructure);
    TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
    /* PWM1 Kanal4 */
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
    TIM_OC4Init(TIM3, &TIM_OCInitStructure);
    TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM3, ENABLE);
    TIM_Cmd(TIM3, ENABLE);
    /***************************************************************************************************************************************************/
}

son olarak ana blogumuz olan main.c fonksiyonumuz.

int main(void)
{
	SetSysClockTo24();
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    /* GPIOA and GPIOB clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
                         RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
    /*GPIOB Configuration: TIM3 channel1, 2, 3 and 4 */
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);
    ADC_simple();
    while(1)
    {
		AdcDegeri= (ADC_GetConversionValue(ADC1) ); // 0-4095  arası okunan değeri gerilime çevirmek için (referans/4095) ile çarpılması gerekir.
		for (i=0;i<1000;i++); //bir müddet bekleyelim
		//CCR1_Val=AdcDegeri/6; //PWM kanal 0
		//CCR2_Val=AdcDegeri/6; //PWM kanal 1
		CCR3_Val=AdcDegeri/6;	//PWM Kanal 2 -PC8
		CCR4_Val=666-(AdcDegeri/6); // PWM kanal 3 PC9
    	TIM_PWMOutput();// Muhtemeldirki tüm ayarlamaları çağırmamak gerekir. ama deneme amaçlı yazıldığından pekte optimize sayılmaz.
    }
}

Programın tüm kodları için TIKLAYINIZ.
Herkese iyi çalışmalar.
 

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Google fotoğrafı

Google hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d blogcu bunu beğendi: