(ATtiny817) Generate a PWM signal in TCB periheral

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi everyone!

 

I am new here and I have a doubt and I think that here may be someone to help me :). I am using an Attiny817 microcontroller and I want to generate a PWM signal using the 16bit counter type B (PB0 output). I'm following the datasheet, but I'm not able to get the desired output signal.

I leave you the part of the datasheet regarding the configuration of TCB and the code that I am using. I hope your answer. Thank you very much in advance.

 

 

 

#include <avr/io.h>


int main(void)
{ 
 //Set pin 0 of port B (PB0/WO) as output. Waveform Output
 PORTB.DIRSET |= PIN0_bm; 
 
 TCB0.CTRLA = TCB_CLKSEL_CLKDIV1_gc
 | 0 << TCB_ENABLE_bp   // Disable the peripheral
 | 0 << TCB_RUNSTDBY_bp
 | 0 << TCB_SYNCUPD_bp;
 
 
 TCB0.CCMPH=125;  // Write compare/capture register to {CCMPH, CCMPL}
 TCB0.CCMPL=251;  
 TCB0.CNT=0x0000; // Write 0x0000 to count register
 
 
 TCB0.CTRLB = 0 << TCB_ASYNC_bp       // Asynchronous Enable: disabled. Only important in "Single Shot Mode"
 | 1 << TCB_CCMPEN_bp    // Pin Output Enable: Enabled (enable the output "Compare/Capture")
 | 0 << TCB_CCMPINIT_bp  // Set 0 (LOW) the initial output value in the pin that is used as output
 | TCB_CNTMODE_PWM8_gc;  // TCB_CNTMODE_PWM8_gc = (0x07<<0) --> 8-bit PWM  


 TCB0.CTRLA = TCB_CLKSEL_CLKDIV1_gc  // CLK_PER (No Prescaling). Using the main clock. See page 18 of datasheet
 | 1 << TCB_ENABLE_bp   // Enable the counter
 | 0 << TCB_RUNSTDBY_bp // Run Standby: disabled
 | 0 << TCB_SYNCUPD_bp; // Synchronize Update: disabled

 
    while (1) 
    {
    }
}

 

This topic has a solution.
Last Edited: Fri. Sep 15, 2017 - 08:52 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

In case you are still having problems. The line

 PORTB.DIRSET |= PIN0_bm; 

should be:

 PORTA.DIRSET = PIN5_bm;

(Check chapter 5.1 of the datasheet. The PB0 is WO0 for TCA, while WO for TCB0 is on Porta, pin 5).

 

Also in figure 21-9 that you included above, notice how the CCMPL is actually the top, and CCPMH is the midpoint. So your lines:

 TCB0.CCMPH=125;  // Write compare/capture register to {CCMPH, CCMPL}
 TCB0.CCMPL=251;  

should read:

 TCB0.CCMPL=251;  // Write compare/capture register to {CCMPH, CCMPL}
 TCB0.CCMPH=125;

 

That seemed to get it working, for me at least.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Threiran! Thank you so much for your answer. You're right, I have those errors in the code. I have been fighting the problem these days and finally decided to use the type A timer and I was able to get the PWM signal. I leave here the code that I used to generate the PWM signal in case it can help anyone. A greeting.  

//Set pin 0 of port B (PB0/WO) as output. Waveform Output (pag 204 datasheet)
 PORTB.DIRSET |= PIN0_bm;
 
 // FRECUENCIA:   Fpwm_ss = Fclk_per/(N(PER+1))
 // RESOLUCIÓN MÁXIMA: Rpwm_ss = (log(PER+1))/(log(2))
 
 TCA0.SINGLE.PER=PWM_per;
 
 //CMP fija el Duty Cycle de la señal PWM --> CT= CMP0/PER
 TCA0.SINGLE.CMP0=PWM_duty_cycle; //Duty Cycle aprox. 50% cuando CMP0 es PER/2
 TCA0.SINGLE.CNT=0x0000; //Iniciamos el contador en 0;
 
 //Configuramos el registro CTRLB
 TCA0.SINGLE.CTRLB = 0 << TCA_SINGLE_ALUPD_bp      /* Auto Lock Update: disabled */
 | 1 << TCA_SINGLE_CMP0EN_bp   // Compare 0 enabled: Habilitamos la salida WO0 (PB0)
 | 0 << TCA_SINGLE_CMP1EN_bp   // Setting: disabled
 | 0 << TCA_SINGLE_CMP2EN_bp   // Setting: disabled
 | (0x03<<0); // TCA_SINGLE_WGMODE_SINGLESLOPE_gc = (0x03<<0),  --> Single Slope PWM

 TCA0.SINGLE.CTRLA = (0x00<<1)    //TCA_SINGLE_CLKSEL_DIV1_gc = (0x00<<1), -- System Clock; No hay división de frecuencia. La frecuencia de reloj para el temporizador es Fclk_per
 | 1 << TCA_SINGLE_ENABLE_bp;  // Habilitamos el periférico