I/O ları PWM olarak kullanmak

Başlatan baran123, 23 Kasım 2014, 19:06:13

baran123

18F4550 de 'D' portunun hepsini PWM olarak kontrol etmek istiyorum yani 8 adet 220V lambaya ışık ayarı yapmak amaçlı bunu için kullanabileceğim bir entegre veya bir yol var mı ?
(CCS C)

Gökhan BEKEN

en basitinden bir örnek
unsigned int i=0;
unsigned int duty=500;
unsigned int dutyMax=1000;

while(1){
    i++;
    if(i==duty){porta=0xFF}
    if(i==dutyMax){i=0; porta=0x00}
}


Ledler %50 parlaklıkta yanacaktır. Çünkü sayaç 1000'e ulaşınca sıfırlanıyor ve ilk 500 de ledler yanıyor ve son 500 de ledler sönüyor.
Sayılar ve işlemcinin çalışma hızı ledlerideki titreşimi etkiler. Yani işlemci ne kadar yavaşsa o kadar titreşim görürsün. Dutymax değeri ne kadar yüksekse yine o oranda titreşim görürsün. Titreşimin az olması için daha fazla hıza ihtiyacın var. Bu işlemleri timer ile yapmak işlemciye başka işlemler yapabilmesi için zaman kazandırır. En iyisi donanımsal pwm kullanmaktır ama mantığını anlaman için yukarıdaki örnekte olduğu gibi yazılımsal olarak kendin yapmanı öneririm.
Özel mesaj okumuyorum, lütfen göndermeyin.

baran123

Hocam çeşitli örnekler yapacağım bununla ilgili örnekler için teşekkürler.Bir diğer aklıma takılan kısım ise işlemci yavaşalar mı çeşitli problemler olur gibi çünkü 4550 yi bir yandan usb ile haberleştiriyorum, ayrıca ds18b20 ile de sıcaklık bilgisi alıyorum gerçi ds bekleme yapmıyor kutuphanesını duzenledım ama daha devreyı kurmadıgım ıcın bılemıyorum
Hocam bır de bu verdıgınız ornek butun bıtlere aynı degerı verıyor galıba 8 tane ayrı ayrı kontrol edeceğim de

Kabil ATICI

O işlemcinin istediğin şeyi kaldırabileceğinden emin değilim. USB üstüne birde DS1820 ve 100Hz'lik PWM kontrolu. (şebeke frekansı 50 Hz ama triak için 100Hz kontrol gerekir.-Negatif alternans ve pozitif alternans için)
256 adımda olursa 256x100 (kesme frekansı)
adım sayısı azaltılırsa frekansıda düşecektir. Sonuçta işlemcinin başka işi olmadığını varsayarsak iki kesme arasında 8 tane PWM'in kontrol edilmesi gerekecek. Ama işlemcinizin yapması gereken başka işler var. Üstekilk birde şebeke frekansının 0 geçişi takip edilecek...

Alternatif olarak PWM olayı başka işlemcileri yüklenebilir.
ambar7

baran123

Hocam aslında şöyle bir şey yapsam diyorum;
4550 yerine 2550 kullansam 20 mhz de usb bağlantısı yapsa diğer angarya işleri başka mcu larda yapsam bunlarıda aralarımda seri iletişim ile haberleştrir sem ve bu seri iletişim kesmesinde bilgi geldiği zaman işlem yapsam tahmin ettiğim kadarı ile yük hafifler sizce boyle yapmak mantıklımı ? çünkü hazırladığım arayüzde bir çok donanım kullanıyorum lcd,portlar, usb,ds18b20,pwm,zamanlı çalışan bazı sistemler

Kabil ATICI

olabilir. seri olabilir, i2c olabilir, spi olabilir. Bu tamamen senin donanım üzerine hakimiyetine kalmış...
ambar7

Gökhan BEKEN

Timer ile portc'yi komple pwm ile sürmek için bir örnek yaptım, timer 4 kerede 1 işini tamamlıyor, yani zamandan tasarruf yapıyor, bu sayede diğer işlere de zaman kalıyor.  DelayUs (bekle); şeklinde dinamik çalışan bir fonksiyonu gerçek zamanla birebir tutturmak pic ile neredeyse imkansız, bunun için ayrı bir timer kurmak şart, NOP gibi komutlarla olacak iş değil. 16f serisinde interrupt önceliği olmadığı için 16f serisi ile timer kurarak da yapamazsınız. 18f serisinde yapılabilir.
interrupt TIMER(void) fonksiyonuna yani timer kesme fonksiyonuna 1ms'de bir girecek şekilde timer kurulumu yapın ve portc'nin kullanacağınız pinlerini TRIS ile çıkış yapmayı unutmayın.

unsigned int mikroBekle = 2000; //mikro saniye birimi(max:4000) (duty'i doğrudan etkiler)
unsigned char sayac = 0;

void interrupt TIMER(void) { //her 1ms'de bir bu fonksiyona girecek şekilde kullanın
    unsigned int bekle = 0; //mikro saniye birimi(max:1000)
    sayac++;
    if (sayac > 4)sayac = 1;

    if (sayac == 4) { // her 4ms'de bir bu if'e girer ve 1ms sonra cikar
        PORTC = 0xFF; //burda portun pwm yapılmak istenen pinleri HIGH yapılıyor
    }
    if (sayac == 4) {
        if (mikroBekle >= 0 && mikroBekle < 1000) {
            bekle = mikroBekle;
            DelayUs (bekle);
            PORTC = 0x00;
        }
    }
    if (sayac == 1) { //4. durumdan 1ms sonra buraya gelir.
        //burada yapacagin en buyuk delay 1ms'yi asmamalidir.
        if (mikroBekle >= 1000 && mikroBekle < 2000) {
            bekle = mikroBekle-1000;
            DelayUs (bekle);
            PORTC = 0x00;
        }
    }
    if (sayac == 2) { //4. durumdan 2ms sonra buraya gelir.
        //burada yapacagin en buyuk delay 1ms'yi asmamalidir.
        if (mikroBekle >= 2000 && mikroBekle < 3000) {
            bekle = mikroBekle-2000;
            DelayUs (bekle);
            PORTC = 0x00;
        }
    }
    if (sayac == 3) { //4. durumdan 3ms sonra buraya gelir. Bu islem bittiginde 4ms tamamlanmis olur.
        //burada yapacagin en buyuk delay 1ms'yi asmamalidir.

        if (mikroBekle >= 3000 && mikroBekle < 4000) {
            bekle = mikroBekle-3000;
            DelayUs (bekle);
            PORTC = 0x00;
        }
	}


    //Timer Interrupt Flag'ini sifirla
}
Özel mesaj okumuyorum, lütfen göndermeyin.