Гудвин, волшебник (07.11.2019 15:27, просмотров: 193) ответил Ксения на Научите как :), у меня эта матрица в жизни первая.
Вот для Меги. Пульт ДУ радио на 48 кнопок. Особо глазастым занудам (задержка в функции прерывания) - прерывание это и есть основной функционал ;)
// atmega48v, компилятор CodeVision AVR
// fuses настраиваем для работы внутреннего генератора 8 МГц, включен делитель на 8 - (частота тактирования 1 МГц).
// матрица клавиатуры 8*6
// PORTD - строки
// PORTC - колонки
#include <mega48.h>
#include <delay.h>
#include <sleep.h>
/* // эта отладочная фишка имеется только в моем stk500 клоне
void init_debug(void)
{
PORTB=0x00;
DDRB=0x38;
PORTB.3=1; // сигнал MOSI программатора - используется как SS
delay_ms(1);
PORTB.3=0;
delay_ms(1);
}
void putchar( char c)
{
unsigned char n;
for (n=0;n<8;n++)
{
if (c & 1) PORTB.4=1; // сигнал MISO программатора - данные
else PORTB.4=0;
PORTB.5 =0; // сигнал SCK программатора - clock
delay_us(100);
PORTB.5 =1;
delay_us(100);
c=c>>1;
}
}
*/
void imp_led(void) // мигнем одним из светодиодов (PORTB.5)
{
PORTB.5 = 1;
delay_ms(3);
PORTB.5 = 0;
// PORTB.4 = 1;
// delay_ms(5);
// PORTB.4 = 0;
// PORTB.3 = 1;
// delay_ms(5);
// PORTB.3 = 0;
}
void send_byte(char b) // пошлем байт в порт (PORTB.7) - "модулятор" передатчика
{
char i;
for (i=0;i<8;i++)
{
if (b & 1)
{
PORTB.7=1;
delay_us(1000);
PORTB.7=0;
delay_us(1000);
}
else
{
PORTB.7=1;
delay_us(500);
PORTB.7=0;
delay_us(500);
}
b=b>>1;
}
}
void send_cod(unsigned char cod) // пошлем код в COM порт 0x0,0x0, - преамбула для синхронизации
// 0xE6, - синхпробайт
// <код>,<инверсия кода>, - код
// 0x6E, 0x0 - конец пакета
{
PORTB.6=1; // порт (PORTB.6) включим питание передатчика
delay_ms(1); // ждем 1мс для фиксации PLL передатчика
send_byte(0);
send_byte(0);
send_byte(0);
send_byte(0);
send_byte(0);
send_byte(0);
send_byte(0);
send_byte(0xE6);
send_byte(cod);
send_byte(~(cod));
send_byte(0x6E);
send_byte(0);
PORTB.6=0; // порт (PORTB.6) вЫключим питание передатчика
}
// Pin change 16-23 interrupt service routine
interrupt [PCINT2] void pin_change_isr2(void)
{
unsigned char i;
unsigned char b;
volatile unsigned char cod;
delay_ms(5); // антидребезг
b=PIND;
if(b == 0xFF) return; // прерывание было при отпускании кнопки - выходим без обработки
for (i=0;i<8;i++)
{
if (!(b & 1)) break;
b=b>>1;
}
cod=i;
PORTD = 0; // меняем порты D и С местами
DDRD = 0xFF;
DDRC = 0;
PORTC = 0x7F;
delay_ms(5); // антидребезг
b=PINC;
for (i=0;i<6;i++)
{
if (!(b & 1)) break;
b=b>>1;
}
DDRD=0x00; // возвращаем порты D и С в исходное состояние
PORTD=0xFF;
PORTC=0x00;
DDRC=0x7F;
cod=(i*8)+cod;
cod+=1; // чтобы код начинался с единицы
//putchar(cod); // отладочный вывод в отладчик stk500
lab1:
send_cod(cod);
imp_led();
if ((cod==12) || (cod==14)) // кнопки громкости - автоповтор
{
delay_ms(100);
if (!(PIND==0xFF)) goto lab1; // повторяем пока нажата кнопка
}
PCIFR=0x04; // чистим флаг прерывания перед выходом
}
////////////////////////////////////////////////////////////////////////////////////////
void main(void)
{
PORTB=0x00;
DDRB=0xFF;
PORTC=0x00;
DDRC=0x7F;
PORTD=0xFF;
DDRD=0x00;
// Interrupt on any change on pins PCINT16-23: On
EICRA=0x00;
EIMSK=0x00;
PCICR=0x04;
PCMSK2=0xFF;
PCIFR=0x04;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;
// int_debug();
// Global enable interrupts
#asm("sei")
while (1)
{
sleep_enable(); // здесь просто спим. Вся обработка в прерывании
powerdown();
};
}