16f628 için software pwm (rgb parlaklığı için)

Başlatan fzeylan, 26 Eylül 2007, 16:32:58

fzeylan

Selam arkadaşlar,
16f628'de ayrı pinlerden 3 farklı ledin (Kırmızı, Yeşil, Mavi) parlaklıklarını CCS C ile ayarlamak istiyorum. Amacım farklı renk tonlarını oluşturabilmek. Tek led için CCP ve PWM kullanarak istediğimi yapabiliryorum. Ancak 628'de bir adet ccp olduğu için 2 adet daha PWM çıkışına ihtiyacım var.. Bunun yolu da anladığım kadarı ile yazılım ile halletmek.

Kullandığım software pwm kodunu tek led örneği için aşağıda gönderiyorum.
#include <16F628.h>
#fuses HS,NOWDT,NOPUT,NOBROWNOUT,NOMCLR,NOLVP
#use fast_io(a)
#use delay(clock=4915200)

#define   PORTA   0x05

typedef enum
{
   RED,
   GREEN,
   BLUE
}  ColorType;

unsigned int pwm_counter=0;
unsigned int16 pwm_duty_red=0;
unsigned int16 pwm_duty_green=0;
unsigned int16 pwm_duty_blue=0;
unsigned int output=0;

#INT_TIMER2
void TIMER2_isr()
{
   #asm
      movf     pwm_counter,w
      subwf    pwm_duty_green,w
      rlf      output,f
      movf     pwm_counter,w
      subwf    pwm_duty_red,w
      rlf      output,f
      movf     pwm_counter,w
      subwf    pwm_duty_blue,w
      rlf      output,f

      rlf      output,f
      rlf      output,w
      movwf    PORTA

      incf     pwm_counter,f
      clrf     output
   #endasm
}

#inline
void set_pwm_duty(ColorType color,int duty)
{
   switch(color)
   {
      case RED:
      {
         pwm_duty_red=duty;
         break;
      }
      case GREEN:
      {
         pwm_duty_green=duty;
         break;
      }
      case BLUE:
      {
         pwm_duty_blue=duty;
         break;
      }
      default:break;
   }
}

void main()
{
   set_tris_a(0x21);//00100001
   //setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   //setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_1,50,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_ccp1(CCP_OFF);
   enable_interrupts(INT_TIMER2);
   enable_interrupts(GLOBAL);

   while(TRUE)
   {
      ++pwm_duty_red;
      set_pwm_duty(RED,pwm_duty_red);
      delay_ms(10);
   }
}


bu koddaki problemim şu, pwm_duty_red değeri artmaya 0'dan başladığı halde ilk andaki led parlaklığı beklediğimin daha üzerinde.. burada problemimin PWM ve duty cycle'dan kaynaklanabileceğini düşünüyorum..

Yani ;
setup_timer_2(T2_DIV_BY_1,50,1) satırında

istediğim değereleri elde edemedim gibi.

Farklı forumlarda rastladığım örnekler ya CCS değildi ya da benim işime yaramadılar.

Bu konuda herhangi bir fikriniz veya elinizde buna benzer bir amaç için kullandığınız, özellikle kendi yazdığınız bir kod varsa yardımlarınızı bekliyorum.

Kolay gelsin.

protech06

CCS Bilmiyorum fakat 3 adet CCP(PWM) olarak PIC 16F777 deneyebilirsin

zafzaf82

Mikroişlemci bi araçtır, amaç değil.....

erdinch

multiplexer ile ilk önce ilgili ledi seçip sonra gerekli pwm darbelerini gönderebilirsin.

protech06


sezgin05


necati

#include <12F675.h>
#use delay (clock=4000000)
#fuses INTRC_IO,noWDT,PUT,NOBROWNOUT,noPROTECT,NOPUT,NOCPD,MCLR

#define    led1      PIN_A0//yes  led 220R +V
#define    led2      PIN_A1//mavi led 220R +V
#define    led3      PIN_A2//kirm led 220R +V

#ROM 0x3ff = {0x3480}

BYTE CONST TABLE [120]= {
                250,80,0,220,70,0,200,30,0,
                180,0,30,150,0,60,120,0,80,
                100,0,120,80,0,150,60,0,180,
                30,0,200,20,0,230,0,20,250,
                0,40,220,0,60,200,0,80,170,
                0,100,150,0,120,120,00,150,100,
                0,180,80,0,200,60,0,220,40,
                0,250,20,10,220,0,20,200,0,
                30,200,0,40,170,0,50,10,0,
                250,0,0,220,0,0,200,0,0,
                180,0,0,150,0,0,120,0,0,
                0,0,100,0,0,120,0,0,140,
                0,0,180,0,0,200,0,20,250,
                0,40,220,
            };
////////////////////////////////////////////////////////////////////////
void main() {

int16 titrval, dampval;
int led1val,led2val,led3val, deger,tablsay,lighthed1,lighthed2,lighthed3;
SET_TRIS_A   (0b00001000);
SETUP_TIMER_1(T1_DISABLED );
setup_comparator(NC_NC_NC_NC);
setup_ADC_ports(NO_ANALOGS);

   tablsay = 0;
/////////////////////////////////////////////////////////////////////////
while(1){

deger++;
titrval++;
dampval++;
//////////////////////////////////////
if (titrval == 2000){   //tablodan set say al
   titrval = 0;
   if (tablsay >= 98) tablsay = 0;
   lighthed1 = table [tablsay];
   lighthed2 = table [tablsay+1];
   lighthed3 = table [tablsay+2];
   tablsay+=3;}
///////////////////////////////////////
if (dampval ==600){//soft
   dampval = 0;
   if (led1val < lighthed1) led1val++;
   if (led1val > lighthed1) led1val--;
   if (led2val < lighthed2) led2val++;
   if (led2val > lighthed2) led2val--;
   if (led3val < lighthed3) led3val++;
   if (led3val > lighthed3) led3val--;}
////////////////////////////////////////
if( deger < led1val )
   {
   output_low(led1);
   }
else
   {
   output_high(led1);
   }

if( deger < led2val )
   {
   output_low(led2);
   }
else
   {
   output_high(led2);
   }

if( deger < led3val )
   {
   output_low(led3);
   }
else
   {
   output_high(led3);
   }
}

}
/////////////////////////////////////////
[email]entegreterbiyecisi@yahoo.com[/email]

sagamen

#include <16F917> 
#fuses INTRC_IO,NOPROTECT,NOWDT,PUT 
#use delay(clock=8000000) 
#use standard_io(d) 
#define preload 65458 
#define red pin_d0 
#define green pin_d1 
#define blue pin_d2 

int red_duty; 
int green_duty; 
int blue_duty; 
int Intcount; 

//************************************************************************************************** 
//100Hz pwm (interupt at 25.8kHz 
//************************************************************************************************** 

#INT_TIMER1 
void timer_irq() 
{ 
    set_timer1(preload); 
    
   if (Intcount < 255) 
    { 
      if (Intcount == red_duty) 
       { 
         output_low(red); 
       }    
      if (Intcount == green_duty) 
       { 
         output_low(green); 
       }    
      if (Intcount == blue_duty) 
       { 
         output_low(blue); 
       }    
    } 
    
   else if(Intcount == 255) 
    { 
      Intcount = 0; 
      output_high(red); 
      output_high(green); 
      output_high(blue);    
    }    
    Intcount++; 
} 


//************************************************************************************************** 
// Main Program 
//************************************************************************************************** 

void main() 
{ 
   setup_oscillator(OSC_8MHZ); 
    setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); 
    enable_interrupts(INT_TIMER1); 
    enable_interrupts(GLOBAL); 
   red_duty = 63; 
   green_duty = 1; 
   blue_duty = 250; 
   Intcount = 0; 

   for (;;) 
   { 

       
   } 
}
herkEse kolay gelsin

fzeylan

Cevaplarınız için teşekkür ediyorum arkadaşlar..
Problem düşündüğüm gibi timer'ın uygun set edilememesinden kaynaklanıyormuş. Elimin altında osiloskop olmadığı için gözlemlemem zor oldu. Kodu ve devreyi bitirince çalışır halini burada yayınlayacağım.

Yardımlarınız için teşekkür ediyorum.

elektromer

Alıntı yapılan: fzeylan - 09 Ekim 2007, 12:15:36
Cevaplarınız için teşekkür ediyorum arkadaşlar..
Problem düşündüğüm gibi timer'ın uygun set edilememesinden kaynaklanıyormuş. Elimin altında osiloskop olmadığı için gözlemlemem zor oldu. Kodu ve devreyi bitirince çalışır halini burada yayınlayacağım.

Yardımlarınız için teşekkür ediyorum.

Sanırım Proje hala tamamlanamadı... (Rekora aday..)
Her şey gönlünüzce olsun..

Murat Mert

Alıntı yapılan: elektromer - 13 Haziran 2014, 01:04:19
Sanırım Proje hala tamamlanamadı... (Rekora aday..)

Ömer abi çalışınca unutmuştur. :)
mert07