Moving Timer/Counter/ISR into Tick.c and Tick.h files

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

Newbie.  AS6.2  I'm having trouble moving Timer/Counter/ISR elements into Tick.c and Tick.h files.  Not sure what needs to go into .h vs .c, and what other declarations need to be made.  I've had no troubles with other .h and .c file separation.  Here is the main code which compiles fine:

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//#include "Adc.h"
#include "Display.h"
#include "IoPins.h"
#include "Power.h"
//--------------------------------VARIABLES-GLOBAL (use sparingly) Use CamelCase------------------------------------------------
volatile int TickFlag = 0;				// Tick Flag is volatile, since it changes in the ISR
//--------------------------------MACROS------------------------------------------------
//--------------------------------CONSTANTS (use CAPS)------------------------------------------------
//--------------------------------MAIN------------------------------------------------
int main(void) 
{
	PowerOn();					// Initialize MCU
	
	// TIMER/COUNTER DETAILS
	TCCR1B |= (1 << WGM12);				// Configure 16bit Timer/Counter 1 for CTC mode
	TIMSK1 |= (1 << OCIE1A);			// Enable CTC interrupt
	sei();						// Enable global interrupts
	OCR1A   = 15624;				// Set CTC compare value to 1Hz at 1MHz AVR clock, with a prescaler of 64
	TCCR1B |= ((1 << CS10) | (1 << CS11));	        // Start timer at Fcpu/64
	// END TIMER/COUNTER DETAILS
	
	while (1)					// MAIN loop starts
		{
			if (TickFlag == 1)
			{
				PORTB ^= (1 << LED01);	// Toggle the LED
				TickFlag = 0;
			}
		}
	return (0);					// end MAIN loop
}
//--------------------------------END MAIN------------------------------------------------

//--------------------------------ISR------------------------------------------------
	ISR(TIMER1_COMPA_vect)
	{
		TickFlag = 1;
	}

 

So, the parts I want to move to new Tick.h and Tick.c files would be:

volatile int TickFlag = 0;				// Tick Flag is volatile, since it changes in the ISR

and

	// TIMER/COUNTER DETAILS
	TCCR1B |= (1 << WGM12);				// Configure 16bit Timer/Counter 1 for CTC mode
	TIMSK1 |= (1 << OCIE1A);			// Enable CTC interrupt
	sei();						// Enable global interrupts
	OCR1A   = 15624;				// Set CTC compare value to 1Hz at 1MHz AVR clock, with a prescaler of 64
	TCCR1B |= ((1 << CS10) | (1 << CS11));	        // Start timer at Fcpu/64
	// END TIMER/COUNTER DETAILS

and

//--------------------------------ISR------------------------------------------------
	ISR(TIMER1_COMPA_vect)
	{
		TickFlag = 1;
	}

 

I need help figuring out what elements should go where, and what additional things need to be added for it to compile.  All kinds of multiple definition errors.  I've tried swapping things around.  Suggestions appreciated ... thanks!

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

Tick.c:

#include <avr/io.h>
#include <avr/interrupt.h>
#include "Tick.h"

volatile int TickFlag = 0;				// Tick Flag is volatile, since it changes in the ISR

void tick_init(void) 
{
	TCCR1B |= (1 << WGM12);				// Configure 16bit Timer/Counter 1 for CTC mode
	TIMSK1 |= (1 << OCIE1A);			// Enable CTC interrupt
	sei();						// Enable global interrupts
	OCR1A   = 15624;				// Set CTC compare value to 1Hz at 1MHz AVR clock, with a prescaler of 64
	TCCR1B |= ((1 << CS10) | (1 << CS11));	        // Start timer at Fcpu/64
}
//--------------------------------END MAIN------------------------------------------------

//--------------------------------ISR------------------------------------------------
	ISR(TIMER1_COMPA_vect)
	{
		TickFlag = 1;
	}

Tick.h:

#ifndef TICK_H
#define TICK_H

extern volatile int TickFlag;				// declare externs
extern void tick_init(void); 

#endif 

 

You don't really need the "include guard" TICK_H.    Or to include "Tick.h" in "Tick.c",    but it ensures consistency.

 

Note that I really don't like your statement order or style in tick_init().   It will work ok,   but think about it.

 

David.

Last Edited: Wed. Jan 14, 2015 - 08:40 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Go to the tutorial forum and find an article by abcminiuser about "Managing large projects". It will tell you all about this kind of "splitting". The key thing that comes out of it is the use of  "extern".

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

Why is TickFlag an int when a uint8_t will do?

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

Why is TickFlag an int when a uint8_t will do?

In fact if you want to be "real clever" you can make it a single bit in GPIOR0 (assuming a "modern" AVR) and the access code will be the most efficient SBI/CBI and SBIC/SBIS for the test.

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

Thanks!  It works now.  I think I forgot the "extern"

 

David,  You don't like the order of this?:

void tick_init(void) 
{
	TCCR1B |= (1 << WGM12);				// Configure 16bit Timer/Counter 1 for CTC mode
	TIMSK1 |= (1 << OCIE1A);			// Enable CTC interrupt
	sei();						// Enable global interrupts
	OCR1A   = 15624;				// Set CTC compare value to 1Hz at 1MHz AVR clock, with a prescaler of 64
	TCCR1B |= ((1 << CS10) | (1 << CS11));	        // Start timer at Fcpu/64
}

Maybe, are you saying, that sei(); should come first?  Or, are you saying something else ... ?

 

Kartman, I earlier had a warning where the compiler warned 'int' was implied, so I added it.  If I change it to 'uint8_t', the compiler then gives an error 'conflicting types for TickFlag'.  So, I've changed it back to 'int'.

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

I am saying that I would write:

void tick_init(void) 
{
	TCCR1B = (1 << WGM12)|(3 << CS10);	        // PWM#4 (CTC), Fcpu/64
	OCR1A   = 15624;				// F_CPU/64/1 - 1 i.e. 1sec @ 1MHz
	TIMSK1 |= (1 << OCIE1A);			// Enable CTC interrupt
	sei();						// Enable global interrupts
}

i.e. I would try to use = rather than |=

and set OCR1A before enabling the SEI

 

but there are good arguments for your sequence i.e. 'start' as last operation.   I would still prefer = when initialising the mode.

 

Personal preference.   Your code should work fine if it is the first thing from reset.

 

David.

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

Ok ... thanks!