Hallo zusammen!
Momentan erzeugen meine 3 Timer konstant IRQs. Das funktioniert auch im CTC Mode.
Das Problem: Jetzt möchte ich aber in der ISR des Timer1 den Timer0 bzw Timer 2 starten. Diese sollen "Singleshot" Timer sein. Bisher habe ich diese am Anfang vor der while(1) Schleife Prescale etc initialisiert. um jetzt den Timer zu starten, setze ich jetzt in der Timer1 ISR
Code:
OCR0A = x-1; TIMSK0 |= (1 << OCIE0A);
Die Timer0 ISR macht ihre Aktion und soll dann sich selbst wieder stoppen mit
Code:
TIMSK0 &= ~(1 << OCIE0A);
Geht das prinzipell oder ist das unmöglich dass der Atmega168 in einer TimerISR einen anderen Timer startet? Bzw seine "eigenen" IRQ register beschreibt?
Der Atmega168 läuft mit 16 MHz.
Hier ist mein Code:
Code:
#include <stdlib.h>
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "i2cmaster.h"
#include "uart.h"
// -----------------------------------------------------
// defines for better readability
// -----------------------------------------------------
// Leds
#define led_alive_on() (PORTC |= (1<<PC0))
#define led_alive_off() (PORTC &= ~(1<<PC0))
// timer
#define start_timer0(x) { OCR0A = x-1; TIMSK0 |= (1 << OCIE0A);}
#define start_timer2(x) { OCR2A = x-1; TIMSK2 |= (1 << OCIE2A);}
#define stop_timer0() (TIMSK0 &= ~(1 << OCIE0A))
#define stop_timer2() (TIMSK2 &= ~(1 << OCIE2A))
// EEPROMs
#define EEPROM_SERVO_1 0b01010000
#define EEPROM_SERVO_2 0b01010001
// Baud rate
#define UART_BAUD_RATE 38400
// -----------------------------------------------------
// global variables
// - communication of IRQ routines with main loop
// - communication if pin change irqs with impuls generation
// -----------------------------------------------------
// status of live led
volatile bool b_live_led = false;
volatile uint16_t gi_cnt = 0;
// -----------------------------------------------------
// io handling
// -----------------------------------------------------
void init_io()
{
DDRB = 0b00000000; // All inputs
DDRC = 0b11111111; // All outputs
DDRD = 0b11111000; // mixed in-/outputs
PORTB = 0b11111001; // set inputs to high
PORTC = 0b00000000; // set outputs to low
PORTD = 0b00000111; // set inputs to high
}
// -----------------------------------------------------
// Timer handling
// -----------------------------------------------------
void init_timer(void)
{
// prescalefactor settings is equal at timer 0 and 1. Timer 2 is different
// ((16.000.000 MHz / 64) = 250 kHz Prescaleclock;
// ----------------------------
// Timer 1
// ----------------------------
TCCR1A = 0; // CTC Mode
TCCR1B = ((1<<WGM12) | (1<<CS01) | (1<<CS00)); // prescale factor 64
OCR1A = 2500-1;
TIMSK1 |= (1 << OCIE1A);
// ----------------------------
// Timer 0
// ----------------------------
TCCR0A = 0; // CTC Mode
TCCR0B = ((1<<WGM12) | (1<<CS11) | (1<<CS10)); // prescale factor 64
// ----------------------------
// Timer 2
// ----------------------------
TCCR2A = 0; // CTC Mode
TCCR2B = ((1<<WGM12) | (1<<CS22)); // prescale factor 64
}
// Timer ISR
ISR(TIMER1_COMPA_vect)
{
// Debug
if (++gi_cnt > 100)
{
led_alive_on();
start_timer0(250);
gi_cnt = 0;
}
}
// set servo output off for servo 1
ISR(TIMER0_COMPA_vect)
{
led_alive_off();
stop_timer0();
#if 0
// regular ISR
// set output off for servo 1
servo1_off();
stop_timer0();
#endif
}
ISR(TIMER2_COMPA_vect)
{
led_alive_off();
stop_timer0();
return;
#if 0
// regular ISR
// set output off for servo 2
servo2_off();
stop_timer2();
#endif
}
// -----------------------------------------------------
// main loop
// - handle modes
// - handle I2C storage, save and read
// -----------------------------------------------------
int main(void)
{
// io port directions
init_io();
// init timer at 1ms rate
init_timer();
// init the UART library
uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));
// allow all interrupts
sei();
// endless loop
while(1)
{
// check mode switch
static uint8_t s_old_mode_switch_status = 0;
static uint8_t s_new_mode_switch_status = 0;
s_new_mode_switch_status = is_mode_switch_on();
if (s_new_mode_switch_status && !s_old_mode_switch_status)
{
gb_mode++;
if (gb_mode > MODE_REPLAY)
gb_mode = MODE_DIRECT;
}
s_old_mode_switch_status = s_new_mode_switch_status;
// mode direct
if (gb_mode == MODE_DIRECT)
{
// leds
led_mode_direct_on();
led_mode_capture_off();
led_mode_replay_off();
// only display active led for debug purpose
}
// mode capture
else if (gb_mode == MODE_CAPTURE)
{
// leds
led_mode_direct_off();
led_mode_capture_on();
led_mode_replay_off();
}
// mode replay
else if (gb_mode == MODE_REPLAY)
{
// leds
led_mode_direct_off();
led_mode_capture_off();
led_mode_replay_on();
}
}
}
Gruß
Georg
Lesezeichen