Страница 1 из 2
attiny13 и PCINT0 в железе
Добавлено: Вт мар 16, 2021 19:17:33
Land
Собственно суть проблемы. К ногам тиньки 5 и 6 (РВ0 и РВ1) подключены две кнопки. Инициализированы прерывания PCINT0 и, в качестве источника прерываний, определены две ноги:
Спойлер
Код: Выделить всё
#define BUTTON_LUX_MEMORY PB1 //вход определения нажатой кнопоки 1
#define BUTTON_SYGNAL PB0 //вход определения нажатой кнопоки 0
GIFR |= (1<<INTF0) | (1<<PCIF); // сброс флагов прерывания
PCMSK |= (1<<BUTTON_LUX_MEMORY) | (1<<BUTTON_SYGNAL); //прерывания по входам PCINT0, PCINT1 (PB0, PB1)
GIMSK |= (1<<PCIE); //разрешаем внешние прерывание
В обработчике прерывания определяю какая кнопка нажата и выполняю нужный код
Спойлер
Код: Выделить всё
ISR (PCINT0_vect) //обработка прерывания кнопки
{
GIMSK &= ~(1<<PCIE); //запрещаем прерывания
GIFR |= (1<<INTF0) | (1<<PCIF); // сброс флагов прерывания
TCCR0B = 0x00; //останоавливаем таймер
asm("wdr"); //сброс WDT
PORTB |= (1<<LED_OUT_PIN);
_delay_ms(500); //пауза 500 мС
if bit_is_clear (PINB,BUTTON_LUX_MEMORY)
{
MEM_value_LUX = read_adc(LUX_IN_PIN); eeprom_write_word(&LUX_MEM,MEM_value_LUX); //измеряем уровень освещенностиeeprom, записываем в
}
if bit_is_clear (PINB,BUTTON_SYGNAL)
{
NUM_SYGNAL+=1; while (NUM_SYGNAL == 7) {NUM_SYGNAL=0x01;} eeprom_write_byte(&SYGNAL_MEM,NUM_SYGNAL);
switch (NUM_SYGNAL)
{
case 1: SYGNAL=0xAA; break;
case 2: SYGNAL=0xCC; break;
case 3: SYGNAL=0xF0; break;
case 4: SYGNAL=0x63; break;
case 5: SYGNAL=0xD4; break;
default: SYGNAL=0xE6; break;
}
}
_delay_ms(500);
PORTB &= ~(1<<LED_OUT_PIN);
GIFR |= (1<<INTF0) | (1<<PCIF); // сброс флагов прерывания
TCCR0B |= (1<<CS02); // запуск таймера
в симулятора 7 студии все отрабатывает без вопросо. Но в железе у меня получается бесконечный цикл вызова прерыания, при этом виновником является вход РВ1 (BUTTON_LUX_MEMORY). Если програмно я не определяю этот вход как источник прерывания (PCMSK |= (1<<BUTTON_SYGNAL);), то кнопка на РВ0 (BUTTON_SYGNAL) работает без нареканий. Заходим в прерывание, выполняем нужное действие, возвращаемся в основной цикл.
Осциллограмма на РВ1 в норме, напряжение питания стоит, никаких дерганий уровня не видно.
Может у кого есть идеи, в какую сторону копать?
Re: attiny13 и PCINT0 в железе
Добавлено: Вт мар 16, 2021 20:43:59
NStorm
Код: Выделить всё
GIMSK &= ~(1<<PCIE); //запрещаем прерывания
GIFR |= (1<<INTF0) | (1<<PCIF); // сброс флагов прерывания
Это - лишнее. Прерывания глобально и так запрещаются при входе в ISR, а флаг прерывания сбрасывается по выходу.
Вы нигде PB1 не дергаете случаем из программы? Ну вот, например, чему равно LED_OUT_PIN?
Ну и чтение АЦП и запись в EEPROM из ISR - очень плохая идея. В прерывании просто поднимайте флаг (переменная), что надо это сделать. А сам замер + запись делайте в основном коде. Там уже предварительно перед записью в EEPROM отключив временно глобально прерывания через cli(), а потом включив через sei().
Re: attiny13 и PCINT0 в железе
Добавлено: Вт мар 16, 2021 20:51:34
Land
NStorm,
Код: Выделить всё
#define LED_OUT_PIN PB3 //выход на светодиоды
что прерывания глобально запрещаются, а флаги сбрасываются -- знаю. Но вряд-ли эти строки загоняют контроллер в цикл с прерываниями. Но для красоты кода -- уберу.
Т.е. вы считаете, что в цикл падаю из-за чтения adc и записи в eeprom ? Ок, как рабочую версию приму, проверю. Спасибо
Re: attiny13 и PCINT0 в железе
Добавлено: Вт мар 16, 2021 21:23:33
parovoZZ
а флаг прерывания сбрасывается по выходу.
При входе в обработчик.
Re: attiny13 и PCINT0 в железе
Добавлено: Вт мар 16, 2021 21:25:42
ARV
Вообще-то обрабатывать прерывание одну секунду - это, имхо, явно не хорошо.
Re: attiny13 и PCINT0 в железе
Добавлено: Вт мар 16, 2021 21:30:00
parovoZZ
В тиньке13 PCINT на что реагирует? На смену уровня или на уровень? Если на уровень, то так и не будете вылезать из прерывания, пока не сменится уровень на ноге.
Добавлено after 1 minute 30 seconds:
[uquote="ARV",url="/forum/viewtopic.php?p=3998445#p3998445"]Вообще-то обрабатывать прерывание одну секунду - это, имхо, явно не хорошо.[/uquote]
Если прерывание одно, то по фигу. Можно из него вообще не вылезать. Да даже если и не одно. Как в MSP430...
Re: attiny13 и PCINT0 в железе
Добавлено: Вт мар 16, 2021 21:33:59
Land
[uquote="ARV",url="/forum/viewtopic.php?p=3998445#p3998445"]Вообще-то обрабатывать прерывание одну секунду - это, имхо, явно не хорошо.[/uquote]
аргументируйте, плз.
Добавлено after 2 minutes 24 seconds:
[uquote="parovoZZ",url="/forum/viewtopic.php?p=3998446#p3998446"]В тиньке13 PCINT на что реагирует? На смену уровня или на уровень? Если на уровень, то так и не будете вылезать из прерывания, пока не сменится уровень на ноге.[/uquote]
PCINT реагирует на любое изменение уровня на ноге.
Re: attiny13 и PCINT0 в железе
Добавлено: Вт мар 16, 2021 21:51:40
NStorm
Land писал(а):[uquote="parovoZZ",url="/forum/viewtopic.php?p=3998446#p3998446"]В тиньке13 PCINT на что реагирует? На смену уровня или на уровень?[/uquote]
Только на смену.
Land писал(а):аргументируйте, плз.
В любом учебнике, во многих мануалах это написано - обработчик прерывания должен быть как можно более коротким. По разным причинам. Хотя бы потому что в это время у вас не будут выполняться другие прерывания, зато потом "выстрелят" отложенно и можете на этом поиметь грабли.
Land писал(а):Т.е. вы считаете, что в цикл падаю из-за чтения adc и записи в eeprom ? Ок, как рабочую версию приму, проверю. Спасибо
Это не может быть прямой причиной, но вот много всяких граблей бывает из-за долгой обработки прерывания. Лучше сразу привыкайте никогда так не делать, даже когда кажется, что в данном случае неважно.
Опять же в read_adc() и при работе с LUX_IN_PIN нигде не можете затрагивать скажем весь регистр PORTB? Случайно где-нибудь вместо R-M-W сделали присваивание может... Ну или приведите весь код в конце концов.
Re: attiny13 и PCINT0 в железе
Добавлено: Вт мар 16, 2021 22:01:37
parovoZZ
А я вот вижу сброс вачдога, сброс флага INT0....либо это сделано со знанием дела, но сия тайна великая есть, либо это откуда-то "нахапано" кусками. Пока я склоняюсь к версии
затрагивать скажем весь регистр PORTB?
В любом учебнике, во многих мануалах это написано - обработчик прерывания должен быть как можно более коротким.
Это кто-то придумал, а другие тупо скопипастили. Старые тиньки никак не предназначены для обработки прерывания вне его - флаги сбрасываются в прерывании, поэтому надо свои вводить, если обработчик пустой. Либо же лупом проверять флаги постоянно...Вообщем, костыльные микры...
Re: attiny13 и PCINT0 в железе
Добавлено: Вт мар 16, 2021 22:09:27
Land
[uquote="NStorm",url="/forum/viewtopic.php?p=3998472#p3998472"]Опять же в read_adc() и при работе с LUX_IN_PIN нигде не можете затрагивать скажем весь регистр PORTB? Случайно где-нибудь вместо R-M-W сделали присваивание может... Ну или приведите весь код в конце концов.[/uquote]
я же не случайно написал, что программное отключение генерации прерывания по РВ1 убирает проблему. Если бы где-то затрагивался весь регистр PORTB, то...
Добавлено after 3 minutes 53 seconds:
[uquote="parovoZZ",url="/forum/viewtopic.php?p=3998479#p3998479"]А я вот вижу сброс вачдога, сброс флага INT0....либо это сделано со знанием дела, но сия тайна великая есть, либо это откуда-то "нахапано" кусками. Пока я склоняюсь к версии
затрагивать скажем весь регистр PORTB?
[/uquote]
думаете wdr зацикливает в прерывании? Или сброс флага INT0 вызывает сбой? Само-собой, как у каждого, у меня есть свои куски кода и я пользуюсь копи-пастом... пока объем памяти позволяет. Если не позволяет -- перехожу на asm.
Re: attiny13 и PCINT0 в железе
Добавлено: Вт мар 16, 2021 22:10:39
parovoZZ
Глянул даташит и понял
PB1 (MISO/AIN1/OC0B/INT0/PCINT1)
По умолчанию INT0 сидит на прерывании по уровню. Если разрешить на INT0 прерывание, то, как я и говорил, из прерывания вылезать не будем при нуле на этом пине. Если обработчика вообще нет, то компилятор GCC выполнение кода по вектору уводит на ресет...
Re: attiny13 и PCINT0 в железе
Добавлено: Ср мар 17, 2021 00:52:13
Самсусамыч
[uquote="Land",url="/forum/viewtopic.php?p=3998361#p3998361"]Собственно суть проблемы. К ногам тиньки 5 и 6 (РВ0 и РВ1) подключены две кнопки. Инициализированы прерывания PCINT0 и, в качестве источника прерываний, определены две ноги:[/uquote]
Попробуй… прошивка для тини13… кнопки на РВ0 и РВ1… светики на РВ3 и РВ4…
Фьюзы прошивать не нужно, тактируется на заводских установках (1,2 МГц).
Test_INT.hex
Нажал кнопку – светик загорелся. Нажал повторно – потух.
Re: attiny13 и PCINT0 в железе
Добавлено: Ср мар 17, 2021 05:30:43
NStorm
[uquote="Land",url="/forum/viewtopic.php?p=3998484#p3998484"]я же не случайно написал, что программное отключение генерации прерывания по РВ1 убирает проблему. Если бы где-то затрагивался весь регистр PORTB, то...[/uquote]
То что "то"? То нет. Вы можете остальные пины и не менять, программа по другим пинам будет как надо работать.
parovoZZ писал(а):Это кто-то придумал, а другие тупо скопипастили. Старые тиньки никак не предназначены для обработки прерывания вне его - флаги сбрасываются в прерывании, поэтому надо свои вводить, если обработчик пустой. Либо же лупом проверять флаги постоянно...Вообщем, костыльные микры...
Не совсем. Это стандартная практика. Никаких проблем нет вести свои флаги, их можно вполне расширить и не просто тупо копировать о срабатывании прерывания. Дело не в этом.
Re: attiny13 и PCINT0 в железе
Добавлено: Ср мар 17, 2021 07:49:49
Demiurg
1 - кнопки это человекоинтерфейс. Реакция человека десятки, сотни миллисекунд. Реакция микроконтроллера, если кнопка повешана на прерывание - несколько тактов. Хочется спросить, куда вы так торопитесь, все равно не успеете.
На прерывание есть смысл вешать кнопки только в случае энергосбережения, спящего режима. Ещё в случае экономии ввода вывода. И то варианты.
2 - дребезг контактов.
3 - режим внешнего прерывания, по уровню или фронту.
Как здесь уже правильно подметили, могут быть неучтенные отложенные прерывания.
Вывод, разберитесь что такое дребезг контактов. Какие режимы внешнего прерывания, как правильно инициализировать внешние прерывания. И нужно ли вешать кнопки на внешние прерывания, если нет энергосбережения.
Re: attiny13 и PCINT0 в железе
Добавлено: Ср мар 17, 2021 08:49:19
akl
Разрешать прерывания логическим ИЛИ не совсем хорошо. Как вариант, простое повторение состояния кнопок с жестким разрешением прерывания PCINT
Спойлер
Код: Выделить всё
.INCLUDE "tn13def.inc"
.CSEG
.ORG $000
RJMP START
.ORG $002
IN R22,PINB
RETI
;*************************************************
START:
CBI ACSR,ACD
SBI DDRB,2
SBI DDRB,3
LDI R16, 0b00000011
OUT PORTB, R16
LDI R16,1<<PCINT1|1<<PCINT0
OUT PCMSK, R16
LDI R16,1<<PCIE ;PCIE: разрешение прерывания при смене состояния лапы
OUT GIMSK, R16
OUT GIFR,R16
LDI R16,1<<SE
OUT MCUCR,R16
SEI
WAIT_PCINT:
SLEEP
ANDI R22,0b00000011
LSL R22
LSL R22
ORI R22,0b00000011
OUT PORTB,R22
RJMP WAIT_PCINT
.EXIT
Re: attiny13 и PCINT0 в железе
Добавлено: Ср мар 17, 2021 09:37:58
parovoZZ
Дело не в этом.
А в чём же?
В прерывании засыпать нельзя, иначе можешь не проснуться. Но это только в AVR. В других МК позволяется всё.
Re: attiny13 и PCINT0 в железе
Добавлено: Ср мар 17, 2021 11:38:09
Land
[uquote="NStorm",url="/forum/viewtopic.php?p=3998597#p3998597"][uquote="Land",url="/forum/viewtopic.php?p=3998484#p3998484"]я же не случайно написал, что программное отключение генерации прерывания по РВ1 убирает проблему. Если бы где-то затрагивался весь регистр PORTB, то...[/uquote]
То что "то"? То нет. Вы можете остальные пины и не менять, программа по другим пинам будет как надо работать.[/uquote]
то, что если бы что-то писалось в PORB тупо в лоб, то это бы вызывало в том числе и прерывание по PB0. А здесь проблема в РВ1. POTB упоминается в коде 7 раз:
Код: Выделить всё
PORTB |= (1<<BUTTON_LUX_MEMORY) | (1<<BUTTON_SYGNAL); //входы кнопок (инициализация)
PORTB &= ~(1<<LED_OUT_PIN);
PORTB |= (1<<LED_OUT_PIN);
PORTB &= ~(1<<LED_OUT_PIN);
PORTB |= (1<<LED_OUT_PIN);
PORTB &= ~(1<<LED_OUT_PIN);
PORTB &= ~(1<<LED_OUT_PIN);
Что самое забавное, зацикливание происходит даже при простой инициализации входа PB1 в качестве источника прерывания. В обработчике ISR можно вообще все закомментить, относящееся к обработке этого пина. Если кому не лень в чужом коде колупаться, листинг под катом. Ткните меня носом. Только, умоляю, не в wdr
Спойлер
Код: Выделить всё
#define F_CPU 1200000UL // 1.2 MHz
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <avr/sfr_defs.h>
#include <avr/sleep.h>
#include <util/delay.h>
// Declare your global variables here
#define LED_OUT_PIN PB3 //выход на светодиоды
#define Ubat_IN_PIN (1<<MUX0) //вход измерения напряжения батареи Ubat_IN_PIN ADC1D
#define BUTTON_LUX_MEMORY PB0 //вход определения нажатой кнопоки 1
#define BUTTON_SYGNAL PB1 //вход определения нажатой кнопоки 0
#define LUX_IN_PIN (1<<MUX1) //вход измерения уровня освещения LUX_IN_PIN ADC2D
#define ADC_VREF_TYPE ((0<<REFS0) | (0<<ADLAR)) //рефернесное напряжение для АЦП -- напряжение питания
uint16_t LUX_MEM EEMEM; //создаем метку адреса для значения освещенности в EEPROM
unsigned char SYGNAL_MEM EEMEM; //создаем метку адреса для сигнала мигания uint8_t
volatile unsigned char TIMER_CYCLE; //счетчик циклов таймера для мигания
volatile unsigned char SYGNAL=0xAA; //вид сигнала мигания по умолчанию
unsigned char NUM_SYGNAL=1; //номер сигнала мигания
//unsigned char BUTTON; //номер кнопки 1- запись уровня освещенности, 2 - изменение номера сигнала мигания
volatile unsigned char TIMER_SLEEP; //счетчик таймера сна
unsigned char mask; //локальная переменная маски
uint16_t value_LUX=0; //уровень освещенности с датчика
//uint16_t value_BUTTON=0; //нажатая кнопка
volatile uint16_t MEM_value_LUX; //сохраненное значение value_LUX
void key_func(void);
void sygnal_out(unsigned char);
unsigned char bat_level(void);
void LUX_level(void);
uint16_t read_adc(int);
// Pin change interrupt service routine
/*===================== ФУНКЦИИ =======================*/
void init(void)
{
// Declare your local variables here
// Port B initialization
DDRB |= (1<<LED_OUT_PIN); //выход
PORTB |= (1<<BUTTON_LUX_MEMORY) | (1<<BUTTON_SYGNAL); //входы кнопок
// INT0: Off
GIFR |= (1<<INTF0) | (1<<PCIF); // сброс флагов прерывания
PCMSK |= (1<<BUTTON_SYGNAL);//(1<<BUTTON_LUX_MEMORY) | (1<<BUTTON_SYGNAL); //прерывания по входам PCINT0, PCINT1 (PB0, PB1)
// Analog Comparator: Off
//ADCSRA |= (1<<ADPS0) | (1<<ADPS1);
ADCSRB &= ~(1<<ADTS2) & ~(1<<ADTS1) & ~(1<<ADTS0);
ADMUX |= (1<<AIN0D) | (1<<AIN1D); // Digital input buffer on AIN0: Off Digital input buffer on AIN1: Off
// ADC enabled
ADCSRA |= (1<<ADPS0) | (1<<ADPS1); // ADPS2=1, ADPS1=0,ADPS0=0 -- коэфф. делителя 8
ADMUX &= ~(1<<REFS0);
DIDR0 |= (1<<Ubat_IN_PIN) | (1<<LUX_IN_PIN); // | (0<<ADC3D); //ADC10 -- VCC, ADC20 -- LUX
// Timer/Counter 0 initialization
TCCR0A = 0x00;
TIMSK0 |= (1<<TOIE0); //прерывания по переполнению разрешены
TCNT0 = 0x00;
OCR0A = 0x00;
OCR0B = 0x00;
//MCUCR |= (1<<SM1); //режим POWER DOWN (1<<SE) Sleep Enable
// Watchdog timeout action: Reset + Interrupt
asm("wdr");
WDTCR |= (1<<WDCE) | (1<<WDE);
WDTCR |= (1<<WDTIF) | (1<<WDTIE) | (1<<WDP0) | (1<<WDP3); // | (1<<WDIE) разрешаем прерывание WDT, 8 сек.
MEM_value_LUX = eeprom_read_word(&LUX_MEM); //читаем из памяти сохраненное значение уровня освещенности
}
/*====================*/
uint16_t read_adc(int adc_input)
{
TCCR0B = 0; //останов таймера
ADMUX= adc_input | ADC_VREF_TYPE;
_delay_us(10); // Delay needed for the stabilization of the ADC input voltage
ADCSRA|=(1<<ADEN)|(1<<ADSC); //Запускаем преобразование
while ((ADCSRA & (1<<ADIF))==0); //Wait for the AD conversion to complete
ADCSRA|=(1<<ADIF); // сброс флага прерывания
ADCSRA &= ~(1<<ADEN); //останавливаем преобразование
return ADCW;
}
void sleepy(void)
{
cli();
TCCR0B = 0x00; //останоавливаем таймер
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //устанавливаем режим сна Power Down
// set_sleep_mode(SLEEP_MODE_IDLE);
// WDTCR |= (1<<WDTIE); // //запускаем WDT
sleep_enable();
sei(); // Globally enable interrupts
}
unsigned char bat_level(void)
{
//модуль измерения и индикации низкого напряжения батареи
//PCMSK |= (1<<BUTTON_LUX_MEMORY) | (1<<BUTTON_SYGNAL); //разрешаем прерывания
TIMER_CYCLE = 0x00; //счетчик циклов таймера
uint16_t value_VCC=0; //определяем локальные переменные
value_VCC = read_adc(Ubat_IN_PIN); //измеряем напряжение батареи
if (value_VCC < 0x239) {SYGNAL=0xA8;} else //если напряжение ниже 1.6В (3.2В/2), то выставляем сигнал аларма, иначе
{NUM_SYGNAL = eeprom_read_byte(&SYGNAL_MEM); //читаем значение номера сигнала из EEPROM
switch (NUM_SYGNAL)
{
case 1: SYGNAL=0xAA; break;
case 2: SYGNAL=0xCC; break;
case 3: SYGNAL=0xF0; break;
case 4: SYGNAL=0x63; break;
case 5: SYGNAL=0xD4; break;
default: SYGNAL=0xE6; break;
}
}
return SYGNAL;
}
void LUX_level(void)
{
GIFR |= (1<<INTF0) | (1<<PCIF); // сброс флагов прерывания
GIMSK |= (1<<PCIE); //разрешаем внешние прерывание
value_LUX = read_adc(LUX_IN_PIN); //измеряем уровень освещенности
asm("wdr"); //сброс WDT
if (value_LUX > MEM_value_LUX)
{TIMER_SLEEP = 0x80; PORTB &= ~(1<<LED_OUT_PIN); sleepy(); //TIMER_SLEEP = 0x80 !!!!!!!!!!!!!!!!
while (TIMER_SLEEP)
{
sleep_cpu(); // спим
}
LUX_level(); //перепроверяем уровень освещенности
} //иначе -- спим 0x25 = 37 циклов таймера сна = 5 мин
//else {;}
{mask=0x80; TIMER_SLEEP = 0xFF;} // ,если темно, разрешаем прерывания, запускаем WDT ; sygnal_out(SYGNAL) TIMER_SLEEP = 0xFF !!!!!!!!!!!!!!!!
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int main(void)
{
init();
LUX_level();
bat_level();
while (1)
{
TIFR0 |= (1<<TOV0); //сброс флага переполнения TIMR0
TCCR0B |= (1<<CS02); //прескалер /256 1.2Mhz/256=1171.875 Hz Period 0.055 sec.
TIMER_CYCLE = 0x00; //счетчик циклов таймера
sei();
//while (TIMER_SLEEP != 0)
while(1)
{
while (TIMER_CYCLE == 0) //если TMER_CYLE = 0, выполняем вложенное
{
if (SYGNAL & mask) //проверяем по маске бит выводимого сигнала логическое "или"
{
PORTB |= (1<<LED_OUT_PIN); //если в результате 1, выставляем 1
}
else
{
PORTB &= ~(1<<LED_OUT_PIN); //если в результате 0, выставляем 0
}
mask = mask >> 1; while (mask == 0) mask=0x80; //сдвинуть маску. обновить маску
TIMER_CYCLE = 0x03; //обновить счетчик таймера
GIFR |= (1<<INTF0) | (1<<PCIF); // сброс флагов прерывания
GIMSK |= (1<<PCIE); //разрешаем внешние прерывание
if (TIMER_SLEEP == 0) LUX_level(); else{}
}
}
}
}
// External Interrupt 0 service routine
ISR (PCINT0_vect) //обработка прерывания кнопки
{
GIMSK &= ~(1<<PCIE); //запрещаем прерывания
GIFR |= (1<<INTF0) | (1<<PCIF); // сброс флагов прерывания
TCCR0B = 0x00; //останоавливаем таймер
asm("wdr"); //сброс WDT
PORTB |= (1<<LED_OUT_PIN);
_delay_ms(250); //пауза 500 мС
if bit_is_clear (PINB,BUTTON_LUX_MEMORY)
{
PORTB &= ~(1<<LED_OUT_PIN);
//MEM_value_LUX = read_adc(LUX_IN_PIN); //измеряем уровень освещенности
//eeprom_write_word(&LUX_MEM,MEM_value_LUX); // записываем в память eeprom
}
if bit_is_clear (PINB,BUTTON_SYGNAL)
{
NUM_SYGNAL+=1; while (NUM_SYGNAL == 7) {NUM_SYGNAL=0x01;} eeprom_write_byte(&SYGNAL_MEM,NUM_SYGNAL);
switch (NUM_SYGNAL)
{
case 1: SYGNAL=0xAA; break;
case 2: SYGNAL=0xCC; break;
case 3: SYGNAL=0xF0; break;
case 4: SYGNAL=0x63; break;
case 5: SYGNAL=0xD4; break;
default: SYGNAL=0xE6; break;
}
}
_delay_ms(500);
PORTB &= ~(1<<LED_OUT_PIN);
GIFR |= (1<<INTF0) | (1<<PCIF); // сброс флагов прерывания
TCCR0B |= (1<<CS02); // запуск таймера
}
// Timer 0 overflow interrupt service routine
ISR (TIM0_OVF_vect)
{
--TIMER_CYCLE; // Декремент счетчика циклов таймера
}
ISR(WDT_vect) // Watchdog timeout interrupt service routine// обработка прерыания WDT
{
//cli();
MCUSR &= ~(1<<WDRF); //сбрасываем Watchdog Reset Flag
asm("wdr");
--TIMER_SLEEP; //декремент счетчика циклов таймера сна
WDTCR |= (1<<WDTIE); // запуск WDT
}
Добавлено after 5 minutes 8 seconds:
[uquote="akl",url="/forum/viewtopic.php?p=3998637#p3998637"]Разрешать прерывания логическим ИЛИ не совсем хорошо. ][/uquote]
вы говорите, что в регистр GINSK нельзя писать через "или"? Откровенно в первый раз об этом слышу. Ну и потом, для пина PB0 такая конструкция работает. Попробовать 6 ногу лучше пропаять?..
Re: attiny13 и PCINT0 в железе
Добавлено: Ср мар 17, 2021 11:53:43
parovoZZ
вы говорите, что в регистр GINSK нельзя писать через "или"?
Ну а зачем так делать? Сразу целиком писать весь регистр без его предварительного чтения. Ведь какие прерывания необходимы, а каие нет - известно. Тоже самое и регистрами флагов. Там всего 2 флага. Ну так и пиши туда сразу 0xFF. Зачем его читать???
Re: attiny13 и PCINT0 в железе
Добавлено: Ср мар 17, 2021 12:16:18
Ivanoff-iv
[uquote="parovoZZ",url="/forum/viewtopic.php?p=3998479#p3998479"]Старые тиньки никак не предназначены для обработки прерывания вне его - флаги сбрасываются в прерывании, поэтому надо свои вводить, если обработчик пустой. Либо же лупом проверять флаги постоянно...Вообщем, костыльные микры...[/uquote]Старые, это какие?
в 13, 2313 и прочих, с которыми я работал можно и без прерываний флаги читать, программно сбоасывать... т.е. тело прерывания и разрешение прерывания совсем необязательны чтобы работать с флагами событий.
Re: attiny13 и PCINT0 в железе
Добавлено: Ср мар 17, 2021 13:31:08
parovoZZ
Старые, это какие?
Это 8-ми битки, кроме: xmega, серия DA, 0-ая и 1-ая серия. В трёх последних флаги в прерываниях не сбрасываются, либо сбрасываются после выполнения определённых условий. Появились два уровня приорита прерываний, карусель прерываний... Это некая коллаборация mega и xmega.
Добавлено after 3 minutes 16 seconds:
[uquote="Ivanoff-iv",url="/forum/viewtopic.php?p=3998783#p3998783"][uquote="parovoZZ",url="/forum/viewtopic.php?p=3998479#p3998479"]Старые тиньки никак не предназначены для обработки прерывания вне его - флаги сбрасываются в прерывании, поэтому надо свои вводить, если обработчик пустой. Либо же лупом проверять флаги постоянно...Вообщем, костыльные микры...[/uquote]
в 13, 2313 и прочих, с которыми я работал можно и без прерываний флаги читать, программно сбоасывать... т.е. тело прерывания и разрешение прерывания совсем необязательны чтобы работать с флагами событий.[/uquote]
Флаги можно читать в любых МК. Они абсолютно независмы и отражают наступление какого-либо события. Речь о другом: выйти из сна в AVR можно только с помощью разрешённого прерывания, а его обработчик сбросит флаги автоматом.