WGM12

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

Hallo,

I noticed that when I wanted to use timer1 in CTC mode, and set a value inside OCR1A and match interrupt, it doesn't matter whether I set WGM12 or not, it works as required, the interrupt just fires, what is the reason for this?

Signature: We need more peripherals in DIP packages. Namely, USB, 12-bit ADC, 16-bit timer, cheaper tool as a programmer/debugger coz STK600 is expensive! Atmel Studio 5/6 sucks! coz it brings MS visual studio crap to AVR world..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Which model of AVR? Show the code.

(I suspect you are setting WGM12 in the wrong register - a lot of AVRs split four WGM bits with 2 in one register and 2 in another)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here you go, it doesn't matter if I set WGM12 or not, it simply works..

/*****************************************************
Project                 : Dimmer
Version                 : 1.3
Date                    : 21/02/2008 - 3/11/2011
Author                  : Ehab Anwar - Modified by MeTaL                           
Company                 : BDR Electronics                            
Chip type               : ATmega8L
Program type            : Application
Clock frequency         : 8.000000 MHz
Memory model            : Small
External SRAM size      : 0
Data Stack size         : 256
*****************************************************/

#include 
#include 

// Alphanumeric LCD Module functions
#asm
   .equ __lcd_port=0x18 ;PORTB
#endasm
#include 

unsigned char LightIntensity=50;

////////////////////////////////////////////ok
void show_number(char a,char c,char temp) 
{                                         
unsigned char number[3];                 
char b;                                   
for(b=0;b<3;b++)                         
 {                                        
 number[b]=temp%10;                       
 temp/=10;                              
 _lcd_ready();                            
 lcd_gotoxy(a+1-b,c);                    
 lcd_putchar(number[b]|0x30);             
 }                                        
}                                         
////////////////////////////////////////////

/////////////////////////////////////////////////////////ok
// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
        { 
        //if (LightIntensity==0)
        PORTD.4=0;              
        //else
        //PORTD.4=0;
        }
/////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////ok
// Analog Comparator interrupt service routine
interrupt [2] void external_int0(void)
        {
        if (LightIntensity!=0)  
        PORTD.4=1;   
        else
        PORTD.4=0;
		
        TCNT1H=0x00;
        TCNT1L=0x00;
        }
/////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////
void SetTimers(void)
        {
        OCR1A=((unsigned int)(LightIntensity)*100);
        if(LightIntensity==100)
                TCCR1B = 0;
        else
                TCCR1B |= (1 << WGM12)|(1 << CS11);  
        //OCR1B=((int)(200-LightIntensity)*100);
        }
///////////////////////////////////////////

// Declare your global variables here
void main(void)
{
// Declare your local variables here
//char loop;
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0xff;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTD=0x00;
DDRD=0x11;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 7.813 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x0A;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
// OCR1AH=0x13;
// OCR1AL=0x88;
// OCR1BH=0x3a;
// OCR1BL=0x98;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: ON - Low triggered, I think better than falling edge and more reliable
// INT1: Off
GICR=0x40;
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;

// Analog Comparator initialization
// Analog Comparator: Off
// Interrupt on Output Toggle
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// LCD module initialization
lcd_init(16);

// Global enable interrupts

PORTD.4=1;
SetTimers();
#asm("sei")
lcd_gotoxy(0,0);
lcd_putsf("Light Intensity");
show_number(1,1,LightIntensity);
while (1)
      {
      while(PINC.5==0)
        {
        if(LightIntensity<99)
                LightIntensity+=5;
        SetTimers();
        lcd_gotoxy(0,0);    
        lcd_putsf("Light Intensity");
        show_number(1,1,LightIntensity);
        delay_ms(150);
        }
      while(PINC.2==0)
        {
        if(LightIntensity>0)
                LightIntensity-=5;
        SetTimers();
        lcd_gotoxy(0,0);
        lcd_putsf("Light Intensity");
        show_number(1,1,LightIntensity);
        delay_ms(150);
        }

      };
}

Signature: We need more peripherals in DIP packages. Namely, USB, 12-bit ADC, 16-bit timer, cheaper tool as a programmer/debugger coz STK600 is expensive! Atmel Studio 5/6 sucks! coz it brings MS visual studio crap to AVR world..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
TCCR1A=0x00;
TCCR1B=0x0A; 

So that is WGM10=0, WGM11=0, WGM12=1, WGM13=0. So that selects mode 4 which is CTC mode (OCR1A = TOP) and if you set WGM12=0 that selects "normal" mode.

So I guess your question is what's the difference between CTC and normal mode then?

Until PINC.2 or PINC.5 is set then I don't see anything touching OCR1A so it will hold 0x0000 I guess.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No, I understand the difference very well, my question is that, if I TCCR1B=0x02; and I never set WGM12, it also works, even when in mode 0, and the interrupt of match/compare simply fires after setting OCR1A, thu I don't set WGM12, why is that?

Signature: We need more peripherals in DIP packages. Namely, USB, 12-bit ADC, 16-bit timer, cheaper tool as a programmer/debugger coz STK600 is expensive! Atmel Studio 5/6 sucks! coz it brings MS visual studio crap to AVR world..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

CTC mode means that hardware resets TCNT1 as soon as it matches OCR1A. e.g. TCNT1 goes 0 -> 1234 -> 0 -> 1234

The COMPA interrupt fires at the match (1234)

If you are in regular mode, TCNT1 goes 0 -> 1234 -> 65535 -> 0 -> 1234 -> 65535 ...

You will get both the COMPA and OVF interrupts.

Now since 0-1234 (1235 ticks) is a lot shorter than 65536 ticks, the COMPA fires but a lot less frequently. i.e. F_CPU/div/65536 Hz instead of F_CPU/div/1235 Hz.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

the difference doesn't actually appear in the behavior, because TCNT1 is reset in INT0 handler.

If CTC is to be used, then it will reset TCNT1, then I have to add more lines to turn timer1 0ff, I think the code without WGM12 is better.

Signature: We need more peripherals in DIP packages. Namely, USB, 12-bit ADC, 16-bit timer, cheaper tool as a programmer/debugger coz STK600 is expensive! Atmel Studio 5/6 sucks! coz it brings MS visual studio crap to AVR world..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I think the code without WGM12 is better.

THen the purpose of this thread was pointless then? :P

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No, it was OK. Actually, after I read about CTC, I thought to use it, the code is not mine, it behaved the same, the point was that timer1 was set to 0 in INT0 handler, which yielded similar results.

I was wondering, once the COMPA interrupt is fired, while the top is OCR1A, inside the handler, should I set timer1 registers to 0 after I stop timer1 in order to ensure correct counting next time?

Signature: We need more peripherals in DIP packages. Namely, USB, 12-bit ADC, 16-bit timer, cheaper tool as a programmer/debugger coz STK600 is expensive! Atmel Studio 5/6 sucks! coz it brings MS visual studio crap to AVR world..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you are actually stopping the timer, then yes, you should set TCNT1 to 0 before starting the timer again.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi again, I've seen semitone using this formula to calculate the phase angle control timings, how can I implement it correctly in my case? I don't really understand how to do it, I know perl, but there are many things I understand not, can someone please explain what these formulas do, how can I make it 100 steps? Once I gain more understanding, I can modify perl code to generate a c array. Actually, I need to understand these lines and how to modify them correctly:

my $use_period = 8.4 / 1000; # seconds
my $timer_start = 880; # old: 54200;
my $pulse_width = 16;

Attachment(s): 

Signature: We need more peripherals in DIP packages. Namely, USB, 12-bit ADC, 16-bit timer, cheaper tool as a programmer/debugger coz STK600 is expensive! Atmel Studio 5/6 sucks! coz it brings MS visual studio crap to AVR world..