WinAVR, c++ и прерывания
Добавлено: Чт май 12, 2011 09:51:27
Подскажите как прикрутить обработчик прерывания к классу c++.
Компилятор - avr-gcc из WinAVR.
Компилятор - avr-gcc из WinAVR.
Здесь можно немножко помяукать :)
https://radiokot.ru:443/forum/
Код: Выделить всё
#include <avr/interrupt.h>
ISR(TIMER0_OVF_vect);
class Foo {
...
private:
friend void TIMER0_OVF_vect();
inline void Isr();
uint8_t cnt;
};
Foo foo;
void Foo::Isr() { ++cnt; }
void TIMER0_OVF_vect()
{
foo.Isr();
}На avrfreaks поищите C++ interrupt, там несколько тем было год-два назад.apwork писал(а):Спасибо за информацию. Буду пробовать. Хотя со статичной функцией класса было бы интереснее.
В том же в чём и впихивание всего остального -- «приватизация» того, что не должно быть видно снаружи при сохранении быстрого доступа, некоторое разделение интерфейса и реализации, ...Мастер Ломастер писал(а):а в чем смысл впихивания обработчика в класс?
возможно, пока я корректировал свое сообщение - вы как раз отвечалиavreal писал(а):Каждый канал - единственный экземпляр «себя» с двумя собственными обработчиками прерываний (внешнее прерывание и таймерное COMPARE). Но все одни -- потомки общего PaсketReceiver и уровнем выше все думают, что вот в этом массиве -- указатели именно на задействованные PacketReceiver, а не на те, нарушающие «непременное условие», единственные экземпляры производных классов.
Но каждый «листовой» класс при этом имеет единственный экземпляр, а топикстартер не упоминал, его классы самостоятельные, или чьи-то потомкиМастер Ломастер писал(а):упоминание об улучшении стройности программы за счет иерархии классов - это как раз ваш случай. это я понимаю и могу с этим согласиться без возражений.
Если остальная программа и так на плюсах (а это отдельный разговор, который шире обсуждения одного какого-то модуля-класса), то никакого специального перехода не будет.Мастер Ломастер писал(а):меня смутил единственный экземпляр единственного класса с обработчиком прерываний - по сравнению с отдельным модулем никаких преимуществ не имееющий, как мне кажется, но требующий перехода на заведомо более сложный инструмент С++. т.е. налицо возрастание сложности решения без заметной выгоды...
Код: Выделить всё
fprintf_P( uart, ...... );Код: Выделить всё
FILE uart_file = FDEV_SETUP_STREAM(uart_putchar, ...);
#define uart (&uart_file)Код: Выделить всё
static inline unsigned GetSystemTimer()
{
extern volatile unsigned sys_timer;
return sys_timer;
}Код: Выделить всё
#define CLASS_IRQ(name, vector) \
static void name(void) asm(__STRINGIFY(vector)) \
__attribute__ ((signal, __INTR_ATTRS))Код: Выделить всё
class CTimer0Interrupt
{
public:
CTimer0Interrupt();
~CTimer0Interrupt();
private:
CLASS_IRQ(OverflowInterrupt, TIMER0_OVF_vect);
};Код: Выделить всё
//***************************************************************
// Timer0Interrupt.cpp
//
#include "Timer0.h"
#include "Timer0Interrupt.h"
extern CTimer0 Timer0;
//----------
CTimer0Interrupt::CTimer0Interrupt()
{
TCNT0 = TIMER0_TIMEOUT;
TCCR0 = 0x04;
TIMSK |= (1<<TOIE0); // enable overflow interrupts
}
//----------
CTimer0Interrupt::~CTimer0Interrupt()
{
TIMSK &= ~(1<<TOIE0); // disable Timer0 timeout interrupt
}
//----------
void CTimer0Interrupt::OverflowInterrupt(void)
{
TCNT0 = TIMER0_TIMEOUT; // restart the timeout
Timer0.SetOverflowFlag(); // tell our friend of the event
}Код: Выделить всё
class CTimer0
{
friend class CTimer0Interrupt;
public:
CTimer0();
~CTimer0();
int GetTimer0Flags(void);
private:
void SetOverflowFlag(void);
private:
volatile int mTimer0Flags;
CTimer0Interrupt mTimer0Interrupt;
};
void CTimer0Interrupt::OverflowInterrupt(void)
{
TCNT0 = TIMER0_TIMEOUT; // restart the timeout
Timer0.mTimer0Flags |= TIMER0_OVERFLOW;
}а в чем смысл впихивания обработчика в класс?
На мой взгляд, класс, от которого в программе существует в принципе единственный экземпляр -- вполне нормальное явление.
Код: Выделить всё
class Usart
{
...
static void RxHandler()
{
char byte = UDR;
...
}
...
};
...
ISR(USART_RXC_vect)
{
Usart::RxHandler();
}