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ın, Table 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
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.