Ynt: PWM

Başlatan muhittin_kaplan, 28 Ekim 2012, 20:04:12

muhittin_kaplan

STM32F4 yada F1 ile yapılan PWM hesaplaması nasıl oluyor (Registerleri açıklarsanız sevinirim)
Bülent hocanın 8 li örneği Software bana hardware gerekli.

mesaj birleştirme:: 28 Ekim 2012, 20:34:40

TIM3->CCMR2 = TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | 
              TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; // PWM mode on channel 3 & 4

burada ne yapmak istemiş ?

Klein

#1
hesaplamayı mı soruyorsun?  Timer'i nasıl PWM olarak ayarlayacağını mı?

Eğer hesaplamayı soruyorsan çok kolay.

İki tane registerin var birisi önbölücü (prescaler) registeri olan TIMx_PSC ve diğeri otomatik geri yükleme (Reload) değerini barındıran TIMx_ARR registeri.

ARR registeri çözünürlüğünü belirleyen register. CNT değeri CCR registerine yazdığın değeri aştığında counter çıkış seçimine göre 0 veya 1 olur.  ARR registerini aştığında ise sıfırlanır.
Örneğin:  bu registeri  1000 yaparsan
CCR=0 ise  Duty %0 olur.
CCR=500 ise Duty = %50 olur.
CCR=1000 ise DUuty=%100 olur.

PSC registeri frekansımızı belirler. Ama frekansı tek başına belirleyemez. Frekansımız hem ARR hem de PSC registerine göre belirlenir.
PSC önbölücüdür.
Örn:
Bus hızımız 84Mhz.  PSC değerimiz  100,  ARR değerimiz ise 1000 olsun.
Çnce bus frekansımız  100'e bölünür. PWM sayıcısının saat frekansı artık 8.4MHz.
ARR registerimiz 1000 olduğuna göre, sayıcımız 1000 değerini aştığında resetlenecek ve yeniden başlayacak. Yani 1000 darbede 1 resetleneceğiz. Bu drumda resetlenme frekansımız 8.4MHz/1000 = 8.4KHz olur. Yani PWM frekansımız 8.4KHz.

Bu değerlerde +-1 yanılma olabilir. Counter taştıktan sonra resetlenme için 1 darbe daha gerekiyordu sanırım. Detayı rehberde var.

mesaj birleştirme:: 28 Ekim 2012, 21:16:16

Alıntı yapılan: muhittin_kaplan - 28 Ekim 2012, 20:04:12


mesaj birleştirme:: 28 Ekim 2012, 20:34:40

TIM3->CCMR2 = TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | 
              TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; // PWM mode on channel 3 & 4

burada ne yapmak istemiş ?
Öncelikle bu tanımlamalara bir göz atalım. Tanımlamalar Stm32F4xx.h dosyasında. Aşağıdaki şekilde tanımlanmış.

#define  TIM_CCMR2_OC3M_1                    ((uint16_t)0x0020)            /*!<Bit 1 */
#define  TIM_CCMR2_OC3M_2                    ((uint16_t)0x0040)            /*!<Bit 2 */
#define  TIM_CCMR2_OC4M_1                    ((uint16_t)0x2000)            /*!<Bit 1 */
#define  TIM_CCMR2_OC4M_2                    ((uint16_t)0x4000)            /*!<Bit 2 */

Yukarıdaki tanımlama bir maske tanımı.  Yukarıdaki sayıların tümünü orlayalım.

0x0020  0000 0000 0010 0000
0x0040  0000 0000 0100 0000
0x2000  0010 0000 0000 0000
0x4000  0100 0000 0000 0000
-----------------------------------
0x6060  0110 0000 0110 0000

görüldüğü gibi elimizde 0x6060 sayısı oluyor. CCMR2 registerine baktığımızda bu set edilen bitlerin  OC34 ve OC4M registerlerine denk geldiğini görüyoruz. Yani  OCxM registerini 110 yapıyoruz. Rehberden baktığımızda da OCxM registerinin 110 olması durumunda o kanalın PWM 1. modda çalışacağını görüyoruz.

M_B

muhittin_kaplan Hocam
Klein hocam cok guzel acıklamış ek olarakta altaki linkide  bir bakın.
https://www.picproje.org/index.php/topic,41911.0.html
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

muhittin_kaplan

#3
Aşağıdaki Kodları Anadığım dil e çevirmeye çalıştım ama beceremedim. PWM i çalıştıramadım.

//=============================================================================
// STM32VLDISCOVERY tutorial
// Lesson 6. Pusle Width Modulation (PWM)
// Copyright : Radoslaw Kwiecien
// http://en.radzio.dxp.pl
// e-mail : radek(at)dxp.pl
//=============================================================================
#include "stm32f10x.h"
#include "antilib_gpio.h"

int main(void)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;

AFIO->MAPR = AFIO_MAPR_TIM3_REMAP;         //AFIO->MAPR |=0x00000C00
TIM3->PSC = 239; // Set prescaler to 24 000 (PSC + 1)
TIM3->ARR = 500; // Auto reload value 500

TIM3->CCR3 = 0;   // Start PWM duty for channel 3
TIM3->CCR4 = 500; // Start PWM duty for channel 4

TIM3->CCMR2 = TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | 
              TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; // TIM3->CCMR |=0x6060 PWM mode rehber 259


TIM3->CCER = TIM_CCER_CC4E | TIM_CCER_CC3E; // TIM3->CCER |=0x1100
TIM3->CR1  = TIM_CR1_CEN; // TIM3->CR1 |=0x0001

TIM3->DIER = TIM_DIER_UIE; // TIM3->DIER |=0x0001
NVIC_EnableIRQ(TIM3_IRQn); // NVIC->ISR[0] |=0x20000000
while (1) {}
}

void TIM3_IRQHandler(void)
{
if(TIM3->SR & TIM_SR_UIF) // if UIF flag is set
  {
  TIM3->SR &= ~TIM_SR_UIF;  // clear UIF flag
  TIM3->CCR3 += 5;          // increase ch3 duty
  if(TIM3->CCR3 == 500)     // if maximum
    TIM3->CCR3 = 0;         // set to zero 
  TIM3->CCR4 -= 5;          // decrease ch4 duty
  if(TIM3->CCR4 == 0)       // if minimum
    TIM3->CCR4 = 500;       // set to maximum
}
}


mesaj birleştirme:: 28 Ekim 2012, 22:54:08

RCC->APB2ENR |= RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN;
daki AFIO registerinin clock uygulamayı atlamışım. sorun hallaoldu PWM üretiyorum atrıkın :)