Портал для радиолюбителей и разработчиков электроники · с 2003 годаРеклама на сайте
Найти компонент, схему или даташит

Даташиты, справочник отечественных приборов, схемы с разбором и живой форум

AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR...

 
Опции темы

Матричная клавиатура-динамическая индикация

Непрочитано 12.03.2021, 18:06  
Maxsan22
Прохожий
 
Регистрация: 12.03.2021
Сообщений: 3
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Maxsan22 на пути к лучшему
Печаль Матричная клавиатура-динамическая индикация

Здравствуйте. Начал изучать программирование Си 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. Причина: удалил спойлер так как он не открывался
Maxsan22 вне форума  
Непрочитано 12.03.2021, 18:19  
baiderin
Почётный гражданин KAZUS.RUN
 
Аватар для baiderin
 
Регистрация: 10.12.2007
Адрес: Екатеринбург
Сообщений: 2,739
Сказал спасибо: 2,487
Сказали Спасибо 897 раз(а) в 584 сообщении(ях)
baiderin на пути к лучшему
По умолчанию Re: Матричная клавиатура-динамическая индикация

Сообщение от Maxsan22 Посмотреть сообщение
razr3 = razbivka_chisla % 100 / 10; // десятки
razr4 = razbivka_chisla % 10; // единицы
razr3 = razbivka_chisla %1000% 100 / 10; // десятки
razr4 = razbivka_chisla %1000% 100% 10; // единицы
Для начала
baiderin вне форума  
Непрочитано 12.03.2021, 19:53  
NewWriter
Почётный гражданин KAZUS.RUN
 
Аватар для NewWriter
 
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,481
Сказал спасибо: 396
Сказали Спасибо 2,222 раз(а) в 1,317 сообщении(ях)
NewWriter на пути к лучшему
По умолчанию Re: Матричная клавиатура-динамическая индикация

Полагаю, надо начать с изучения английского языка хотябы в объеме гугл-переводчика.
RAZRIAD = DIGIT
CHISLO = NUMBER
razbivka_chisla = bcd (от binary-coded decimal, двоично-десятичное представление числа)
vse_chislo = value

Затем нужно почитать про BCD-преобразования на Си.
NewWriter вне форума  
Непрочитано 12.03.2021, 21:22  
Maxsan22
Прохожий
 
Регистрация: 12.03.2021
Сообщений: 3
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Maxsan22 на пути к лучшему
По умолчанию Re: Матричная клавиатура-динамическая индикация

Похоже тут решили что спросил о грамматике?
С отображением числа 1234 если он в переменной z проблем нет.
Мне нужно при последовательном нажатии кнопок 1.2.3.4 на матричной клавиатуре в переменную z нужно записать 1234. Но пока получается вывести только один символ. ТО есть поочередно 1.2.3.4.
Как я понял, нужно создать некую переменную куда при нажатии 1 запишется 1, затем при нажатии 2, единица сдвинется в лево и запишется 2 и тд, но как это осуществить на практике???
Миниатюры:
Нажмите на изображение для увеличения
Название: 2021-03-14_17-39-21.png
Просмотров: 0
Размер:	22.8 Кб
ID:	161306  

Последний раз редактировалось Maxsan22; 14.03.2021 в 16:42.
Maxsan22 вне форума  
Непрочитано 13.03.2021, 01:02  
DanilinSA
Почётный гражданин KAZUS.RUN
 
Регистрация: 25.11.2010
Адрес: г. Дзержинск Нижегородская обл.
Сообщений: 1,801
Сказал спасибо: 133
Сказали Спасибо 1,152 раз(а) в 549 сообщении(ях)
DanilinSA на пути к лучшему
По умолчанию Re: Матричная клавиатура-динамическая индикация

Сообщение от Maxsan22 Посмотреть сообщение
переменную куда при нажатии 1 запишется 1, затем при нажатии 2, единица сдвинется в лево и запишется 2 и тд, но как это осуществить на практике???
Число в аккумуляторе умножать на 10 и суммировать с введенным числом.
DanilinSA вне форума  
Непрочитано 13.03.2021, 15:53  
NewWriter
Почётный гражданин KAZUS.RUN
 
Аватар для NewWriter
 
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,481
Сказал спасибо: 396
Сказали Спасибо 2,222 раз(а) в 1,317 сообщении(ях)
NewWriter на пути к лучшему
По умолчанию 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.
NewWriter вне форума  
Эти 2 пользователя(ей) сказали Спасибо NewWriter за это сообщение:
makakus (15.01.2022), mtit (14.03.2021)
Непрочитано 14.03.2021, 16:51  
Maxsan22
Прохожий
 
Регистрация: 12.03.2021
Сообщений: 3
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Maxsan22 на пути к лучшему
По умолчанию Re: Матричная клавиатура-динамическая индикация

Сообщение от NewWriter Посмотреть сообщение
key = ReadKeyboard();
я новичок и не совсем понял, откуда функция ReadKeyboard()?
так же, впервые вижу конструкцию
Сообщение от NewWriter Посмотреть сообщение
case 0 ... 9:
можно подробнее..?
Сообщение от NewWriter Посмотреть сообщение
Print(value);
Это вывод на LCD дисплей?
Maxsan22 вне форума  
Непрочитано 14.03.2021, 17:38  
baiderin
Почётный гражданин KAZUS.RUN
 
Аватар для baiderin
 
Регистрация: 10.12.2007
Адрес: Екатеринбург
Сообщений: 2,739
Сказал спасибо: 2,487
Сказали Спасибо 897 раз(а) в 584 сообщении(ях)
baiderin на пути к лучшему
По умолчанию Re: Матричная клавиатура-динамическая индикация

тоже самое

case 0:
case 1:

. . . .

case 9:
для любой цифры от 0 до 9
baiderin вне форума  
Непрочитано 15.03.2021, 19:14  
NewWriter
Почётный гражданин KAZUS.RUN
 
Аватар для NewWriter
 
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,481
Сказал спасибо: 396
Сказали Спасибо 2,222 раз(а) в 1,317 сообщении(ях)
NewWriter на пути к лучшему
По умолчанию 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);
}
NewWriter вне форума  
Непрочитано 09.01.2022, 13:56  
SvetlanaG
Прохожий
 
Регистрация: 09.01.2022
Сообщений: 3
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
SvetlanaG на пути к лучшему
По умолчанию

Здравствуйте, а как в этом коде указываются пины контроллера?

Получила кучу ошибок:
Код:
../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
SvetlanaG вне форума  
 
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Посегментная динамическая индикация 3ann Микроконтроллеры, АЦП, память и т.д 39 22.10.2012 13:49
Динамическая индикация 16/1 - увеличить яркость whoim Электроника - это просто 29 30.01.2012 02:25
Динамическая индикация EKuzmich TTL и CMOS логика 16 05.08.2011 08:18
Не матричная клавиатура для МП alexplev Микроконтроллеры, АЦП, память и т.д 8 22.02.2009 03:16
Динамическая индикация ПОМОГИТЕ 7Fantomas7 Микроконтроллеры, АЦП, память и т.д 2 27.03.2008 23:53


Часовой пояс GMT +4, время: 12:18.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.