Arkadaşlar Merhaba,
Pic 18f4520 kullanarak 1Hz - 300kHz aralığında buton ile kontrol edebileceğim sabit %50 duty pwm sinyali üretmek istiyorum. Osilatör frekansım 20Mhz. CCS C de yazdığım programa göre buton ile artış azalış yaptığımda duty de değişmektedir. Bu istediğim frekans aralığını Pic ile yapmak mümkün müdür?
Herkese iyi çalışmalar.
#include <18f4520.h> // Kullanılacak denetleyicinin başlık dosyası tanıtılıyor.
// Denetleyici konfigürasyon ayarları
#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay (clock=20000000) // Gecikme fonksiyonu için kullanılacak osilatör frekansı belirtiliyor.
#use fast_io(a) //Port yönlendirme komutları A portu için geçerli
#use fast_io(c) //Port yönlendirme komutları C portu için geçerli
int i=125; // Tamsayı tipinde değişken tanımlanıyor
/********* ANA PROGRAM FONKSİYONU********/
void main ( )
{
setup_psp(PSP_DISABLED); // PSP birimi devre dışı
setup_spi(SPI_SS_DISABLED); // SPI birimi devre dışı
setup_timer_1(T1_DISABLED); // T1 zamanlayıcısı devre dışı
setup_adc_ports(NO_ANALOGS); // ANALOG giriş yok
setup_adc(ADC_OFF); // ADC birimi devre dışı
set_tris_a(0x03); // RA0 ve RA1 pinleri giriş
set_tris_c(0x00); // C portu komple çıkış
setup_ccp1(CCP_PWM); // CCP1 birimi PWM çıkışı için ayarlandı
setup_timer_2(T2_DIV_BY_1,i,1); // Timer2 ayarları yapılıyor
set_pwm1_duty(50); // PWM1 çıkışı görev saykılı belirleniyor
while(1) // Sonsuz döngü
{
if (input(pin_a0)) // Eğer RA0 girişine bağlı butona basılırsa
{
delay_ms(20); // Buton arkı önleme gecikmesi
while(input(pin_a0)); // Basılı butondan el çekile kadar bekle
i++; // i=i+1 anlamındadır.
if (i>254) // i değeri 250'dan büyükse i değeri 250 olsun
i=254;
setup_timer_2(T2_DIV_BY_1,i,1); // Timer2 ayarları yapılıyor
set_pwm1_duty(50); // PWM1 çıkışı görev saykılı belirleniyor
}
if (input(pin_a1)) // Eğer RA1 girişine bağlı butona basılırsa
{
delay_ms(20); // Buton arkı önleme gecikmesi
while(input(pin_a1)); // Basılı butondan el çekile kadar bekle
i--; // i=i-1 anlamındadır.
if (i<2) // i değeri 65'den küçük ise i değeri 65 olsun
i=2;
setup_timer_2(T2_DIV_BY_1,i,1); // Timer2 ayarları yapılıyor
set_pwm1_duty(50); // PWM1 çıkışı görev saykılı belirleniyor
}
}
}
set_pwm1_duty(50); deki 50 %50 değil.
onu set_pwm_duty((unsigned int)(i/2)); yapmalısın yani timerin sayacağı değer değiştiğinde duty değeri de değişmeli.
tam %50 istiyorsan i değeri çift sayı olmalı. i yi 2 şer artırıp azaltabilirsin.
#include <18f4520.h> // Kullanılacak denetleyicinin başlık dosyası tanıtılıyor.
// Denetleyici konfigürasyon ayarları
#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay (clock=20000000) // Gecikme fonksiyonu için kullanılacak osilatör frekansı belirtiliyor.
#use fast_io(a) //Port yönlendirme komutları A portu için geçerli
#use fast_io(c) //Port yönlendirme komutları C portu için geçerli
unsigned int i=120; // Tamsayı tipinde değişken tanımlanıyor
/********* ANA PROGRAM FONKSİYONU********/
void main ( )
{
setup_psp(PSP_DISABLED); // PSP birimi devre dışı
setup_spi(SPI_SS_DISABLED); // SPI birimi devre dışı
setup_timer_1(T1_DISABLED); // T1 zamanlayıcısı devre dışı
setup_adc_ports(NO_ANALOGS); // ANALOG giriş yok
setup_adc(ADC_OFF); // ADC birimi devre dışı
set_tris_a(0x03); // RA0 ve RA1 pinleri giriş
set_tris_c(0x00); // C portu komple çıkış
setup_ccp1(CCP_PWM); // CCP1 birimi PWM çıkışı için ayarlandı
setup_timer_2(T2_DIV_BY_1,i,1); // Timer2 ayarları yapılıyor
set_pwm1_duty((unsigned int)(i/2)); // PWM1 çıkışı görev saykılı belirleniyor
while(1) // Sonsuz döngü
{
if (input(pin_a0)) // Eğer RA0 girişine bağlı butona basılırsa
{
delay_ms(20); // Buton arkı önleme gecikmesi
while(input(pin_a0)); // Basılı butondan el çekile kadar bekle
i=i+2; // i=i+2 anlamındadır.
if (i>255) // i değeri 250'dan büyükse i değeri 250 olsun
i=255;
setup_timer_2(T2_DIV_BY_1,i,1); // Timer2 ayarları yapılıyor
}
if (input(pin_a1)) // Eğer RA1 girişine bağlı butona basılırsa
{
delay_ms(20); // Buton arkı önleme gecikmesi
while(input(pin_a1)); // Basılı butondan el çekile kadar bekle
i=i-2; // i=i-2 anlamındadır.
if (i<15) // i değeri 65'den küçük ise i değeri 65 olsun
i=15;
setup_timer_2(T2_DIV_BY_1,i,1); // Timer2 ayarları yapılıyor
}
}
}
değişiklikleri yaptım fakat i değeri 120 den başlatıp azalttığımda i=60 değerinde duty %100 oluyor. Aynı şekilde 120 de %50 olan duty değeri i değeri 255e doğru yaklaşınca duty %0 yaklaşmaktadır.
GÜNCEL!!!
CcsC ide nin help kısmına PWM yazıp,
çıkan başlıklardan "pwm_set_duty_percent" a bak.
#USE PWM(OUTPUT=PIN_C2, FREQUENCY=10kHz, DUTY=25)
pwm_set_duty_percent(500); //set PWM duty cycle to 50%
Bu komut ile:
0 verirsen %0,
1000 verirsen %100 duty olur.
Burada anlamadığım; pwm frekansı
mı ayarlanacak, yoksa belli bir
frekansda dalga oranı mı?
Olur mu kısmına bakmamıştım, onuda yazayım:
Alıntı YapEQUATION 15-1:
PWM Period = [(PR2) + 1] • 4 • TOSC •(TMR2 Prescale Value)
Tosc = 1 / [Kristal Frekansı]
20MHz kristal ile minimum 1.2kHz PWM üretebilirsin,
32768Hz lik saat kristali kullansan bile
minimum ancak 2Hz PWM frekansına düşebilirsin.
Alıntı yapılan: mehmet - 14 Şubat 2019, 23:58:23Burada anlamadığım; pwm frekansı
mı ayarlanacak, yoksa belli bir
frekansda dalga oranı mı?
Hocam şu şekilde Pwm duty sabit %50 olacak ben butonlarla frekansı azaltıp ya da artıracağım. Yukarıda da belirttiğim şekilde frekans değişiyor fakat duty de değişiyor, sabit kalmıyor.
http://eng-serve.com/pic/pwm_functions.html
Alıntı yapılan: RaMu - 15 Şubat 2019, 00:57:17Olur mu kısmına bakmamıştım, onuda yazayım:Tosc = 1 / [Kristal Frekansı]
20MHz kristal ile minimum 1.2kHz PWM üretebilirsin,
32768Hz lik saat kristali kullansan bile
minimum ancak 2Hz PWM frekansına düşebilirsin.
Tpwm= 1/Fkomut X (PR2 + 1) X (TMR2 BÖLME ORANI) Fpwm=1/Tpwm
PR2: 15 ile 255 arasında değerler alıyor.
TMR2: 1
Bu hesaba göre
Minimum frekansım: 19531 Hz
Maksimum frekansım: 312500 Hz
Bu değerleri dahi göremedim.
Alıntı yapılan: mehmet - 15 Şubat 2019, 10:12:08http://eng-serve.com/pic/pwm_functions.html
Hocam siteyi inceledim. CCS C kullandığım için registerları örnekteki gibi kullanmama izin vermiyor derleyiciç