Merhaba arkadaşlar
Yaklaşık 2 hafta kadar oldu hi-tech ten mplab c18 e geçiş yaptım, hazır c18 e geçmişken bir kaç uygulama yapayım dedim.
Bilindiği üzere pwm uygulamalarda bir çok kolaylıklar sağlayan bir yöntemdir, fakat microcontrollerlarda donanım olarak yeralan pwm-modülü sayısı sınırlıdır. Bazen uygulamalarda sayı olarak fazla miktarda pwm ihitiyaca olmaktadır.
Bu nedenle mplab c18de pwm işlemini pwm modullerine ihtiyaç duymadan yerine getirecek küçük bir program yazdım.
İşleyişi kısaca şu şekildedir:
Struct olarak oluşturduğumuz sanal pwm modüllerini timer ve kesme yardımı ile program içerisinde dutycycle karşılaştırmalarını yapıp istediğimiz bir portun isteğimiz pininden genişliği ayarlanmış puls çıkışı veriyoruz.
Puls genişliği yazılımsal olarak kontrol edildiği için pwm kanal sayısı ve işlemci hızı verim açısından büyük rol oynamaktadır.
Pwm çıkışlarından analog sinyal elde etmek için alçak geçiren filitreden geçirilmektedir. Alçak geçiren filitre için gereken bilgiler aşağıdaki application note ta yeralmaktadır
http://ww1.microchip.com/downloads/en/AppNotes/00538c.pdf
kaynak kodları:
not: kodaları düzenleyip hi-tech içinde kullanabilirsiniz
/* **************************************************************
PROJECT NAME : 8 kanal yazlimsal PWM çikis
AUTHOR : PROTECH_
DATE : 21,nisan, 2010
ABSTRACT : Yazilimsal PWM modüllerini olusturulup
Timer ve interrupt yardimi ile , 8 kanal
8 bit çözünürlükte pwm çikisi saglamak.
Istege bagli olarak çikislar low-pas yada alçakçak
geçiren olarak adlandirdigimiz filitreden geçirilip
analog çikis alinabilir, DAC(dijital analog çevirici)
olarak kullanilabilir.
COMPILER : Microchip C18
PROCESSOR : pic18f452-I/P (I=industrial process 40Mhz)
SPEED : 10mips (10Mhz X HSPLL=40Mhz )
REFERENCES : PWM, www.microchip.com Application notes
**********************************************************************/
#include <p18f452.h>
#include <math.h>
#include <delays.h>
#pragma config WDT=OFF, OSC=HSPLL, DEBUG=OFF
#define pwmport PORTD // PWM portu
#define pwmtris TRISD // çikis olarak seçilebilmesi için TRIS reg.
#pragma udata gpr0 //degiskenlerimiz BANK0a yerlestrilsin (not:istege bagli)
typedef struct PWM { // PWM yapisi
unsigned char dutycycle; // PWM.dutycycle
unsigned timerov: 1; //pwmtimer taşma bayrağı
} PWM; // PWM.pwmtimer over flow Bayragi
PWM pwm1,pwm2,pwm3,pwm4,pwm5,pwm6,pwm7,pwm8; // 8 adet PWM olustruldu
unsigned char pwmtimer=0; // pwm sanal timer
unsigned char i1=0; // pwmdeger_ata fonksiyonu for döngüsü için
#pragma udata gpr1 //
unsigned char sinus[32]; // sinus tablosu
unsigned char kare[32]; // kare dalga tablosu
unsigned char ucgen[32]; // ucgen dalga tablosu
unsigned char testere[32]; // testere dalga tablosu
//----------------------------------------------------------------------------------------------------------
void pwm_init(void); // pwm ayar fonksiyonu
void sig_tblinit(void); // pwm data table
void pwmdeger_ata(void); // pwm lere tablodan deger ata
void KESMEH(void);
void setpwmduty(unsigned char duty,unsigned char pwm); // pwm dutycycle yazma fonksiyonlari
/*......................Main fonksiyonu */
void main()
{
INTCON=0X00; //kesmeler kapali
sig_tblinit(); //sinyal tablolarini hesapla
pwm_init(); // pwm degerlerini ayarlarini yap
while(1)
{
pwmdeger_ata(); //pwmlere sinyal değerleri ata deger ata
Delay10KTCYx(5); // 500u Sn bekle
}
}
/* ......................Main fonksiyonu bitis */
void pwmdeger_ata()
{
if(pwm1.timerov) // pwmtimerda tasma oldumu ?
{
setpwmduty(sinus[i1],1); // 1.pwmin dutycyle ı sinus[i1] degerine ayarla
setpwmduty(testere[i1],2); // 2.pwmin dutycyle ı testere[i1] degerine ayarla
setpwmduty(kare[i1],3); // 3.pwmin dutycyle ı kare[i1] degerine ayarla
setpwmduty(ucgen[i1],4); // 4.pwmin dutycyle ı ucgen[i1] degerine ayarla
setpwmduty(sinus[i1],5); // 5.pwmin dutycyle ı sinus[i1] degerine ayarla
setpwmduty(testere[i1],6); // 6.pwmin dutycyle ı testere[i1] degerine ayarla
setpwmduty(kare[i1],7); // 1.pwmin dutycyle ı kare[i1] degerine ayarla
setpwmduty(ucgen[i1],8) ; // 1.pwmin dutycyle ı ucgen[i1] degerine ayarla
i1++; // i1 index i bir arttir
if(i1==32)
{ i1=0; } //i1 32 ye ulaştığında sıfırla
pwm1.timerov=0; //timer taşma bayrağını sıfırla
}
}
/*---------------------------------------------------------------------
KESME RUTINI
-----------------------------------------------------------------------*/
#pragma interrupt KESMEH
void KESMEH(void)
{
unsigned char t0contemp;
if(INTCONbits.TMR0IF)
{
INTCONbits.TMR0IF=0; //TIMER INT bayragini temizle
pwmtimer++; // sanal timer lari artirma blogu
pwmtimer++; //pwmtimer 2nin katları şeklinde artırılarak period değeri ayarlanabilir
if(pwmtimer>pwm1.dutycycle) // eger timer degerinden duty cycle küçükse pwm çikisini sifirla
{ PORTDbits.RD0=0; }
if(pwmtimer>pwm2.dutycycle)
{ PORTDbits.RD1=0; }
if(pwmtimer>pwm3.dutycycle)
{ PORTDbits.RD2=0; }
if(pwmtimer>pwm4.dutycycle)
{ PORTDbits.RD3=0; }
if(pwmtimer>pwm5.dutycycle)
{ PORTDbits.RD4=0; }
if(pwmtimer>pwm6.dutycycle)
{ PORTDbits.RD5=0; }
if(pwmtimer>pwm7.dutycycle)
{ PORTDbits.RD6=0; }
if(pwmtimer>pwm8.dutycycle)
{ PORTDbits.RD7=0; }
if(pwmtimer>0xfa) //eger timer owerflow meydana gelirse pwm çikislarini set yap
{PORTD=0xff;
pwm1.timerov=1; // taşma bayrağı set edildi
}
t0contemp=T0CON; // Timer0 başlangıç değeri ata
TMR0L=0X80; // 128 cycle sonra kesme meydana gelir
T0CON=t0contemp;
}
}
#pragma interruptlow KESMEL
void KESMEL(void)
{
}
//---------
#pragma code isrl=0x18
void isrlow(void)
{
_asm GOTO KESMEL _endasm
}
#pragma code
#pragma code isrh=0x08
void isrh(void)
{
_asm GOTO KESMEH _endasm
}
#pragma code
/*---------------------------------------------------------------------
KESME RUTINI bitis
-----------------------------------------------------------------------*/
void pwm_init()
{
pwmtris=0x00; //PORTD çikis olarak ayarlandi
pwmport=0; //PORTD=0;
pwm1.dutycycle=128; // pwm dutycycle baslangiç degerleri
pwm2.dutycycle=128;
pwm3.dutycycle=128;
pwm4.dutycycle=128;
pwm5.dutycycle=128;
pwm6.dutycycle=128;
pwm7.dutycycle=128;
pwm8.dutycycle=128;
pwm1.timerov=0; // pwm sanal timer overflow bayraklarini sil
INTCON=0X00; // kesme ayarları
INTCONbits.TMR0IE=1;
INTCONbits.GIE=1;
RCONbits.IPEN=0;
T0CONbits.T08BIT=1; // TMR0 8 BIT
T0CONbits.PSA=1; //PRESCALER DIS.
T0CONbits.T0CS=0;
T0CONbits.TMR0ON=1; //TMR0 ON
}
//-------------------------------------------------------------------
void setpwmduty(unsigned char duty,unsigned char pwm)
{
pwm1.timerov=0;
if(pwm==1)
{pwm1.dutycycle=duty; // pwm in duty degerini ata
}
if(pwm==2)
{pwm2.dutycycle=duty; // pwm in duty degerini ata
}
if(pwm==3)
{pwm3.dutycycle=duty; // pwm in duty degerini ata
}
if(pwm==4)
{pwm4.dutycycle=duty; // pwm in duty degerini ata
}
if(pwm==5)
{pwm5.dutycycle=duty; // pwm in duty degerini ata
}
if(pwm==6)
{pwm6.dutycycle=duty; // pwm in duty degerini ata
}
if(pwm==7)
{pwm7.dutycycle=duty; // pwm in duty degerini ata
}
if(pwm==8)
{pwm8.dutycycle=duty; // pwm in duty degerini ata
}
}
#pragma code
void sig_tblinit()
{
unsigned char i=0;
char j;
float a;
ucgen[0]=1; //baslangiç degerleri
testere[0]=1; // baslangiç degerleri
kare[0]=255;
for(i=1;i<32;i++)
{
kare[i] = 32; // kare dalga için sürekli dutycycle period / 2
if(i<17) // ücgen dalga için
{ucgen[i]=ucgen[i-1]+15;
kare[i] =255;
}
else
{
kare[i] = 0;
ucgen[i]=ucgen[i-1]-15;}
testere[i] =testere[i-1]+8;
// testere için
}
for(j=0;j<32;j++)
{
a=sin(0.196*(float)j); //sin(2*pi/32*j)
sinus[j] =(unsigned char)(128+127*a); //0-255 arasi boyutlandir
}
}
sinyal çıktıları
[IMG]http://img46.imageshack.us/img46/6549/pwmdac.jpg[/img] (http://img46.imageshack.us/i/pwmdac.jpg/)
[IMG]http://img688.imageshack.us/img688/1866/pwmdacsinyl.jpg[/img] (http://img688.imageshack.us/i/pwmdacsinyl.jpg/)
Eline sağlık Turgutum sinüs ,kare ,üçgen ,testere falan güzel olmuş.
Alıntı yapılan: tamirci_erhan - 22 Nisan 2010, 10:06:26
Eline sağlık Turgutum sinüs ,kare ,üçgen ,testere falan güzel olmuş.
sağol erhan hocam
Aslında PWM ile ilgili fikri olan varsa yapıp forumda yayınlayabiliriz!
yeni konu açmayım dedim.
Alıntı Yaptypedef struct PWM { // PWM yapisi
unsigned char dutycycle; // PWM.dutycycle
unsigned timerov: 1; //pwmtimer taşma bayrağı
} PWM; ;
timerov: 1; bu ifade standart c ifadesimidir. stuct yapısına mı özeldir. biri kullanımını açıklayabilir mi?