Hello,
I've made a four microseconds precision chronometer for a futur RC5 remote control decoder.
This chronometer is based on 16bits timer-1 on ATmega168. The big feature of this code is to generate an interrupt only for 100ms !
Here the code :
/* 4us precision chronometer
* -------------------------
*
* Chronometer with a four microsecond of precision based on
* 16bits internal timer-1 of ATmega168.
* Only one interrupt by 100ms.
*
*
* Created by Vincent Le Gouic in 27th January 2009
* Copyleft 2009
* France
*
*/
// Variables definition
uint16_t microseconds = 0, milliseconds = 0;
uint8_t seconds = 0, minutes = 0, hours = 0;
// Interrupt service routines
ISR(TIMER1_COMPA_vect) // Timer-1 OC1A Match interrupt handler
{
milliseconds += 100;
if (milliseconds == 1000)
{
milliseconds = 0;
seconds++;
}
if (seconds == 60)
{
seconds = 0;
minutes++;
}
if (minutes == 60)
{
minutes = 0;
hours++;
}
}
// Reset chronometer
void reset_chrono(void)
{
unsigned char sreg;
sreg = SREG; // Save global interrupts flag
cli(); // Disable interrupts
TCNT1 = 0; // Reset timer-1 counter
SREG = sreg; // Restore global interrupts flag
milliseconds = 0;
seconds = 0;
minutes = 0;
hours = 0;
}
// Read microseconds counter
uint32_t read_microseconds(void)
{
uint32_t microseconds;
unsigned char sreg;
sreg = SREG; // Save global interrupts flag
cli(); // Disable interrupts
microseconds = TCNT1*4; // one timer-1 count for 4us
SREG = sreg; // Restore global interrupts flag
return microseconds;
}
// Setup
void setup(void)
{
Serial.begin(9600); // Open serial port with 9600bps
// Set timer-1 parameters
TCCR1A = 1<<WGM10 | 1<<WGM11; // Fast PWM mode enabled with 16bits registers
TCCR1B = 1<<CS10 | 1<<CS11 | 1<<WGM12 | 1<<WGM13; // Fixe clock for timer1 F_CPU=16MHz/64 (prescaler)
OCR1A = 24999; // Set the top limit counter to 24999
TIMSK1 = 1<<OCIE1A; // Enable interrupt on 0C1A match
sei(); // Enable interrupts
}
// Main loop
void loop(void)
{
char char_readed = 0;
char_readed = Serial.read(); // Read serial port character
if (char_readed == 0x31) // Type "1" to reset chronometer
{
reset_chrono();
Serial.println("Reset chronometer");
}
if (char_readed == 0x32) // Type "2" to print chronometer time
{
uint32_t microseconds_count = 0;
uint16_t milliseconds_display = 0, microseconds_display = 0, milliseconds_rest = 0;
microseconds_count = read_microseconds();
milliseconds_rest = (uint16_t)(microseconds_count/1000); // Take the two most important digits (decimal value) of microseconds counter
milliseconds_display = milliseconds + milliseconds_rest; // Add rest to milliseconds hundred
microseconds_display = (uint16_t)(microseconds_count-(uint32_t)(milliseconds_rest*1000)); // Conserve microseconds
Serial.print(hours, DEC);
Serial.print("h ");
Serial.print(minutes, DEC);
Serial.print("m ");
Serial.print(seconds, DEC);
Serial.print("s ");
Serial.print(milliseconds_display, DEC);
Serial.print("ms ");
Serial.print(microseconds_display, DEC);
Serial.print("us ");
Serial.println();
}
}
I think that can be useful for people because I don't find a clear code for microsecond timer an internet.
Thanks at all who are guide me to solution with their code. ![]()
Bye.