AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR... |
12.03.2021, 18:06
|
|
Прохожий
Регистрация: 12.03.2021
Сообщений: 3
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Матричная клавиатура-динамическая индикация
Здравствуйте. Начал изучать программирование Си AVR. Столкнулся с проблемой. Не получается вывести на 4 разрядный 7 сегментный дисплей значение из матричной клавиатуры 3х4. То есть, вывести 1,2,3.. получается. Но вывести 11,12,...111,234,...1234,7865 не получается. Может кто уже делал и посоветует как с этим справится..?
Код:
|
#include ‹inttypes.h›
#include ‹avr/io.h›
#include ‹avr/interrupt.h›
#include ‹avr/sleep.h›
#include ‹util/delay.h›
#define CHISLO PORTA
#define RAZRIAD PORTB
// Массив значений для порта вывода
int i = 0;
unsigned char key_tab[4] =
{
0b11111110,
0b11111101,
0b11111011,
0b11110111
};
// Функция опроса клавиатуры
// Функция опроса клавиатуры
int n = 0;
unsigned int razr1 = 0, razr2 = 0, razr3 = 0, razr4 = 0;
unsigned char g = 1;
unsigned int z = 0;
unsigned int chisla [10] = {0x3f, 0x6, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x7, 0x7f, 0x6f};
void vse_chislo (unsigned int razbivka_chisla)
{
razr1 = razbivka_chisla / 1000; // тысячи
razr2 = razbivka_chisla % 1000 / 100; // сотни
razr3 = razbivka_chisla % 100 / 10; // десятки
razr4 = razbivka_chisla % 10; // единицы
}
ISR (TIMER0_OVF_vect)
{
if (g == 1) {RAZRIAD = (1 ‹‹ 0); CHISLO = chisla[razr1];} //включаем 1-й разряд, остальные выключаем
if (g == 2) {RAZRIAD = (1 ‹‹ 1); CHISLO = chisla[razr2];} //включаем 2-й разряд, остальные выключаем
if (g == 3) {RAZRIAD = (1 ‹‹ 2); CHISLO = chisla[razr3];} //включаем 3-й разряд, остальные выключаем
if (g == 4) {RAZRIAD = (1 ‹‹ 3); CHISLO = chisla[razr4];} //включаем 4-й разряд, остальные выключаем
g++; // добавляем к переменной g единицу
if (g › 4) g = 1; // отслеживаем переменную g, чтобы она не превысила значение 4
}
unsigned char scan_key(void)
{
unsigned char key_value = 0;
unsigned char i;
for(i = 0; i ‹ 5; i++)
{
PORTC = key_tab[i]; // выводим лог. 0 в порт вывода
_delay_us(10);
switch (PINC & 0xF0)
{
case 0b11100000: key_value = 1 + i * 3;
return (key_value);
case 0b11010000: key_value = 2 + i * 3;
return (key_value);
case 0b10110000: key_value = 3 + i * 3;
return (key_value);
default: break;
}
}
return (key_value);
}
int main(void)
{
DDRC |= (1 ‹‹ PC3) | (1 ‹‹ PC2) | (1 ‹‹ PC1) | (1 ‹‹ PC0); // Порт вывода
DDRC &= ~(1 ‹‹ PC7) | (1 ‹‹ PC6) | (1 ‹‹ PC5) | (1 ‹‹ PC4); // Порт ввода
PORTC = 0xF0; // Устанавливаем лог. 1 в порт ввода
DDRA = 0b11111111;
DDRB = 0x0F;
PORTB |= (1 ‹‹ 4) | (1 ‹‹ 5);
_delay_ms(10);
RAZRIAD = (1 ‹‹ 0);
CHISLO = 0x3f;
// Настройка 0-го таймер счетчика на прерывание по переполнению
TCCR0 |= (1 ‹‹ 1); TCCR0 &= ~((1 ‹‹ 0) | (1 ‹‹ 2)); // f/8
TIMSK |= (1 ‹‹ 0);
TCNT0 = 0;
sei ();
while(1)
{
// Выводим значение нажатой кнопки на индикатор
z = scan_key();
if(scan_key() › 0 )
{
if(scan_key ‹ 9)
vse_chislo(z);else if(scan_key › 9)
{
z = z * 10 + z;
vse_chislo(z);
}
}
}
} |
Последний раз редактировалось Maxsan22; 12.03.2021 в 18:11.
Причина: удалил спойлер так как он не открывался
|
|
|
|
12.03.2021, 18:19
|
|
Почётный гражданин KAZUS.RU
Регистрация: 10.12.2007
Адрес: Екатеринбург
Сообщений: 2,731
Сказал спасибо: 2,439
Сказали Спасибо 893 раз(а) в 580 сообщении(ях)
|
Re: Матричная клавиатура-динамическая индикация
Сообщение от Maxsan22
|
razr3 = razbivka_chisla % 100 / 10; // десятки
razr4 = razbivka_chisla % 10; // единицы
|
razr3 = razbivka_chisla %1000% 100 / 10; // десятки
razr4 = razbivka_chisla %1000% 100% 10; // единицы
Для начала
|
|
|
|
12.03.2021, 19:53
|
|
Заблокирован
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,486
Сказал спасибо: 396
Сказали Спасибо 2,220 раз(а) в 1,319 сообщении(ях)
|
Re: Матричная клавиатура-динамическая индикация
Полагаю, надо начать с изучения английского языка хотябы в объеме гугл-переводчика.
RAZRIAD = DIGIT
CHISLO = NUMBER
razbivka_chisla = bcd (от binary-coded decimal, двоично-десятичное представление числа)
vse_chislo = value
Затем нужно почитать про BCD-преобразования на Си.
|
|
|
|
12.03.2021, 21:22
|
|
Прохожий
Регистрация: 12.03.2021
Сообщений: 3
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Матричная клавиатура-динамическая индикация
Похоже тут решили что спросил о грамматике?
С отображением числа 1234 если он в переменной z проблем нет.
Мне нужно при последовательном нажатии кнопок 1.2.3.4 на матричной клавиатуре в переменную z нужно записать 1234. Но пока получается вывести только один символ. ТО есть поочередно 1.2.3.4.
Как я понял, нужно создать некую переменную куда при нажатии 1 запишется 1, затем при нажатии 2, единица сдвинется в лево и запишется 2 и тд, но как это осуществить на практике???
Последний раз редактировалось Maxsan22; 14.03.2021 в 16:42.
|
|
|
|
13.03.2021, 01:02
|
|
Почётный гражданин KAZUS.RU
Регистрация: 25.11.2010
Адрес: г. Дзержинск Нижегородская обл.
Сообщений: 1,717
Сказал спасибо: 130
Сказали Спасибо 1,108 раз(а) в 527 сообщении(ях)
|
Re: Матричная клавиатура-динамическая индикация
Сообщение от Maxsan22
|
переменную куда при нажатии 1 запишется 1, затем при нажатии 2, единица сдвинется в лево и запишется 2 и тд, но как это осуществить на практике???
|
Число в аккумуляторе умножать на 10 и суммировать с введенным числом.
|
|
|
|
13.03.2021, 15:53
|
|
Заблокирован
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,486
Сказал спасибо: 396
Сказали Спасибо 2,220 раз(а) в 1,319 сообщении(ях)
|
Re: Матричная клавиатура-динамическая индикация
В правильной грамматике лежит половина решения задачи.
Код:
|
#define MAX_DIGITS 4
#define ENTER 10
#define BACKSPACE 11
uint8_t key; // код кнопки
uint8_t n = 0; // число введенных цифр
uint16_t value = 0; // это ваше "всё число"
do{
key = ReadKeyboard();
switch(key)
{
case 0 ... 9:
value = value * 10 + key;
Print(value);
n++;
break;
case ENTER:
break;
case BACKSPACE:
value /= 10;
Print(value);
n--;
break;
}
}while((n › 0) && (n ‹ MAX_DIGITS) && (key != ENTER)); |
Последний раз редактировалось NewWriter; 13.03.2021 в 16:34.
|
|
|
Эти 2 пользователя(ей) сказали Спасибо NewWriter за это сообщение:
|
|
|
14.03.2021, 16:51
|
|
Прохожий
Регистрация: 12.03.2021
Сообщений: 3
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Матричная клавиатура-динамическая индикация
Сообщение от NewWriter
|
key = ReadKeyboard();
|
я новичок и не совсем понял, откуда функция ReadKeyboard()?
так же, впервые вижу конструкцию
Сообщение от NewWriter
|
case 0 ... 9:
|
можно подробнее..?
Сообщение от NewWriter
|
Print(value);
|
Это вывод на LCD дисплей?
|
|
|
|
14.03.2021, 17:38
|
|
Почётный гражданин KAZUS.RU
Регистрация: 10.12.2007
Адрес: Екатеринбург
Сообщений: 2,731
Сказал спасибо: 2,439
Сказали Спасибо 893 раз(а) в 580 сообщении(ях)
|
Re: Матричная клавиатура-динамическая индикация
тоже самое
case 0:
case 1:
. . . .
case 9:
для любой цифры от 0 до 9
|
|
|
|
15.03.2021, 19:14
|
|
Заблокирован
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,486
Сказал спасибо: 396
Сказали Спасибо 2,220 раз(а) в 1,319 сообщении(ях)
|
Re: Матричная клавиатура-динамическая индикация
Сообщение от Maxsan22
|
я новичок и не совсем понял
|
ммм... Тогда тут есть два важных момента.
Во-первых, любая клавиатура ввода должна работать по принципу триггера, то есть различать момент, когда кнопку только что нажали, и момент, когда кнопку только что отпустили. Опрос клавиатуры происходит довольно часто, 50-200 раз в секунду. И если при следующем опросе кнопка не будет отпущена, а она не будет отпущена - среднее время удержания кнопки пальцем 20 - 60 мс, произойдет повторный ввод той же цифры. Если клавиатуру реже опрашивать, например 10 раз в секунду (100 мс), то такая клавиатура будет восприниматься тормознутой.
Второй момент - возвращаемые коды кнопок, то есть коды событий срабатывания клавиатуры. Для удобства дальнейшего применения коды нажатых кнопок с цифрами будут в диапазоне от 0 до 9. Код кнопки Enter (ввод) = 10, код кнопки Backspace (или отмена) = 11. Хотя тут нет ограничений.
Соответственно, по второму моменту:
функция ReadKeyboard() может выглядеть вот так:
Код:
|
/** -------------------------------------------------------
* @brief Чтение матричной клавиатуры.
* Последовательно активируются столбцы клавиатуры и считываются строки,
* определяется нажатая кнопка. Код события (нажатой кнопки) возвращается
* функцией.
* Если ни одна кнопка не была нажата, возвращается 0xFF.
* @return Код события (кнопки).
*/
uint8_t ReadKeyboard(void)
{
uint8_t rows = 0; // переменная для чтения входов строк
uint8_t keycode = 0xFF; // переменная для кода кнопки
/* Активация столбца 1, считывание строк */
ACTIVATE_COL1 // COL1 = Low, COL2 = Hi-Z, COL3 = Hi-Z
sDelay(1000); // выдержка времени для стабилизации уровней
rows = READ_ROWS; // чтение входов строк
/* Определение строки, на которой вх.уровень = Low */
if((rows & (1 ‹‹ R1_bit)) == 0) keycode = 1; // нажата кнопка 1
if((rows & (1 ‹‹ R2_bit)) == 0) keycode = 4; // нажата кнопка 4
if((rows & (1 ‹‹ R3_bit)) == 0) keycode = 7; // нажата кнопка 7
if((rows & (1 ‹‹ R4_bit)) == 0) keycode = 11; // нажата кнопка BKSP
/* Активация столбца 2, считывание строк */
ACTIVATE_COL2 // COL1 = Hi-Z, COL2 = Low, COL3 = Hi-Z
sDelay(1000); // выдержка времени для стабилизации уровней
rows = READ_ROWS; // чтение входов строк
/* Определение строки, на которой вх.уровень = Low */
if((rows & (1 ‹‹ R1_bit)) == 0) keycode = 2; // нажата кнопка 2
if((rows & (1 ‹‹ R2_bit)) == 0) keycode = 5; // нажата кнопка 5
if((rows & (1 ‹‹ R3_bit)) == 0) keycode = 8; // нажата кнопка 8
if((rows & (1 ‹‹ R4_bit)) == 0) keycode = 0; // нажата кнопка 0
/* Активация столбца 3, считывание строк */
ACTIVATE_COL3 // COL1 = Hi-Z, COL2 = Hi-Z, COL3 = Low
sDelay(1000); // выдержка времени для стабилизации уровней
rows = READ_ROWS; // чтение входов строк
/* Определение строки, на которой вх.уровень = Low */
if((rows & (1 ‹‹ R1_bit)) == 0) keycode = 3; // нажата кнопка 3
if((rows & (1 ‹‹ R2_bit)) == 0) keycode = 6; // нажата кнопка 6
if((rows & (1 ‹‹ R3_bit)) == 0) keycode = 9; // нажата кнопка 9
if((rows & (1 ‹‹ R4_bit)) == 0) keycode = 10; // нажата кнопка ENTER
/* Возвращается код события */
return keycode;
}//-------------------------------------------------------- |
Макросы ACTIVATE_COL1, ACTIVATE_COL2, ACTIVATE_COL3 представляют собой команды установки выходных уровней на пинах столбцов клавиатуры - то есть активируемый столбец переводится в лог.0, а неактивные столбцы переводятся в высокоимпедансное (Hi-Z) состояние. Не в лог.1, а именно в Hi-Z. Почему? А для того, что если вдруг будут нажаты одновременно две и более кнопки из разных столбцов, не получилось КЗ.
В качестве Hi-Z состояния может быть на это время включен либо режим входа, либо выход постоянно настраивается на Open Drain.
Макрос READ_ROWS - это команда чтения входного порта, на который приходят строки клавиатуры.
R1_bit, R2_bit, R3_bit, R4_bit - это номер входного пина строк.
Выдержка времени между активацией столбца и считыванием входов строк нужна для завершения переходных процессов от ёмкости монтажа (кнопок, дорожек) клавиатуры. Выдержка времени небольшая, десятки микросекунд, подбирается экспериментально по надежности определения кнопок.
С этим разобрались. Окей.
Теперь по первому моменту, по триггированию клавиатуры.
За время "тычка" пальцем в кнопку клавиатура будет опрошена несколько раз, и каждый раз функция ReadKeyboard() будет возвращать код нажатой кнопки. И вместо ввода одной цифры получится несколько одинаковых. А значит, нужно фиксировать только первый переход от состояния "нет нажатых кнопок" к состоянию "кнопка нажата", а все последующие события, кроме события "нет нажатых кнопок", игнорировать.
Когда первое нажатие фиксируется, клавиатура выставляет флаг. Этот флаг в дальнейшем, вместе с кодом нажатой кнопки, будет использован для выполнения действий по нажатию кнопки.
Код:
|
/* По флагу таймера интервалов опроса клавиатуры
* опрашивается клавиатура, определяется код события
* клавиатуры.
* Если код соответствует нажатой кнопке, и кнопка
* нажата только что, устанавливается флаг клавиатуры,
* а состояние клавиатуры = KEYPRESS.
* Если код события клавиатуры = 0xFF, это значит, что
* все кнопки отпущены, а значит, состояние клав.= KEYFREE
*/
#define KEYFREE 0
#define KEYPRESS 1
if(kbdtimer_flag)
{
keycode = ReadKeyboard();
if(keycode == 0xFF)
kbdstate = KEYFREE;
else if(kbdstate == KEYPRESS)
{
kbdstate = KEYPRESS;
kbdflag = 1;
}
}
/* По флагу клавиатуры (зафиксировано нажатие кнопки)
* выполняется действие.
* Флаг клавиатуры сбрасывается перед (или после)
* выполнением действия
*/
if(kbdflag)
{
kbdflag = 0;
KeyAction(keycode);
} |
|
|
|
|
09.01.2022, 13:56
|
|
Прохожий
Регистрация: 09.01.2022
Сообщений: 3
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Здравствуйте, а как в этом коде указываются пины контроллера?
Получила кучу ошибок:
Код:
|
../main.c: In function 'ReadKeyboard':
../main.c:16: error: 'ACTIVATE_COL1' undeclared (first use in this function)
../main.c:16: error: (Each undeclared identifier is reported only once
../main.c:16: error: for each function it appears in.)
../main.c:17: error: expected ';' before '_delay_ms'
../main.c:18: error: 'READ_ROWS' undeclared (first use in this function)
../main.c:21: error: 'R1_bit' undeclared (first use in this function)
../main.c:22: error: 'R2_bit' undeclared (first use in this function)
../main.c:23: error: 'R3_bit' undeclared (first use in this function)
../main.c:24: error: 'R4_bit' undeclared (first use in this function)
../main.c:27: error: 'ACTIVATE_COL2' undeclared (first use in this function)
../main.c:28: error: expected ';' before '_delay_ms'
../main.c:38: error: 'ACTIVATE_COL3' undeclared (first use in this function)
../main.c:39: error: expected ';' before '_delay_ms' |
Последний раз редактировалось mike-y-k; 12.01.2022 в 19:24.
Причина: 6.6, 7.15
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 12:39.
|
|