"Приоритеты" в случае прерываний AVR определяют, какое обработается раньше, если оба возникли, когда прерывания были запрещены. И даже в таком понимании приоритетов, PCINT идут сразу за INTx, то есть, первыми, если INTx неактивны или вызываются редко. Так что никакой необходимости тянуть проводки к INTx нет.
Что за ноги таймера
Таймер он внутри тикает у него ног нету
"ноги таймера" - выводы, которые могут обрабатываться модулем таймера без участия ядра. Например, OC1A, T0, ICP. При правильной настройке, разумеется.
Будет ли работать данный код на других AVR контроллерах?
У всех контроллеров есть Timer0, он везде восьми разрядный?
Может быть разное количество настроек и, соответственно, разное количество регистров TCCR0A, кроме того, может быть отдельный TIMSK0. Насчет разрядности - да, T0 и T3 всегда 8-разрядные.
Project : Dozimetr
Version : 1.0
Date : 05.11.2014
Author :
Company :
Comments:
Chip type : ATmega324P
Program type : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 512
*******************************************************/
#include <mega324.h>
#include <delay.h>
// I2C Bus functions
#include <i2c.h>
//#include <Display.h>
// Declare your global variables here
int i = 1;
int counterTime = 0;
int counterPulse = 0;
int countR = 0;
// структура определяе следующие сосотояния:
// sTime - 1 - было прерывание от таймера
// sPulse - 1 - было прерывание от импульса
// sOn - 1 - прибор включен
// sOff - 1 - прибор выключен
// sRejim - 10 - режим 1, 01 - режим 2, 11 - режим 3.
//
struct Flag
{
char sTime;
char sPulse;
char sOn;
char sOff;
char sRejim;
}sFlag;//={0x0,0x0,0x0,0x0,0x01};
// Функция работы с дисплем
void Display(int num)
{
// точка - 0x80
// массив содержит цифры от 0 - 9 в переводе на значения сегментов
char Zahl[10] = {0x3f,0x6,0x5b,0x4f,0x66,0x6d,0x7d,0x27,0x7f,0x6f};
//char Zahl[10] = {0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x72,0x7f,0x7b};
//char Zahl_4[10] = {0x3f,0x6,0x5b,0x4f,0x66,0x6d,0x7d,0x27,0x7f,0x6f};
int j;
int led_data[2]; // массив количества символов на ЖКИ
int temp = 0;
i2c_start(); // Issue start signal
i2c_write(0x70); // Address SAA 1064
i2c_write(0); // Start
i2c_write(0x27); // config
//a=temp/100 для вывода сотен
//b=temp%100/10 для вывода десятков
//с=temp%100%10 для вывода единиц
temp = num;
j = 0;
while (j <= 1)
{
if (j != 0) temp /= 10;
led_data[j] = Zahl[temp %10];
j++;
}
// if (num<1000) led_data[3] = 0x7e;
// if (num<100) led_data[2] = 0x7e;
if (num<10) led_data[1] = 0x3f;
// Add decimal point if required
//led_data[1] |= 0x80;
// Auto increment applies for digit data. Have to send out digits in reverse
// because most significant digit is 1st digit.
// i2c_write(0x01);
for (j=2;j>=1;j--)
{
i2c_write(led_data[j-1]);
}
i2c_stop();
}
// Функция инициализации аналогово компаратора
void InitializeComparator()
{
// Analog Comparator initialization
// AIN0 подключаем к источнику внутреннего опорного напряжения. AIN1 используется как простой выход.
// Analog Comparator: On
// К подключаем AIN0 внутрений источник опорного напряжения ACBG = 1
ACSR = (0<<ACD) | (1<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (1<<ACIS1) | (0<<ACIS0);
ADCSRB = (1<<ACME); // включаем мультиплексар аналогового компаратора
ADCSRA = (0<<ADEN); // сбрасываем бит ADEN для отключения АЦП
// ADMUX = (0<<MUX2) | (0<<MUX1) | (0<<MUX0); // Выбираем вход АЦП - ADC0
// Digital input buffer on AIN0: Off
// Digital input buffer on AIN1: On
// DIDR1=(1<<AIN0D) | (0<<AIN1D);
}
// Функция инициализации портов
void InitializePort()
{
// Input/Output Ports initialization
// Port A initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRA = 0x00;
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTA = 0x00;
Сделал TIMSK1 &= ~(1<<TOIE1); результат тот же. Проблема скорее всего в переменной sFlag.sOn. Если правильно понял всегда происходит инициализация таймера.
Сделал по другому: объявил переменную в eeprom - eeprom int StatusOn = 0; и через нее провожу инициализацию. Но почему то при объявлении eeprom int StatusOn = 0 0 не записываеться. Отлаживаю в протеусе, может ли быть косяк в протеусе? или всетаки у меня?
Извините за глупые вопросы.. недавно программирую(
переменная sFlag.sOn отвечает за состояние включения прибора. Если она равна 0 то прибор включается впервые и проходит инициализация его. В конструкции if ( sFlag.sOn = 0) {инициализация}. Затем этой переменной присваиваю 1. Теперь по логике когда выходит из прерывания и заходит в main(), то т.к. sFlag.sOn = 1 инициализация таймера проходить не будет.
Всем большое спасибо! разобрался. Проблема именно в переменной sOn. Она почему то не держит состояние в 1. Сейчас инициализацию таймера провожу по нажатию на кнопку. Все работает.
DarkWolf писал(а):Всем большое спасибо! разобрался. Проблема именно в переменной sOn. Она почему то не держит состояние в 1. Сейчас инициализацию таймера провожу по нажатию на кнопку. Все работает
А, понятно, я этот вариант не рассматривал т.к. думал что она "состояние держит" =)
А вы отладчиком не пользуетесь чтоли? Можно было бы легко такое отловить.
Добрый вечер! Можно ли включить два ISR в Atmega128 что бы они не мешали друг другу при срабатывании одного из прерываний, пока обрабатывается одно прерывание другое не останавливалось?
Нет один МК Atmega128. Мне нужно что бы две разные задачи в одном МК обрабатывались независимо друг от друга, как две программы на компе которые не мешают работе одна - другой.
Раньше я справлялся с данной задачей разбивая паузу на миллисекунды и делал обработку нажатия кнопок, теперь задача усложнилась и как-то надо выходить из тупика.
А на компе тоже задачи друг другу "мешают". Только их пишут так, что это почти незаметно.
Полной параллельности можно добится использованием FPGA, но к контроллерам это практически не относится.
Использовать delay_ms() - только в крайнем случае.
Касательно кода в первом посте - это называется вложенные прерывание. Но они также используются в экзотических ситуациях и при полном понимании происходящего.
alexey6522,А зачем вам вообще пауза(delay_ms) нужна? Делайте её так что бы в это время выполнялся другой кусок кода. Или по таймеру.
Почитайте вот тут про флаговые автоматы может это не много прояснит. http://easyelectronics.ru/avr-uchebnyj- ... gramm.html
Так же ещё можно по смотреть статьи Владимира Татарчевского "Применение SWITCH-технологии при разработке прикладного программного обеспечения для микроконтроллеров".
И если у вас задача на опрос кнопок, то в 8 части там как раз приведен пример драйвера клавиатуры (без всяких прерываний).
Здравствуйте уважаемые коты.
Всех с Новым годом и Рождеством.
В общем такое дело, решил в новом году научиться программировать AVR, подопытный ATtiny2313. Светодиодом наморгался вволю, динамическую индикацию освоил, сейчас разбираюсь с Т/С1. Пытаюсь освоить режим захвата со входа ICP(PD6), Евстифеева мышкой до дыр затёр (и не только его). ДШ распечатал, но так и не нашёл как эту ногу (ICP) активировать, в каком регистре нужно поставить 1. B DDRD эта ножка вход, вектор прерывания указан, настройки таймера:
;========= инициализация TIM1 ================
ldi temp1,(1<<ICIE1) ; разрешение прерывания по захвату ( ICP)
out TIMSK,temp1 ;
ldi temp1,(1<<ICES1)|(1<<CS10) ; активный перепад 0>1, такт 1/1
out TCCR1B,temp1 ;
sei ;
rjmp Main ;
В симуляторе студии если принудительно ставлю флаг этого прерывания то прога переходит в обработчик, а если "дрыгаю" ножкой в порту D, то прерывания не происходит. Что нужно ещё сделать?
Включил не помогло, да и как могло помочь если ACIC наоборот отключает вход ICP от таймера, а подключает выход компаратора. Выключил модуль компаратора совсем - без изменений. нет прерывания.
P.S. Ну в общем разобрался с симулятором, просто не давно работаю со студией и всех нюансов ещё не знаю. Оказывается сэмулировать сигнал на входе ICP можно только тогда, когда он настроен как выход И после наступления события захвата таймер не сбрасывается аппаратно, об этом нигде ни слова Ладно будем копать дальше.
pazak писал(а): Оказывается сэмулировать сигнал на входе ICP можно только тогда, когда он настроен как выход...
Студии 3.21 и 4.19 отрабатывают чётко активный перепад на PIND6 (ICP1) независимо от настройки этой лапы.
pazak писал(а):... И после наступления события захвата таймер не сбрасывается аппаратно, об этом нигде ни слова...
В режиме захвата модуль ICP1 и не должен этого делать. Другое дело, использование модуля ICP1 в качестве регистра сравнения с автосбросом. Но для этого и нужна соответствующая настройка по Table 46. Waveform Generation Mode Bit Description(1)
Т.к. достоверно не знаю всех событий произошедших на лапе PIND6 (ICP1) до разрешения прерываний, чищу флаг ICF1
;========= инициализация TIM1 ================
ldi temp1,(1<<ICIE1) ; разрешение прерывания по захвату ( ICP)
out TIMSK,temp1 ;
OUT TIFR,temp1 ;!!!!!!!!!!!!!!!!!!!!!
ldi temp1,(1<<ICES1)|(1<<CS10) ; активный перепад 0>1, такт 1/1
out TCCR1B,temp1 ;
sei ;
rjmp Main ;