Страница 1 из 1
Не нашел примера использования PCINT для Attiny13
Добавлено: Пт янв 03, 2014 20:31:00
c2n
Доброго дня.На третий день празднеств решил побаловаться с Тини13, переработать код товарисча, в более компактную форму.
Решил за одно изучить использование прерываний PCINT, на практике. До этого с такой мелюзгой и этим прерыванием не работал.
Код: Выделить всё
#include <avr/io.h>
#include <avr/interrupt.h>
int Counter=1;
ISR(PCINT0_vect) //Прерывание на PCINT
{
sei(); //Запретить прерывания...дабы неповадно было
if (Counter >=4) // если переменная 4 и более
{
Counter = 1; // приравниваем к 1.
} else // иначе
{
Counter++; // инкремент счетчика
}
cli(); //Разрешить прерывание
}
int main(void)
{
sei(); //Запретил прерывания, дабы не повадно было
DDRB = 0b00111; //установил пол порта на вход, половину на выход
PORTB = 0b00111; //включил порт
GIMSK = GIMSK|(1<<PCIE); //разрешил прерывание PCINT0
PCMSK = PCMSK|(1<<PCINT4); //Разрешил вызов прерывания при изменении наа порту 4
cli(); //Разрешил прерывания
while(1)
{
PORTB = Counter; //вывожу некую переменную в порт.
}
}
Ну и как результат - не работает

Понятно что ошибка в ДНК, да и отравление еще не прошло. Подскажите...
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Пт янв 03, 2014 20:41:03
codenamehawk
Ошибки в :
sei(); //Запретить прерывания...дабы неповадно было
sei(); Разрешает прерывания.
cli(); //Разрешить прерывание -- запрещает.
Они вообще не нужны в прерывании, там все автоматом делается.
При изменении переменной в прерывании необходимо добавить квалификатор volatile.
Примерно так.
volatile int Counter=1;
Остального не смотрел.
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Пт янв 03, 2014 20:52:47
c2n
http://radiokot.ru/forum/viewtopic.php? ... 2#p1188562
Тут мои догадки "подтвердились", только комрады плавно перешли с Сей на АСМу

а я на этом диалекте пока не очень...
codenamehawk писал(а):Они не нужны в прерывании, там все автоматом делается.
Но во многоих источниках пишут - пользуй RETI, или з-апрещай прерывания делай что надо и потом разрешай т.к. SREG при возникновении прерывания обнуляется...
=======
местами поменял. Не помогло

Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Пт янв 03, 2014 20:55:51
codenamehawk
Компилятор сам запретит прерывания при входе в прерывание и разрешит при выходе.
(Это относится к языку С, на АСМ все ручками)
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Пт янв 03, 2014 21:07:29
codenamehawk
Создайте проект в протеус, посмотрю.
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Пт янв 03, 2014 21:07:59
pyzhman
codenamehawk писал(а):Компилятор сам запретит
И даже сам камень.
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Пт янв 03, 2014 21:14:49
codenamehawk
pyzhman писал(а):
И даже сам камень.
И где тут смеяться?
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Пт янв 03, 2014 21:30:35
zero648
codenamehawk писал(а):И где тут смеяться?
Зачем смеяться? Глобальные прерывания аппаратно запрещаются при входе в прерывание, и разрешаются ком-ой RETI при выходе.
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Пт янв 03, 2014 21:34:41
c2n
протеус - зло!
а отладчик системы драгон у меня помер
Код - рабочий.
Спойлер
Код: Выделить всё
#include <avr/io.h>
#include <avr/interrupt.h>
int Counter=1;
ISR(PCINT0_vect) //Прерывание на PCINT
{
if (Counter >=4) // если переменная 4 и более
{
Counter = 1; // приравниваем к 1.
} else // иначе
{
Counter++; // инкремент счетчика
}
}
int main(void)
{
cli(); //Запретил прерывания, дабы не повадно было
DDRB = 0b00111; //установил пол порта на вход, половину на выход
PORTB = 0b00111; //включил порт
GIMSK = GIMSK|(1<<PCIE); //разрешил прерывание PCINT0
PCMSK = PCMSK|(1<<PCINT4); //Разрешил вызов прерывания при изменении наа порту 4
sei(); //Разрешил прерывания
while(1)
{
PORTB = Counter; //вывожу некую переменную в порт.
}
}
Теперь осталось разобраться, как определить On_Button_Down и On_Button_Up, но это другая песня
Спасибо. надеюсь новичкам поможет.
а мне - закусывать нада

всех с новым годом
=====
Ну да
- указывает компилятору не проводить оптимизацию...
Думаю в моем случае это не существенно, но по хорошему - надо.
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Пт янв 03, 2014 21:46:59
codenamehawk
zero648 писал(а):
Зачем смеяться? Глобальные прерывания аппаратно запрещаются при входе в прерывание, и разрешаются ком-ой RETI при выходе.
Это я уже написал выше, но при чем тут "сам камень"?
Камень выполнит то, что ему прикажет программа.
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Пт янв 03, 2014 21:52:08
codenamehawk
То c2n
Выбросите cli(); и sei(); из обработчика прерывания.
В прерывании используют sei(); , только если необходимо отловить следующее прерывание, находясь в другом прерывании.
И то это надо очень осторожно применять, программа может зациклиться.
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Пт янв 03, 2014 22:53:04
oleg110592
codenamehawk писал(а):Это я уже написал выше, но при чем тут "сам камень"?
Камень выполнит то, что ему прикажет программа.
человек хотел сказать
что если МК начал выполнять программу прерывания, то вход в другие прерывания "блокируется" (автоматически) сбросом флага I регистра статуса, и другие прерывания если произошла установка их флагов, будут ожидать пока флаг I не будет установлен. Флаг I устанавливается при выходе из прерывания командой reti
это делает сам "камень" без "приказов" и компилятор Си такого никогда не делает:
codenamehawk писал(а):Компилятор сам запретит прерывания при входе
достаточно листинг посмотреть и в ассемблерной программе "ручками" совсем не надо этого делать.
для примера тестовый код:
Спойлер
Код: Выделить всё
// -----------------------------------------
// cpu: ATmega8
// speed: 8 mhz (max: 16 mhz)
// -----------------------------------------
#include <avr/io.h>
#include <avr/interrupt.h>
#if !defined (__AVR_ATmega8__)
#error __AVR_ATmega8__ not defined !
#endif
#if !defined (F_CPU)
#define F_CPU 8000000
#endif
#define RAMSTART 0x0060
#define RAMSIZE (RAMEND-RAMSTART)
ISR(TIMER0_OVF_vect) // Timer/Counter0 Overflow
{
TCNT0 = 178;
// ... ;
}
// --------------
// --- Timer0 ---
// --------------
void Timer0_Init(void)
{
// Timer0 settings: ~ 79872 ticks (9984 us / 9,984 ms / 0,009984 sec)
TCCR0 = (1<<CS02) | (1<<CS00); // CLK/1024
TIMSK = (1 << TOIE0); // Timer/Counter0 Overflow Interrupt Enable
TCNT0 = 178;
}
// --------------
// --- main() ---
// --------------
int main()
{
Timer0_Init();
sei(); // enable interrupts
for (;;)
return 0;
}
листинг обработчика прерывания после компиляции:
Спойлер
Код: Выделить всё
ISR(TIMER0_OVF_vect) // Timer/Counter0 Overflow
{
38: 1f 92 push r1
3a: 0f 92 push r0
3c: 0f b6 in r0, 0x3f ; 63
3e: 0f 92 push r0
40: 11 24 eor r1, r1
42: 8f 93 push r24
TCNT0 = 178;
44: 82 eb ldi r24, 0xB2 ; 178
46: 82 bf out 0x32, r24 ; 50
// ... ;
}
48: 8f 91 pop r24
4a: 0f 90 pop r0
4c: 0f be out 0x3f, r0 ; 63
4e: 0f 90 pop r0
50: 1f 90 pop r1
52: 18 95 reti
нет там команды cli
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Сб янв 04, 2014 00:06:29
codenamehawk
"Компилятор сам запретит прерывания при входе в прерывание" тут я ошибся.
(Ожидал,что раз есть RET и RETI, то есть и два вызова по аналогии.)
Действительно, сам камень аппаратно запрещает прерывания.
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Сб янв 04, 2014 06:59:48
pyzhman
Фуф, а я то уже наглотался валидола и начал переосмыслять структуру прерываний...

Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Сб янв 04, 2014 08:52:18
Alkul
c2n писал(а):т.к. SREG при возникновении прерывания обнуляется...
С точностью до наоборот
В регистре SREG при вызове обработчика прерывания аппаратно сбрасывается только флаг I (флаг глобального запрета прерываний) Все остальные флаги не изменяются. А вот сам обработчик прерывания вполне может изменить какие-то флаги. Поэтому при использовании прерываний в обработчике
обязательно нужно писать следующий код:
Код: Выделить всё
INTERRUPT: ;Имя выбрано только для примера
push R16 ;Сохранить на стеке регистр, который будет "испорчен" при сохранении регистра состояния
in R16,SREG ;Скопировать содержимое регистра состояний в регистр R16
push R16 ;Сохранить на стеке содержимое регистра состояний
push R17 ;Регистры выбраны для примера,
push ZL ;в котором показывается необходимость
push ZH ;сохранения регистров, использованных в обработчике прерывания
; ... Здесь расположено тело обработчика прерывания
pop ZH ;Восстановить из стека
pop ZL ;регистры, использованные
pop R17 ;в обработчике прерывания
pop R16 ;Восстановить из стека содержимое регистра состояний
out SREG,R16 ;Восстановить регистр состояний
pop R16 ;Восстановить "испорченный" при сохранении SREG регистр
reti
Регистры R17, ZL и ZH взяты наугад. Предположим, что эти регистры используются в коде обработчика прерывания.
Смысл в том, что вызов обработчика прерывания не должен никак сказываться на работе основной программы после выхода из обработчика. Поэтому обязательно нужно после входа в обработчик прерывания сохранить, а перед выходом из обработчика восстановить SREG и все задействованные в обработчике регистры.
codenamehawk писал(а):Ожидал,что раз есть RET и RETI, то есть и два вызова по аналогии
Нет
Разница между RET и RETI лишь в том, что RET снимает со стека адрес возврата и переходит по нему, а RETI, кроме этого еще и глобально разрешает прерывания.
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Пт июн 30, 2017 21:05:59
Valek174
Здравствуйте!
Подскажите пожалуйста как определить какое из внешних прерываний PCINT4 или PCINT3 сработало?
Re: Не нашел примера использования PCINT для Attiny13
Добавлено: Сб июл 01, 2017 03:39:26
pyzhman
Считать состояние порта и определиться с нужным действием.