Если кнопки на PD3, PD4, PD5, можно все три проверять на одном прерывани INT1.x8973 писал(а):С программированием прерывания INT1, вроде как, разобрался. Но теперь "внимание, вопрос". Можно ли использовать для управления кнопками ноги T0 и T1(OC0B)? А то я по незнанию две кнопки из трех на них развел...
ВСЁ по прошивке и программированию AT90S2313/ATTiny2313
- Реклама
zero648
Нет, не принципиально, просто я понять хочу, почему он так реагирует.Принципиально на PD0 кнопку нужно?
Да, они на PD4 и PD5. Но, честно говоря, я понятия не имею, как это замутить.zero648 писал(а):Если кнопки на PD3, PD4, PD5
А было бы неплохо, а то с опросом кнопок код вырос, и памяти контроллера только-только на два эффекта хватило)
Не очень понимаю кому что надо с кнопками, но можно замутить вызов прерывания при нажатия ЛЮБОЙ кнопки, если развязаться диодами (и если нога внешнего прерывания свободна, естессно). В обработчике прерывания уже смотреть какая кнопка нажата.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Если развязываться диодами, то значит - перекраивать плату. А если уже на то пошло, то я лучше кнопки по новой разведу.Gudd-Head писал(а):если развязаться диодами
- Реклама
Ну это так, на будущее. Может, пригодится...
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Схема подключения 3-х кнопок на одно внешнее прерывание:x8973 писал(а): Да, они на PD4 и PD5. Но, честно говоря, я понятия не имею, как это замутить.
А было бы неплохо, а то с опросом кнопок код вырос, и памяти контроллера только-только на два эффекта хватило)
Опрос в прерывании INT1:
status_pinD=PIND&((1<<PB5)|(1<<PB4)|(1<<PB3)); // Опросим и сразу промаскируем порт D
// Проверяем status_pinD:
0x38 - кнопки не нажаты;
0x30 - нажата кнопка PD3;
0x20 - нажата кнопка PD4;
0x10 - нажата кнопка PD5;
if (status_pinD!=0x38)
{
if (status_pinD==0x30) {делаем первое}
if (status_pinD==0x20) {делаем второе}
if (status_pinD==0x10) {делаем третье}
}
Последний раз редактировалось zero648 Сб авг 11, 2012 08:51:18, всего редактировалось 1 раз.
Зачем плату перекраивать, подпаял диоды и все, или вообще SMD-шные, они на дорожки хорошо приделываются.x8973 писал(а):Если развязываться диодами, то значит - перекраивать плату. А если уже на то пошло, то я лучше кнопки по новой разведу.
Если не разобрался со своим кодом, могу предложить такой вариант, кнопка на PD6, юзаем внешнее прерывание таймера:shadivl писал(а):Нет, не принципиально, просто я понять хочу, почему он так реагирует.
Спойлер
Код: Выделить всё
.include "tn2313def.inc" ; Используем ATtiny2313
; ROM ===============
.CSEG ; ROM
.org $000
rjmp RESET ; External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset
reti ; INT0 Внешнее прерывание 0
reti ; INT1 Внешнее прерывание 1
rjmp TIMER1_CAPT ; TIMER1 CAPT Захват таймера/счетчика Т1
; -------------------- R E S E T ---------------------------------------
.ORG INT_VECTORS_SIZE ; Конец таблицы прерываний
RESET:
cli
ldi r16, RAMEND ; Set Stack Pointer to top of RAM
out SPL, r16 ;
; --------------- M A I N P R O G R A M M ------------------------
PORTS_Init:
ldi r16, 0b0000000
out DDRD, r16
ldi r16, 0b1111111
out PORTD, r16
ldi r16, 0b11111111
out DDRB, r16
ldi r16, 0b11111111
out PORTB, r16
OCR1_Init:
ldi r16, (1<<ICIE1) ; Включаем прерывания по сигналу ICP1
out TIMSK, r16
sei
clr r20
ser r21
MAIN_loop:
in r16, MCUCR
ori r16, (1<<SE)
out MCUCR, r16
taste_push: sbis PIND, 6
rjmp taste_push
sleep ; Отдыхаем пока не началось
rjmp MAIN_loop ; Go again
; ------------ E X T E R N A L I N T E R R U P T S ---------------------
TIMER1_CAPT:
eor r20, r21
ori r20, 0b10111111
in r16, PIND
ori r16, 0x80
com r16
eor r16, r20
sbrc r16, 6
ldi r16, 0xff
sbrs r16, 6
ldi r16, 0x00
out PORTB, r16
reti
Не вышло. Все три кнопки работают как одна.
Ну покаж код, посмотримx8973 писал(а):Не вышло. Все три кнопки работают как одна.
Спойлер
Код: Выделить всё
#include <avr/io.h> //Библиотека ввода/вывода
#include <math.h> //Библиотека математических функций
#include <avr/interrupt.h> //Библиотека прерываний
//Переменные
unsigned short int stage = 1; //Номер сцены для эффектов
unsigned short int t = 1000; //Величина задержки для эффектов
unsigned short int mode = 1; //Номер текущего эффекта
unsigned short int pin4hold = 0; //Блокировка многократного срабатывания кнопки "+"
unsigned short int pin5hold = 0; //Блокировка многократного срабатывания кнопки "-"
SIGNAL (SIG_INTERRUPT1)//Программа-обработчик прерывания INT1
{
cli(); //Глобальный запрет прерываний
unsigned int status_pinD = PIND&((1<<PD5)|(1<<PD4)|(1<<PD3));
if (status_pinD!=0x38)
{
if (status_pinD=0x30) //Нажата кнопка MODE (PD3)
{
if (mode < 2) //2 - количество эффектов
{
mode++;
}
else
{
mode = 1;
}
}
if (status_pinD=0x20) //Нажата кнопка "+" (PD4)
{
if (t >= 100)
{
t = t - 100; //Уменьшаем задержку
}
}
if (status_pinD=0x10) //Нажата кнопка "-" (PD5)
{
t = t + 100; //Увеличиваем задержку
}
}
sei(); //Глобальное разрешение прерываний
}
//Подпрограмма задержки
void pause(unsigned int a)
{
unsigned int i;
for (i=a; i>0; i--);
}
//Подпрограмма инициализации ШИМ
void pwm_init(void)
{
TCCR0A = (1<<WGM01)|(1<<WGM00); //Режим FastPWM
TCCR1A = (1<<WGM10); //Режим FastPWM 8 bit
TCCR1B = (1<<WGM12); //Режим FastPWM 8 bit
TCCR0A = TCCR0A|(1<<COM0A1)|(1<<COM0A0); //Инвертированный выход
TCCR1A = TCCR1A|(1<<COM1A1)|(1<<COM1A0);
TCCR1A = TCCR1A|(1<<COM1B1)|(1<<COM1B0);
TCCR0B = TCCR0B|(1<<CS00); //Предделители
TCCR1B = TCCR1B|(1<<CS10);
OCR0A = 0xff; //Начальная яркость нулевая
OCR1AL = 0xff;
OCR1BL = 0xff;
}
/*------Подпрограммы световых эффектов------*/
//Эффект "Непрерывного спектра"
void eff_inf_spectr(unsigned int delay)
{
if (stage == 1){if (OCR1A > 0){OCR1A--;}else{stage = 2;}} //Увеличиваем зеленый
if (stage == 2){if (OCR1B < 255){OCR1B++;}else{stage = 3;}} //Уменьшаем красный
if (stage == 3){if (OCR0A > 0){OCR0A--;}else{stage = 4;}} //Увеличиваем синий
if (stage == 4){if (OCR1A < 255){OCR1A++;}else{stage = 5;}} //Уменьшаем зеленый
if (stage == 5){if (OCR1B > 0){OCR1B--;}else{stage = 6;}} //Увеличиваем красный
if (stage == 6){if (OCR0A < 255){OCR0A++;}else{stage = 1;}} //Уменьшаем синий
pause(delay);
}
//Эффект "Случайный цвет"
void eff_rand_color(unsigned int delay)
{
stage = rand() / 4096; //Случайное число от 0 до 8 (rand() возвращает целое число от 0 до 32768)
switch (stage)
{
case 1:
{
OCR1BL = 0x00; //Красный полная яркость
OCR1AL = 0xff; //Зеленый погашен
OCR0A = 0xff; //Синий погашен
break;
}
case 2:
{
OCR1BL = 0x88; //Половина красного
OCR1AL = 0x88; //Половина зеленого
OCR0A = 0xff; //Синий погашен
break;
}
case 3:
{
OCR1BL = 0xff; //Красный погашен
OCR1AL = 0x00; //Зеленый полная яркость
OCR0A = 0xff; //Синий погашен
break;
}
case 4:
{
OCR1BL = 0xff; //Красный погашен
OCR1AL = 0x88; //Половина зеленого
OCR0A = 0x88; //Половина синего
break;
}
case 5:
{
OCR1BL = 0xff; //Красный погашен
OCR1AL = 0xff; //Зеленый погашен
OCR0A = 0x00; //Синий полная яркость
break;
}
case 6:
{
OCR1BL = 0x88; //Половина красного
OCR1AL = 0xff; //Зеленый погашен
OCR0A = 0x88; //Половина синего
break;
}
}
pause(delay);
}
//Основная подпрограмма
int main(void)
{
DDRB=(1<<PB2)|(1<<PB3)|(1<<PB4); //Инициализация порта B
//DDRD&=~(1<<PD4)|(1<<PD5); //Инициализация порта D
//PORTD|=(1<<PD4)|(1<<PD5); //Настройка ног PD4 и PD5 на ввод (Кнопки "+" и "-")
GIMSK = (1<<INT1); //Разрешение прерывания int1 (Кнопка MODE)
MCUCR = (1<<ISC11) | (1<<ISC10); //Прерывание по появлению низкого уровня
sei(); //Глобальное разрешение прерываний
pwm_init(); //Инициализация ШИМ
while (1)
{
/*if(!(PIND & (1<<PIND4))) //Нажатие на кнопку "+"
{
if (!pin4hold)
{
if (t >= 100)
{
t = t - 100; //Уменьшаем задержку
}
pin4hold = 1;
}
}
else
{
pin4hold = 0;
}
if(!(PIND & (1<<PIND5))) //Нажатие на кнопку "-"
{
if (!pin5hold)
{
t = t + 100; //Увеличиваем задержку
pin5hold = 1;
}
}
else
{
pin5hold = 0;
}*/
switch (mode) //Выбор текущего эффекта
{
case 1:
{
eff_inf_spectr(t); //"Непрерывный спектр"
break;
}
case 2:
{
eff_rand_color(t); //"Случайный цвет"
break;
}
}
}
return 1;
}
Все три кнопки изначально подтянуты на Vcc резюками по 10 кОм.
C инициализацией портов и прерываний были косячки
Код: Выделить всё
//Основная подпрограмма
int main(void)
{
DDRB=(1<<PB2)|(1<<PB3)|(1<<PB4); //Инициализация порта B
DDRD=~((1<<PD5)|(1<<PD4)|(1<<PD3)); //Инициализация порта D
PORTD|=(1<<PD5)|(1<<PD4)|(1<<PD3); //Настройка ног PD4 и PD5 на ввод (Кнопки "+" и "-")
GIMSK = (1<<INT1) ; //Разрешение прерывания int1 (Кнопка MODE)
MCUCR = (1<<ISC11); //Прерывание по появлению низкого уровня
sei(); //Глобальное разрешение прерываний
pwm_init(); //Инициализация ШИМ
Хммм... А разве мы вот этим
не делаем то же самое?
Код: Выделить всё
unsigned int status_pinD = PIND&((1<<PD5)|(1<<PD4)|(1<<PD3));Нет, этим мы проверяем состояние портаx8973 писал(а):Хммм... А разве мы вот этимне делаем то же самое?Код: Выделить всё
unsigned int status_pinD = PIND&((1<<PD5)|(1<<PD4)|(1<<PD3));
Вот этот кусок еще поправь:
Код: Выделить всё
SIGNAL (SIG_INTERRUPT1)//Программа-обработчик прерывания INT1
{
cli(); //Глобальный запрет прерываний
unsigned int status_pinD = PIND&((1<<PD5)|(1<<PD4)|(1<<PD3));
if (status_pinD == 0x30) //Нажата кнопка MODE (PD3)
{
if (mode == 2) {mode = 1;} else {mode = 2;} //2 - количество эффектов
}
if (status_pinD == 0x20) //Нажата кнопка "+" (PD4)
{
if (t >= 100) {t = t - 100;} //Уменьшаем задержку
}
if (status_pinD == 0x10) //Нажата кнопка "-" (PD5)
{t = t + 100;} //Увеличиваем задержку
sei(); //Глобальное разрешение прерываний
}
Да, вот теперь работает как надо) Эх, невнимательность моя - такую ошибку тупую пропустил)
Народ, а подскажет кто-нибудь контроллер AVRовский, так же, с четырьмя каналами ШИМ, но с объемом памяти побольше? А то оптимизация не помогает - не хватает памяти для трех и более эффектов...


