06.05.2016, 15:23
|
|
Прохожий
Регистрация: 06.05.2016
Адрес: г. Санкт-Петербург
Сообщений: 9
Сказал спасибо: 5
Сказали Спасибо 1 раз в 1 сообщении
|
Семисегментный индикатор и клавиатура
Всем доброго времени суток.
Начала учить микроконтроллеры и программирование на Си совсем не давно. Просьба к Google и тп не отправлять, устала искать...
А проблема вот в чем хотела сделать отображение нажатых кнопок на семисегментный четырёх разрядный индикатор, НО столкнулась с такой проблемой, вместо 1234 или 4567 и тд у меня почему то одновременно отображается одна нажатая кнопка 1111 или 2222 и тд. Плиииз помогите советом или примером...
Вот код:
Код:
|
#include ‹inttypes.h›
#include ‹avr/io.h›
#include ‹avr/interrupt.h›
#include ‹avr/sleep.h›
#include ‹util/delay.h›
// Массив значений для порта вывода
unsigned char key_tab[4] = {0xFE, 0xFD, 0xFB, 0xF7};
// массив цифр для индикатора
unsigned char num[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
// Функция опроса клавиатуры
unsigned char scan_key(void)
{
unsigned char key_value = 0;
unsigned char i;
for(i = 0;i ‹ 4;i++)
{
PORTB = key_tab[i]; // выводим лог. 0 в порт вывода
asm("Nop");
switch (PINB & 0xF0)
{
case 0b11100000: key_value = 1 + i * 3; break;
case 0b11010000: key_value = 2 + i * 3; break;
case 0b10110000: key_value = 3 + i * 3; break;
default:
break;
}
}
return (key_value);
}
int main(void)
{
DDRB |= (1 ‹‹ PB3)|(1 ‹‹ PB2)|(1 ‹‹ PB1)|(1 ‹‹ PB0); // Порт вывода
DDRB &= ~(1 ‹‹ PB7)|(1 ‹‹ PB6)|(1 ‹‹ PB5)|(1 ‹‹ PB4); // Порт ввода
PORTB|= (1 ‹‹ PB3)|(1 ‹‹ PB2)|(1 ‹‹ PB1)|(1 ‹‹ PB0); // Устанавливаем лог. 1 в порт ввода
DDRC |= (1 ‹‹ PC3)|(1 ‹‹ PC2)|(1 ‹‹ PC1)|(1 ‹‹ PC0); // Устанавливаем лог. 1 в порт вывода
PORTC=0xF0;
DDRD = 0xFF; // Выход на индикатор
PORTD = 0x3F; // Отображаем 0 на индикаторе
asm("Nop"); // Небольшая задержка
while(1)
{
// Выводим значение нажатой кнопки на индикатор
switch(scan_key()){
case 1: PORTD = num[1]; break;
case 2: PORTD = num[2]; break;
case 3: PORTD = num[3]; break;
case 4: PORTD = num[4]; break;
case 5: PORTD = num[5]; break;
case 6: PORTD = num[6]; break;
case 7: PORTD = num[7]; break;
case 8: PORTD = num[8]; break;
case 9: PORTD = num[9]; break;
case 11: PORTD = num[0]; break;
default:
break;
}
}
} |
Последний раз редактировалось AlesyaS; 06.05.2016 в 19:44.
Причина: Немного подправила код :)
|
|
|
|
06.05.2016, 16:08
|
|
Почётный гражданин KAZUS.RU
Регистрация: 08.05.2008
Адрес: регион 63
Сообщений: 1,827
Сказал спасибо: 739
Сказали Спасибо 683 раз(а) в 386 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
Из кода ясно что сегменты подключены к PORTD, a знакоместа к младшим разрядам PORTB , или PORTC ? Целиком бы схему или проект. Непонятно как происходит перебор знакомест.
И нужно выводить в каждое знакоместо , свою цифру или чтоб они сдвигались по типу бегущей строки ?
__________________
Да здравствует Разум,да сгинет Маразм!
Последний раз редактировалось E_C_C; 06.05.2016 в 16:14.
|
|
|
|
06.05.2016, 16:19
|
|
Почётный гражданин KAZUS.RU
Регистрация: 20.03.2007
Адрес: "Братское кольцо враждебности", т.е. ближайшее заМКАДье.
Сообщений: 6,789
Сказал спасибо: 2,912
Сказали Спасибо 3,120 раз(а) в 2,111 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
1. Похоже, что scan_key почему-то не сбрасывается в 0 при отсутствии нажатий кнопок?
2. ЕМНИП, после каждого "return (key_value);" в "switch (PINB & 0xF0) {...};" надо ставить брейк.
|
|
|
|
06.05.2016, 16:27
|
|
Прохожий
Регистрация: 06.05.2016
Адрес: г. Санкт-Петербург
Сообщений: 9
Сказал спасибо: 5
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Семисегментный индикатор и клавиатура
Я хотела так:
Нажала на кнопку 1 на индикаторе 0001, затем нажала 2 на индикаторе, 0012 нажала 3 = 0123, 4 = 1234, а получаю 1111, 2222, 3333 и тд. Помогите пожаалуйста,
Последний раз редактировалось AlesyaS; 06.05.2016 в 17:30.
Причина: Добавила скриншот в высоком разрешении
|
|
|
|
06.05.2016, 18:48
|
|
Вид на жительство
Регистрация: 11.08.2015
Сообщений: 408
Сказал спасибо: 17
Сказали Спасибо 37 раз(а) в 28 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
Что-то у меня IAR гонит. Не видит числа 0b00001111 и биты регистра PC0, PC1 и т.д. Не знаете случайно как это исправить?
|
|
|
|
06.05.2016, 18:51
|
|
Почётный гражданин KAZUS.RU
Регистрация: 21.03.2007
Адрес: М.(осква)
Сообщений: 4,204
Сказал спасибо: 2,072
Сказали Спасибо 1,685 раз(а) в 956 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
Сообщение от ForcePoint
|
1. Похоже, что scan_key почему-то не сбрасывается в 0 при отсутствии нажатий кнопок?
2. ЕМНИП, после каждого "return (key_value);" в "switch (PINB & 0xF0) {...};" надо ставить брейк.
|
А зачем там столько ретурнов? Один раз. После кеисе.
__________________
+ 7 903 641 87 25// 1. Иногда отвечаю "по памяти" 2. Часто заблуждаюсь >> Критикуйте, не обижусь.
|
|
|
|
06.05.2016, 19:06
|
|
Прохожий
Регистрация: 06.05.2016
Адрес: г. Санкт-Петербург
Сообщений: 9
Сказал спасибо: 5
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Семисегментный индикатор и клавиатура
Сообщение от mtit
|
А зачем там столько ретурнов? Один раз. После кеисе.
|
Сделала так:
Код:
|
switch (PINB & 0xF0)
{
case 0b11100000: key_value = 1 + i * 3; break;
case 0b11010000: key_value = 2 + i * 3; break;
case 0b10110000: key_value = 3 + i * 3; break;
default:
break;
} |
|
|
|
|
06.05.2016, 19:23
|
|
Прописка
Регистрация: 19.02.2008
Адрес: г. Иркутск
Сообщений: 275
Сказал спасибо: 213
Сказали Спасибо 166 раз(а) в 78 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
По схеме индикация динамическая, а по программе статическая.
Поэтому разом все индикаторы показывают одно и тоже.
|
|
|
|
06.05.2016, 19:47
|
|
Прохожий
Регистрация: 06.05.2016
Адрес: г. Санкт-Петербург
Сообщений: 9
Сказал спасибо: 5
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Семисегментный индикатор и клавиатура
Сообщение от andron007
|
По схеме индикация динамическая, а по программе статическая.
Поэтому разом все индикаторы показывают одно и тоже.
|
Нашла кусок кода что мог бы мне помочь но не знаю как её внедрить...
Код:
|
switch(segcounter)
{
case 0:
PORTС = ~(SEGMENTE[display % 10000 / 1000]); // Раскладываем число на разряды
break;
case 1:
PORTС = ~(SEGMENTE[display % 1000 / 100]);
break;
case 2:
PORTС = ~(SEGMENTE[display % 100 / 10]);
break;
case 3:
PORTС = ~(SEGMENTE[display % 10]);
break;
}
if(segcounter++ › 2) segcounter = 0;
} |
|
|
|
|
06.05.2016, 20:34
|
|
Прописка
Регистрация: 19.02.2008
Адрес: г. Иркутск
Сообщений: 275
Сказал спасибо: 213
Сказали Спасибо 166 раз(а) в 78 сообщении(ях)
|
Re: Семисегментный индикатор и клавиатура
Сообщение от AlesyaS
|
Нашла кусок кода что мог бы мне помочь но не знаю как её внедрить...
|
Не думаю что этот кусок кода вам поможет.
Динамическую индикацию организовать проще и правильнее в прерывании по таймеру. У вас четыре индикатора (знакоместа), и вот включаете первое знакоместо PC0=0, (остальные выключены PC1=PC2=PC3=1) и выводите то что хотите видеть на этом месте через PORTD, при следующем прерывании включаете второе знакоместо и обновляете PORTD и т.д. То есть всегда светится только один индикатор, что бы не было видно мерцания переключать нужно с частотой не менее 30-50 Гц для одного индикатора, для четырех индикаторов 120-200 Гц.
А вообще если вам нужна программка так и напишите, а если
Сообщение от AlesyaS
|
Начала учить микроконтроллеры и программирование на Си совсем не давно. Просьба к Google и тп не отправлять, устала искать...
|
то без гугла тяжеловато будет.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 12:13.
|
|