18F4550 10 BIT PWM

Başlatan pax, 02 Aralık 2014, 10:50:26

pax

 pic18f4550 nin CCP1 modülünden 10 bit çözünürlükte pwm üretmek istiyorum. 10bit çözünürlük derken kastedilen nedir. bu konuda kafam karıştı.


örneğin ürettiğim pwm sinyali ile bir motor sürücü yardımıyla 12v bir dc motorun hız kontrolünü yapmak istiyorum. 10 bit pwm çözünürlüğü denildiğinde benim anladığım 12v tu  0-1023 arası bir pwm değeri ile ayarlanabilir hale getirmektir. yanlış mı düşünüyorum?  ancak program içinde pwm periodunu ve duty cycle ayarlarken 10 bit kullanamıyorum .

main.h
#include <pic18f4550.h>
#define _XTAL_FREQ  48000000
// PIC18F4550 Configuration Bit Settings


// 'C' source line config statements


#include <xc.h>


// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.


// CONFIG1L
#pragma config PLLDIV = 1       // PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))
#pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
#pragma config USBDIV = 2       // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes from the 96 MHz PLL divided by 2)


// CONFIG1H
#pragma config FOSC = XTPLL_XT  // Oscillator Selection bits (XT oscillator, PLL enabled (XTPLL))
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)


// CONFIG2L
#pragma config PWRT = ON        // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOR = OFF         // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum setting)
#pragma config VREGEN = OFF     // USB Voltage Regulator Enable bit (USB voltage regulator disabled)


// CONFIG2H
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)


// CONFIG3H
#pragma config CCP2MX = ON      // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)


// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config ICPRT = ON      // Dedicated In-Circuit Debug/Programming Port (ICPORT) Enable bit (ICPORT disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))


// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)


// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM is not code-protected)


// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)


// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM is not write-protected)


// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)


// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)
   

main.c

#include "main.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#define led LATDbits.LATD1
#define led_tris TRISDbits.RD1

void pwm_ayar();
void ilk_ayar(void);
void bekle(unsigned int );

void main()
{
   
    ilk_ayar();
    pwm_ayar();
    led=1;
  
    for(;
    {
      ;
    }
}

void ilk_ayar()
{
     PORTA  = 0X00;
     LATA   = 0X00;

     ADCON1 = 0X00;
     CMCON  = 0X07;

     PORTB  = 0X00;
     LATB   = 0X00;

     LATC   = 0X00;
     PORTC  = 0X00;

     LATD   = 0X00;
     PORTD  = 0X00;

     LATE   = 0X00;
     PORTE  = 0X00;

     TRISA  = 0xff;
     TRISC =  0X00;
     TRISD =  0X00;
     TRISB  = 0Xff;
     TRISE  = 0Xff;
}
void bekle(unsigned int x)
{
   unsigned int i;


   for(i = 0; i < x; i++)
   {
      __delay_ms(1);
   }
}
void pwm_ayar()
{
 PR2 = 254 ;
T2CON = 0b00000111 ;
CCPR1L = 127;
CCP1CON = 0b00001100 ;

}



programda duty cycle ı ayarlamak için"CCPR1L = 127;" komut satırını kullanıyorum . CCPR1L 'nin alabileceği en büyük değer PR2=254 değeri . yani ben burada çözünürlüğü 10 bit ayarlamak istiyorum ancak 254 max değerinden dolayı 8 bit ayarlıyorum. ben mi yanlışım.








ibocakir

TMR2 register'ına istenilen prescale(bölücü) değerini atamanız durumunda 10bit PWM üretebilirsiniz.
ETE hocanın 11.dersinde PWM olayını iyice kavrayabilirsiniz.

pax


Alıntı yapılan: ibocakir - 02 Aralık 2014, 11:46:40
TMR2 register'ına istenilen prescale(bölücü) değerini atamanız durumunda 10bit PWM üretebilirsiniz.
ETE hocanın 11.dersinde PWM olayını iyice kavrayabilirsiniz.

TMR' registerına 1-4-16 prescaler değeri atayabiliyorsunuz. bunu biliyorum. zaten yazdığım programda da bu mevcut

T2CON = 0b00000111 ;  ben 16 olarakseçmişim. 10 bit çözünürlük nedir ? nasıl kullanılır orayı anlayamadım.

ibocakir

PR2 registerina atadığın değer PWM'in frekansını belirler. PWM'in çözünürlüğü ile alakası yok.
10 bitlik çözünürlük için : kullanacağınız duty cycle değerini 10 bitlik düşünün. bunun ilk iki bitini CCP1CON.4 ve CCP1CON.5'e atayın. Kalan 8 biti de CCPR1L'e atamalısın.
10bit için TMR2 bölücü değerini kullanman gerekmiyor özür dilerim. PR2'den bahsedince aklım karıştı bi an.

pax

Karıştırdığım nokta tam olarak şu. PR2 pwm frekansını buna bağlı olarak da PWM periyodunu belirliyor. PR2 enfazla 255 değerini almıyor mu? 

Alıntı yapılan: ibocakir - 02 Aralık 2014, 13:15:39
10 bitlik çözünürlük için : kullanacağınız duty cycle değerini 10 bitlik düşünün. bunun ilk iki bitini CCP1CON.4 ve CCP1CON.5'e atayın. Kalan 8 biti de CCPR1L'e atamalısın.

bu atama sonucunda 10 bitlik bir değer oluyor ve alacağı en büyük değer 1023 oluyor.  PWM sinyalinde de duty cycle ı belirlerken bu 10 bitlik bilginin PR2 ye oranı etkili olmuyor mu? yanı duty cycle süresi pwm periyodunu geçmemeli ama 10 bitlik değer ve PR2 nin alacağı enbüyük 255 değeri duty cycle ın pwm periyodunu geçmesini sağlamıyor mu ?

Nerede yanılıyorum ? 

okay57

10 bitlik PWM mi  10 bit çözünürlüğünde PWM mi üretmek istiyorsunuz?Çünkü ikisi ayrı şeyler.

pax

Alıntı yapılan: okay57 - 02 Aralık 2014, 13:56:24
10 bitlik PWM mi  10 bit çözünürlüğünde PWM mi üretmek istiyorsunuz?Çünkü ikisi ayrı şeyler.


ikisi arasındaki farkı açıklarsanız sevinirim. çünkü ben ikisinin de aynı olduğunu düşünüyordum.

okay57

10 bitlik pwm üretecekseniz pr2 değerine en fazla 255 yazabiliyoruz.Eğer Pwm duty değişkenini int16 olarak tanımlarsanız daha önceden yüzde 50 olan duty saykınızı yüzde 12.5 e düşer.

pax

Alıntı yapılan: okay57 - 02 Aralık 2014, 14:01:55
10 bitlik pwm üretecekseniz pr2 değerine en fazla 255 yazabiliyoruz.Eğer Pwm duty değişkenini int16 olarak tanımlarsanız daha önceden yüzde 50 olan duty saykınızı yüzde 12.5 e düşer.
pwm duty değişkeni olarak yukarıdaki programda yazdığım gibi direkt CCPR1L  yi kullanıyorum ve 8 bit. int16 olarak nasıl tanımlayabilirim ki

ibocakir

Sorunu şimdi daha iyi anladım. PR2 sadece PWM frekansını belirliyor dedik. Evet maximum 255 değerini alabilir.
Fakat sen şimdi bir duty değeri belirlemek istiyorsun. Bu değer %0'dan % 100'e kadar değişebiliyor.
Üretmek istediğin PWM frekansında bir duty cycle değeri vardır. Örnek veriyorum. 20Khz %50 Duty cycle.
Bu durumda senin duty değerini belirlemek için oluşturduğun %50 duty cycle değerinin bit karşılığı PR2 registerına atadığın değerle bir alakası yok.
Yani istersen 1Hz'de %50 duty cycle kullan istersen 20Khzde. Umarım anlatabilmişimdir.



okay57

#10
Kusura bakmayın şimdi inceledim de yanlış bir bilgi kaynağını okumuşum orada çözünürlük pwm in kaç eşit parçada değiştirilceği yazıyordu ben de onu sanki çok farklı bir şey diye almışım
siz sadece  görev çevrim değişkenini(duty) int16 olarak tanımlayın.

mesaj birleştirme:: 02 Aralık 2014, 14:11:15

ccs c : set_pwm1_duty(m) komutundaki m değişkeninin int16 m; olarak tanımlayın o kadar

pax

#11
int16 olarak değiştiremem çünkü duty olarak dediğim gibi CCPR1L yi kullanıyorum. ve CCPR1L 8 bit .
ve ben ccs c kullanmıyorum xc8 kullanıyorum .

okay57

zaten CCPR1L değişmiyor ki yine 255=girilen pr2 değeri siz sadece 255 i 10 bit çözünürlüklü hale getiriyorsunuz şöyle oluyor m/(255) olan duty cycle değeri int16 m; olarak tanımladığınızda m/(255*4) oluyor örneğin m=128 ise int8 m; iken yüzde 50 duty cycle, int16 m; iken yüzde 12.5 duty cycle. ne kadar çok bit o kadar az köfte.

pax

#13
Alıntı yapılan: okay57 - 02 Aralık 2014, 14:18:11
zaten CCPR1L değişmiyor ki yine 255=girilen pr2 değeri siz sadece 255 i 10 bit çözünürlüklü hale getiriyorsunuz şöyle oluyor m/(255) olan duty cycle değeri int16 m; olarak tanımladığınızda m/(255*4) oluyor örneğin m=128 ise int8 m; iken yüzde 50 duty cycle, int16 m; iken yüzde 12.5 duty cycle. ne kadar çok bit o kadar az köfte.

peki bu m değerini benim yazdığım programda nereye yerleştirmem lazım.





okay57

sizin kullandığınız yazılım dilini bilmiyorum.ccs c de bu kadarını yapmanız yeterli.ccs c biliyor musunuz