Перейти к содержанию

Mega8535 Пропуск Прерывания


tire

Рекомендуемые сообщения

Здраствуйте, ATmega8535 должна помимо основного алгоритма считать обороты ДВС.

Алгоритм прост: Первый спадающий уровень на RD6 запускает TIM1 (16b) второй останавливает (дальше код обеспечения расчета)

Для контроля периода измерения мигает диод на RB0, а для задержки 300мс диод RB1 ... но захват надо делать нечаще 300мс. и как-раз запрет захвата он не-выполняет (осцилоскопом подтверждаеться)

Еще вопрос: Допустимо запрещать прерывание из тела обработчика прерывания ?

/*****************************************************
               CodeVision v2.03.5  Evaluation
  Отладка модуля измерения частоты вращения.

Chip type           : ATmega8535
Program type        : Application
Clock frequency     : 8,867000 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 128
Сигнал на RD6 T = 10ms.
*****************************************************/
#include <mega8535.h>
#include <io.h>
#include <DELAY.H>

#define SET_B(z) |= (1<<z) 
#define CLR_B(z) &= ~(1<<z) 

volatile char tem;
const char T_ind = 11;

volatile char KEY ;      //   1 тригер захвата взведен !

// конец модуля обявления переменых
// ++++++++++++++++++++++++++++++++++++++++++++++
interrupt [TIM1_CAPT ] void tim1_capt_isr (void) { 
// обработчик тахометра. 
       if(KEY  != 0){
               PORTB.0 = 1;    // гасим диод "измерение" RB0 НАЛАДКА                 
               TCCR1B = 0;    // останавливаем счетчик
               KEY = 0;   // зброс тригера захвата.
               PORTD.2 = 1; // вызываем прерывание контроля индикации.
       }
       else if(KEY == 0){
              TCNT1 = 0; 
              TCCR1B = 3;        // запускаем счетчик с делителем 1:64                      
              KEY = 1;        // взводим тригер захвата
              PORTB.0 = 0;    // светим диод "измерение" RB0 НАЛАДКА.
       }
}         // конец обработчика тахометра.
// =================================================
interrupt [EXT_INT0 ] void ext_int0_isr (void) { 
// обработчик контроля времени индикации.
         TIMSK CLR_B(5) ;    // запрет прерывания по ICP
         PORTB.1 = 0;      // наладка
         // разрешаем работу таймера TIM0 F = F_CPU/1024
         TCCR0 = 0b00000101;   
         TIMSK SET_B(0);        
         PORTD.2 = 0;  // сброс бита вызова 
}
// =================================================
interrupt [TIM0_OVF ] void tim0_ovf_isr (void) { 
// обработка прерывания переполнения TIM0
       tem = tem + 1;
       if(tem > T_ind){ 
               TCCR0 = 0; // останавливаем таймер TIM0
               TIMSK SET_B(5) ;    // прерывания по ICP
               PORTB.1 = 1;    // наладка
       }
}
//============= ПОДПРОГРАММЫ =====================
void  Inicializacion(void){
// инициализация регистров.
       PORTA = 0xFF;
       DDRA  = 0x00;

       PORTB = 0xFF;        // 0-1 диоды контроля
       DDRB  = 0x03;      

       PORTC = 0xFF;      
       DDRC  = 0x00; 

       PORTD = 0xF0; 
       DDRD  = 0x24;

       MCUCR = 0x03;      // INT0 по нарастающему уровню. 
       TIMSK = 0b00100000;         // разрешаем прерывания по ICP
       GICR SET_B(6);           // разрешим прерывание по INT0
       TCNT1 = 0;                // збросим счетчик.
       TCCR1B = 3;        // запускаем счетчик с делителем 1:64
         #asm("sei")                // разрешаем глобальные прерывания.
       KEY = 0;
}

void main(void) // ++++++++++ ГЛАВНЫЙ МОДУЛЬ ++++++++++     
{
       Inicializacion();  
// основной цыкл +++++++++++++++++++++++++++++++++++++        
       while (1){
                       PORTB.1 = 1;
                       delay_ms(1);
                       PORTB.1 = 0;
                       delay_ms(1);
     };
}
// конец блока main

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Я тоже думал что должны запрещаться при входе в обработчика.. Я знаю что наоборот если обработчик не сильно критичный то разрешали чтобы не пропускал ещё чего...

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

C данным компилятором ни когда не работал. Поэтому как предположение: Функция delay_ms(1); случаем ни чего не делает с прерываниями. По идеи обеспечить точность можно либо таймером, либо запретом прерываний. Таймер она не задействует, остается выяснить, как она работает с прерываниями

Это сообщение поставляется "как есть", без каких либо гарантий. Автор сообщения не несёт какой либо ответственности

за материальный, либо моральный ущерб причиненный данным сообщением напрямую или косвенно.

Ссылка на комментарий
Поделиться на другие сайты

если смущает функция delay_ms(1), можно ее заменить простой прогонкой пустого цикла типа for ... количество итераций выбрать исходя из тактовой частоты и требуемого времени задержки, если нужен запрет прерывания на время задержки, можно использовать команду глобального запрета прерываний cli...

а из тела обработчика действительно нет смысла запрещать - при вызове обработчика прерывания автоматически сбрасывается бит глобального разрешения прерываний, и устанавливается обратно только при вызове команды reti

Ссылка на комментарий
Поделиться на другие сайты

В бесконечном цыкле while функция задержки введена только для примера, полная программа намного обширней.

Файл прилагаю .

Тотже алгоритм реализовывал в AVRStudio 4.14 (таже лажа только с вариациями !!!) При этом в симуляторе все ОК!

:blink:

taxo.rar

Ссылка на комментарий
Поделиться на другие сайты

Уточняю вопрос:

Надо запретить действующее прерывание чтобы при следующем событии не вызывалось.

Я пытался делать внутри обработчика конкретного прерывания (захват ICP) , отрицательный результат.

В выше представленном коде и в пробном варианте, в начале темы, вызывал промежуточный обработчик по INT0(RD2), и уже там запрещал прерывание захват по ICP(RD6), опять не то :( .

Из основной проги все работает кроме тахометра.

Ссылка на комментарий
Поделиться на другие сайты

Приветствую. Всех.

Честно говоря, опять не понял из вопроса, что нужно автору, поэтому расскажу нюансы работы прерывания у AVR(а)

Значит сначала прописные истины. Для управления прерываниями используется глобальный флаг управления прерываниями включает\выключает обработку всех прерываний у МК. Также имеются индивидуальные флаги управления прерываниями (включают\выключают конкретные прерывания). Как это работает я уверен автор знает и понимает.

Теперь нюансы. Допустим у нас индивидуально разрешены три прерывания, и мы разрешили глобальную обработку прерываний. У нас произошел вызов первого прерывания. При вызове обработчика прерывания AVR автоматически запрещает глобальный вызов прерываний. Это понятно. Но что произойдет, если при обработки первого прерывания произойдет вызов второго и третьего прерывания. Ответ: AVR по выходу из первого прерывания вызовет обработчик второго и третьего (в зависимости от паритета) прерывания. Кстати как это работает, хорошо, видно в симуляторе AVR Studio. Может Вы не учитываете этот нюанс.

Если нет, попробуйте задать вопрос прям по Вашему коду.

P.S.

Еще раз перечитал вопрос автора и помойму проблема именно, что я написал выше. Как бороться: при выходе из прерывания в ручную сбросить флаги наступления событий соответствующих прерываний (для внешних прерываний это регистр GIFR для таймеров это TIFR). Не забываем, что сброс осуществляется записью «1»! На мой взгляд, не очень хорошо так делать.

Это сообщение поставляется "как есть", без каких либо гарантий. Автор сообщения не несёт какой либо ответственности

за материальный, либо моральный ущерб причиненный данным сообщением напрямую или косвенно.

Ссылка на комментарий
Поделиться на другие сайты

хм.. а если организовать какой нибудь переменную-триггер, который будет отражать необходимость обработки прерывания... т.е. если нужно запретить прерывание - установить его в "1", а в обработчике, когда он будет вызван, проверить этот триггер, и если он будет равен "1" выйти из прерывания, ничего не делая, иначе продолжить штатное выполнение обработчика... способ, конечно не слишком красивый, но работать по идее должно...

Ссылка на комментарий
Поделиться на другие сайты

Опишу грабли на которые сам наступал

сделал прерывание по спаду фронта на ноге, но по той же ноге слал данные

и когда слал програмно дергал ногу 1 0 1 0, и при этом прерывание было вЫключено,

потом когда я его включал почему-то вызывался обработчик,

прочитав даташит я понял, что когда дергал ногой, то флаг прерывания устанавливался, и когда я включал прерывание, вызывался автоматом обработчик

у меня это как раз и было ваше "и как-раз запрет захвата он не-выполняет "

Ссылка на комментарий
Поделиться на другие сайты

Проблему решил. Все просто.

Из программы на Си флаг прерывания нельзя сбросить (компилятор не даст).

Флаг прерывания сбрасывается автоматом при вызове ответствующего обработчика.

Об этом читал но не придал значения !!!

В программе сделал дополнительный флаг, в общем смотрите код пробной программы.

/*****************************************************
               CodeVision v2.03.5  Evaluation
  Отладка модуля измерения частоты вращения.

Chip type           : ATmega8535
Program type        : Application
Clock frequency     : 8,867000 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 128
Сигнал на RD6 T = 6--200ms.
*****************************************************/

#include <util/delay.h>
#include <avr/interrupt.h>

#define SET_B(z) |= (1<<z) 
#define CLR_B(z) &= ~(1<<z)
#define INV_B(z) ^=(1<<z) 

volatile char x;
volatile char KEY;
volatile unsigned int temp;

// конец модуля обявления переменых
// ++++++++++++++++++++++++++++++++++++++++++++++
ISR(TIMER1_CAPT_vect)	// обработчик тахометра.
{	
if((KEY & 0x02) == 0)	// если нет сброса то пролетаем
{
	if((KEY & 0x01) != 0)
	{
		temp = ICR1;
		TIMSK CLR_B(5);	// запрещаем.
		PORTB SET_B(0);	//  гасим.
		KEY SET_B(1);	// ставим служебный флаг.
	}
	else
	{
		PORTB CLR_B(0);	// сигнализируем.
		KEY SET_B(0);	// ставим служебный флаг.
		TCNT1 = 0;
		TIFR CLR_B(5);	// сброс флага прерывания.
	}
}
}         // конец обработчика тахометра.

//============= ПОДПРОГРАММЫ =====================
void  Inicializacion(void){
// инициализация регистров.
       PORTA = 0xFF;
       DDRA  = 0x00;
	 //PINA = 0xFF;

       PORTB = 0xFC;        	// 0-1 контроль
       DDRB  = 0x03; 
 	 //PINB = 0xFC;     

       PORTC = 0xFF;      
       DDRC  = 0x00; 
	 //PINC = 0xFF;

       PORTD = 0xFF;   		// RD6 вход.	
       DDRD  = 0x00;
	 //PIND = 0xFF;

       TCCR1B = 0x03;      	// запускаем счетчик T1 с делителем 1:64
       TIMSK SET_B(5);    // разрешаем прерывания по ICP   

         asm("sei");       	// разрешаем глобальные прерывания.
}
// ==============================================

// ++++++++++ ГЛАВНЫЙ МОДУЛЬ ++++++++++ 
int main(void)     
{
       Inicializacion();  
// основной цыкл +++++++++++++++++++++++++++++++++++++        
       while (1)
	{
		asm("nop");
       	x++;
       	if(x > 100)x = 0;
		asm("nop");
		if((KEY & 0x02) != 0)
		{
			PORTB CLR_B(1);
			_delay_ms(100);
			PORTB SET_B(1);

			TIMSK SET_B(5);	// разрешение захвата.
			asm("nop");		// необходима задержка для выполнения прерывания !!!
			KEY = 0;		// збрасываем
		}
     	};
}
// конец блока main

За подсказки спасибо , тема решена.

Ссылка на комментарий
Поделиться на другие сайты

Чесно говоря в первую очередь меня интересовал флаг захвата по ICP.

Но писать 1, для сброса флага прерывания ? вот черт, я пытался сбросить нулем ! <_<

Опять поспешил чтоли ? Щас буду побывать.

Ссылка на комментарий
Поделиться на другие сайты

Испробовал ! Верно, для сброса флага прерывания необходимо записать "1" в соответствующий бит регистра флагов.

Сброс проверил как в симуляторе AVR Studio 4.14 так и в макете, все работает !!!

Пробный код теперь выглядит так:

/*****************************************************
               CodeVision v2.03.5  Evaluation
  Отладка модуля измерения частоты вращения.

Chip type           : ATmega8535
Program type        : Application
Clock frequency     : 8,867000 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 128
Сигнал на RD6 T = 6--200ms.
*****************************************************/

#include <util/delay.h>
#include <avr/interrupt.h>

#define SET_B(z) |= (1<<z) 
#define CLR_B(z) &= ~(1<<z)
#define INV_B(z) ^=(1<<z) 

volatile char x;
volatile char KEY;
volatile unsigned int temp;

// конец модуля обявления переменых
// ++++++++++++++++++++++++++++++++++++++++++++++
ISR(TIMER1_CAPT_vect)	// обработчик тахометра.
{	
	if((KEY & 0x01) != 0)
	{
		temp = ICR1;
		TIMSK CLR_B(5);	// запрещаем.
		PORTB SET_B(0);	//  гасим.
		KEY SET_B(1);	// ставим служебный флаг.
	}
	else
	{
		PORTB CLR_B(0);	// сигнализируем.
		KEY SET_B(0);	// ставим служебный флаг.
		TCNT1 = 0;
	}
}         // конец обработчика тахометра.

//============= ПОДПРОГРАММЫ =====================
void  Inicializacion(void)
{...инициализация...
       TCCR1B = 0x03;      	// запускаем счетчик T1 с делителем 1:64
       TIMSK SET_B(5);    // разрешаем прерывания по ICP   

         asm("sei");       	// разрешаем глобальные прерывания.
}
// ==============================================

// ++++++++++ ГЛАВНЫЙ МОДУЛЬ ++++++++++ 
int main(void)     
{
       Inicializacion();  
// основной цыкл +++++++++++++++++++++++++++++++++++++        
       while (1)
	{
		asm("nop");
       	x++;
       	if(x > 100)x = 0;
		asm("nop");
		if((KEY & 0x02) != 0)
		{
			PORTB CLR_B(1);
			_delay_ms(100);
			PORTB SET_B(1);	// контроль.
			TIFR SET_B(5);	// сброс ложного захвата.
			TIMSK SET_B(5);	// разрешение захвата.
			KEY = 0;		// сбрасываем
		}
     	};
}
// конец блока main

Ссылка на комментарий
Поделиться на другие сайты

  • 3 недели спустя...

#define SET_B(z) |= (1<<z)

..

TIFR SET_B(5); // сброс ложного захвата.

обратите внимание, что это стратегическая ошибка!

для примера TIFR==0b11 и мы хотим сбросить нулевой бит, тогда выполнив TIFR=(TIFR | 0b01) мы получим TIFR=0b11, МК обработает это так, будто мы хотели сбросить оба бита! И так мы теряем флаг другого прерывания!

если мы запишем TIRF=0b01 , МК обработает это так, как мы и собирались, т.е. сбросит нулевой бит. (т.к. чтобы сбросить бит, нужно записать в него 1).

Т.е. записывая ноль в какой-либо бит, мы не меняем его значения ( он как был 1 так и останется 1, или как был 0 так и останется 0) ,

НО записывая единицу - делаем NOT для бита. ( не тестил этого, но что 1 он сбрасывает в 0 это точно)

В вашем случае нужно писать

#define SET_B(z) |= (1<<z)

TIFR = (1<<5); // сброс ложного захвата.

Изменено пользователем hohlov
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...