Пишу простенькую прогу для простенького регулятора скорости для PPM RC радиаппаратуры..
Для обработки длительности управляющего импульса решил использовать линию прервыания INT1 настроенную на формирования прерывания по смене логического сотояния на входе INT1.
Решив проверить жив ли пациент или мертв (я про ПРОЕКТ) в PROTEUS (пробовал даже в симуляторе AVR Studio), был приятно удивлен тем, что при смене уровня вхождения в обработчик не происходит. При настройке на falling edge или rising edge обработчик выполняется. Пробовал по линиям INT1 и INT0 - ничего не происходит... Пробовал компилировать в AVR Studio и CodeVision - борода... Пробовал компилировать под Mega8 и Mega16 - нет слов... В общем виню архитектуру AVR. Специально прошуршил даташит и убедился в том, что вектор прерывания falling edge/Any logical change/The low level/The rising edge (для INT1) один и тот же (для ряда кристалов используются ветор Pin Change Interrupt Request X для обработки смены уровня).
Помогите товарищи!!!! Поясните почему в режиме Any logical change не выполняется обработчик прерывания?
Листинг в AVR STUDIO:
- Код: Выделить всё
#include <avr/io.h>
#include <avr/interrupt.h>
#define FTACT 1000000 //тактовая частота процессора Гц
#define F_TIMER1_TACT 0.001 //(мс) периодичность счета таймера1 Гц
#define PPM_PER 20 //(мс) период упр имп
#define PPM_MIN 0.8 //(мс) минимальная длительнось упр имп (крайнее левое полож)
#define PPM_MID 1.5 //(мс) средняя длительнось упр имп центральное полож)
#define PPM_MAX 2.2 //(мс) максимальная длительнось упр имп (крайнее правое полож)
#define PPM_NORM_CONST (F_TIMER1_TACT*65536)/((PPM_MAX -PPM_MIN)/F_TIMER1_TACT) //константа для приведения получ длит имп-а к нормальному виду
#define c_FORV_motion 1 // прямое движение
#define c_BACKW_motion 0 // обратное движение
typedef struct // тип - структура описывающая входной канал
{
unsigned int v_mot_speed_LEV; // скорость вращения
unsigned char v_mot_speed_DIR; // направление движения мотора
unsigned char v_PPM_prev_LEV; // предыдущее значеие уровня упр сигнала
} T_PPM_INPUT;
T_PPM_INPUT CH1; // создаем 1- й входной канал
// External Interrupt 0 service routine
//interrupt [EXT_INT1] void ext_int1_isr(void)
ISR(INT1_vect)
{
PORTB=(PORTB^1);// так для проверки вхождения в перывание!
if (CH1.v_PPM_prev_LEV==0) //передний фронт
{
// начать счёт
TCNT1H=0x00;
TCNT1L=0x00;
CH1.v_PPM_prev_LEV=1;
TCCR1B=0x01;// запуск таймера 1
}
else //задний фронт
{
TCCR1B=0x00; //остановка таймера 1
CH1.v_mot_speed_LEV =TCNT1L; // cначала читаем младшие разряды / старшие пишутся в ТЕМП
CH1.v_mot_speed_LEV |=TCNT1H<<8;// Считать старшие из ТЕМП
CH1.v_mot_speed_LEV*= PPM_NORM_CONST;
if (CH1.v_mot_speed_LEV>0x7FFF) //больше половины
CH1.v_mot_speed_DIR=c_FORV_motion;
else
CH1.v_mot_speed_DIR=c_BACKW_motion;
CH1.v_PPM_prev_LEV=0;
}
}
// Timer 2 overflow interrupt service routine
//interrupt [TIM2_OVF] void timer2_ovf_isr(void)
ISR(TIMER2_OVF_vect)
{
if (CH1.v_mot_speed_DIR)
{PORTB|=1<<2;
PORTB&=~(1<<1);}
else
{PORTB|=1<<1;
PORTB&=~(1<<2);}
OCR2 = (CH1.v_mot_speed_LEV>>8);
}
// Timer 2 output compare interrupt service routine
//interrupt [TIM2_COMP] void timer2_comp_isr(void)
ISR(TIMER2_COMP_vect)
{
if (CH1.v_mot_speed_DIR)
PORTB&=~(1<<2);
else
PORTB&=~(1<<1);
}
// Declare your global variables here
int main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=Out Func1=Out Func0=out
// State7=T State6=T State5=T State4=T State3=T State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0x07;
// 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=0x00;
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=0x00;
// 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: 1000,000 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: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 31,250 kHz
// Mode: Fast PWM top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x4B;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: On
// INT1 Mode: Any change
// INT2: Off
GICR|=0x80;
MCUCR=0x04;
MCUCSR=0x00;
GIFR=0x80;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0xC0;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// Global enable interrupts
sei();
CH1.v_PPM_prev_LEV=0;
while (1)
{
// Place your code here
};
}