Go Down

Topic: PWM RAMP2 Operation (Read 130 times) previous topic - next topic

b0rn4

Hello! I decided make my own thread becose can be usefull to future ramp2 aplications.
I'm trying to make a code for pwm 2 outputs(pin 5 and pin 6), XXhz pwm frec.
Reading atmel SAMD21G datasheet found RAMP2 operation could be a solution, but is difficult due to huge register configuration needed of matches, modes, etc.
Upload picture show my idea how output should be work and that 90° off phases needed between W[5] and W[6] output. Only change % PWM and frec is constant.
I have problem to implement output idea due can't make a correct register configuration.
Someone can tell me if i'm in a right way, or suggest other solution, code examples, edit my code, etc? Any help is welcome.

Thanks!  

Code: [Select]

#include <Adafruit_NeoPixel.h>

#define Pin13LED 13
#define NEOPIXEL 8  // Neopixel

int PERx = 32000; // PER=TOP value just for example

volatile int cont =0;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(1, NEOPIXEL);   // Create an strip object

void setup()
{
  strip.begin();
  strip.show(); // neopixel off
  
  REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Generic clock divisor D = 1
    GCLK_GENDIV_ID(4);          // Selecciono el clock gen 4
  while (GCLK->STATUS.bit.SYNCBUSY);    // Espero sincronizacion

  REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | // Duty cicle 50%
    GCLK_GENCTRL_GENEN |        // habilito gclk4
    GCLK_GENCTRL_SRC_XOSC32K |    // selecciono clock de 32Khz
    GCLK_GENCTRL_ID(4);         // Selecciono el clock gen 4
  while (GCLK->STATUS.bit.SYNCBUSY);    // Espero sincronizacion

  // Habilito el multiplexor para 2 canales de PWM con Timer TCC0
  const uint8_t CHANNELS = 2;
  const uint8_t Pin_5 = 5;  // TCC0;CCB1;Odd
  const uint8_t Pin_6 = 6;  // TCC0;CCB2;Even
  PORT->Group[g_APinDescription[Pin_5].ulPort].PINCFG[g_APinDescription[Pin_5].ulPin].bit.PMUXEN = 1;
  PORT->Group[g_APinDescription[Pin_6].ulPort].PINCFG[g_APinDescription[Pin_6].ulPin].bit.PMUXEN = 1;

  // Conecto el timer TCC0 con los puertos de salida
  PORT->Group[g_APinDescription[5].ulPort].PMUX[g_APinDescription[5].ulPin >> 1].reg = PORT_PMUX_PMUXO_F | PORT_PMUX_PMUXE_F;
  PORT->Group[g_APinDescription[6].ulPort].PMUX[g_APinDescription[6].ulPin >> 1].reg = PORT_PMUX_PMUXO_F | PORT_PMUX_PMUXE_F;

  // Conecto el GCLK con TCC0
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |
     GCLK_CLKCTRL_GEN_GCLK4 |
     GCLK_CLKCTRL_ID_TCC0_TCC1;
  while (GCLK->STATUS.bit.SYNCBUSY);    // Espero sincronizacion

  
  // Single slope PWM: timer TCC0
  REG_TCC0_WAVE |= TCC_WAVE_WAVEGEN_NPWM |
    //TCC_WAVE_CIPEREN |  // Diferentes PER en ciclo A y B
    TCC_WAVE_POL0 | // Change polarity output
    TCC_WAVE_POL1;
    TCC_WAVE_RAMP_RAMP2;  // RAMP2 operation
  while (TCC0->SYNCBUSY.bit.WAVE);    // Espero sincronizacion

  // Configuro valor PER
  REG_TCC0_PER = PERx;
  while(TCC0->SYNCBUSY.bit.PER)   // Espero sincronizacion

  delay(50);

  // Configuro valor CCBx
  REG_TCC0_CC1 = (PERx/2);       // TCC0 CCB1 - 50% PWM on PIN 5
  while(TCC0->SYNCBUSY.bit.CC1);
  REG_TCC0_CC2 = (PERx/2);    // TCC0 CCB2 - 50% PWM on PIN 6
  while(TCC0->SYNCBUSY.bit.CC2);

  
  // Configuro preescaler y habilito las salidasTCC_CTRLBSET_IDXCMD_DISABLE |
  REG_TCC0_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 |
    TCC_CTRLA_CPTEN0 |  // capture channel 0 enable
    //TCC_CTRLBSET_IDXCMD_DISABLE |
    TCC_CTRLA_ENABLE;
  while (TCC0->SYNCBUSY.bit.ENABLE);  // Espero por sincronizacion

  delay(50);
  
}

void loop()
{
  
  REG_TCC0_CCB1 = (PERx/2);                       // OUTPUT pin 5
  while(TCC0->SYNCBUSY.bit.CCB1);
  REG_TCC0_CCB2 = (PERx/2);                     //OUTPUT pin 6  
  while(TCC0->SYNCBUSY.bit.CCB2);

}

parsec326

Hello b0rn4,

I'm a new user to the M0 pro as well. I try not to use any of the Arduino libraries because they are super slow and I need really high performance. I found a few resources that can help:
1. Install Atmel studio. You can find it here: https://www.microchip.com/development-tools/atmel-studio-7

2. After installing Atmel studio,  in your computer (windows) you can go here:
C:\Program Files (x86)\Atmel\Studio\7.0\packs\atmel\SAMD21_DFP\1.2.276\samd21a\include\component
This folder lists the component definitions for all the peripherals. This is super useful when you want to configure a timer, ADC, RTC etc.

3. This wiki will help you to read and understand the component definitions if you're new to them:
https://eewiki.net/display/microcontroller/Getting+Started+with+the+SAM+D21+Xplained+Pro+without+ASF
Once you understand the component definitions structure, its relatively simple to configure registers and peripherals just from reading the datasheet. Your code will also be very readable and easy to understand.

4. Understand and use the Arduino pin definitions here:
https://github.com/arduino/ArduinoCore-samd/blob/master/variants/arduino_mzero/variant.cpp
For example, this is a more readable way to code:
Code: [Select]

    PORT->Group[PORTA].PINCFG[14].bit.PMUXEN = 1; // Peripheral mux enable PWM
    PORT->Group[PORTA].PINCFG[15].bit.PMUXEN = 1; // Peripheral mux enable PWM 
    PORT->Group[PORTA].PMUX[7].reg = PORT_PMUX_PMUXO_F | PORT_PMUX_PMUXE_F; // Enable PMUX group F both Odd and Even pins

This is not:
Code: [Select]

 PORT->Group[g_APinDescription[Pin_5].ulPort].PINCFG[g_APinDescription[Pin_5].ulPin].bit.PMUXEN = 1;
  PORT->Group[g_APinDescription[Pin_6].ulPort].PINCFG[g_APinDescription[Pin_6].ulPin].bit.PMUXEN = 1;
  PORT->Group[g_APinDescription[5].ulPort].PMUX[g_APinDescription[5].ulPin >> 1].reg = PORT_PMUX_PMUXO_F | PORT_PMUX_PMUXE_F;
  PORT->Group[g_APinDescription[6].ulPort].PMUX[g_APinDescription[6].ulPin >> 1].reg = PORT_PMUX_PMUXO_F | PORT_PMUX_PMUXE_F;

Both code samples do the exact same thing, but the first example is easier to debug.

b0rn4

Hello parsec326,

I need too high performance in my proyect and you make me curious about atmel studio.
I read many atmel application notes about pwm, all their examples are in atmel studio.
But my problem is that code is a small part of a big program to make a firmware for a stimulator. In other words, i also have made lot of interrups, functions, etc.
Its that all posible in atmel studio, and what about the time to learn??

Hope your response. Thanks!!

Go Up