Многоуважаемые коты, помогите! Вот уже который день пытаюсь решить следующую задачу. Есть ИК-пульт, протокол РС5, нужно записать в массив последовательность команд(к примеру a[8]), затем эту последовательность привести к виду a = 12345678; Пробовал в обработчике прерывания произвести следующие манипуляции
Код:
const char N = 8; unsigned long a[N]; char k; interrupt [EXT_INT0] void ext_int0_isr(void) { a[k] = command;
"последовательность значений массива представить в виде числа"? Каким образом?
вот и я о том же.... представлю код... в двух словах, в прерывании по приходу команды с ИК-пульта, происходит расшифровка этой команды и ее значение заносится в соответствующую ячейку массива(
Код:
int a[k] = command; k++; if(k == 8){k=0;}]
с этим думаю понятно... а теперь продолжение, в этой части кода происходит передача заданного числа по SPI на 7-ми сегментники
Код:
typedef unsigned char byte; typedef unsigned long ulong;
void show_dig() { SS=0; //Ни чего не передаем if (dig_num==0) { dig_data=show_data; //Если показываем первую цифру обновляем переменную dig_num++; } spi(dig_num); //Отправляем байт для отображения разряда spi(led_table[dig_data%10]); //Получаем разряд из dig_data и отправляем байт с цифрой dig_data/=10; dig_num<<=1; //Смещаем бит для отображения следующего разряда SS=1; //Показываем разряд } // Timer 1 overflow interrupt service routine interrupt [TIM1_OVF] void timer1_ovf_isr(void) { show_dig(); //Отображаем разряды }
так вот, полученный массив a[k] нужно каким-то образом перевести в переменную ulong show_data=12345678. только вместо цифр(12345678) были цифры из массива.
!@#$%. Объясните на примере чего вы хотите. Что на входе, и что на выходе. Если вы сами не можете вопсроизвести действия программы, то никогда ее и не напишете.
UPD. Ладно, если я сейчас угадаю, что вы хотите, может быть перестанете выносить мозг мне и остальным.
У вас в массиве хранятся числа от 0 до 9? Вам нужно примерно то, что я описал в предыдущем сообщении? Тогда вот мой быдлокод:
Код:
long show_data = 0; char a[ARRAY_LENGTH] = {1, 3, 6, 6, 6, 1, 3} int i; long mul = 1;
Уважаемый, blackx, спасибо за терпение. Передо мной стоит такая задача, я на пульте нажимаю кнопку(пусть 5, не важно) на 7-ми сегментнике появляется соответствующая цифра а не команда, нажал на другую клавишу на следующем разряде появилась эта цифра и т.д. Вот я и думал, что сначала все эти номера команд и соответсвующие им цифры занести в отдельный массив, а потом уже этот массив перевести число, которое можно передать в SPI.
P.S. пишу не так давно, поэтому не серчайте на глупые вопросы
Вроде начинаю понимать. У вас есть массив с кодами команд RC-5. В этих кодах команды 0-9 соответствуют нажатию соотв клавиш 0-9. По приходу команды, вы ее заносите, и, если это цифра, то происходит ввод числа (с контролем позиции), и вам нужно вывести полученное число на индикатор. Так?
В любом случае для этого вам не нужно переводить массив ни в какие числа, как я уже и говорил. У вас есть массив led_table, соответственно, чтобы получить код цифры индикатора по команде вы просто должны взять из массива соответствующее значение: led_table[a[i]]. Например, для 2 это будет 0b00100101. Вот его и передавайте по SPI. А уж когда в программе нужно будет интерпретировать {2, 4, 9} как 249 - то адаптируйте для себя алгоритм из моего предыдущего сообщения.
А теперь встречные вопросы: 1. Как у вас подключен семисегментный индикатор и сколько в нем секций? 2. Зачем используется SPI? Индикатор у вас подключен через сдвиговый регистр?
ответ на встречные вопросы... 7-ми сегментник с 8-ю разрядами подключен через сдвиговые регистры 74hc595 схема во вложении.
Pawlo писал(а):
По приходу команды, вы ее заносите, и, если это цифра, то происходит ввод числа (с контролем позиции), и вам нужно вывести полученное число на индикатор. Так?
Да. Следующий глупый вопрос, а как это более правильно реализовать?
В общем, как это реализовать. Я не вникал особо в ваш код, скажу как бы я сделал. Вам нужно по прерыванию таймера сделать код обновления значений индикатора. Не знаю, как это будет визуально выглядеть в протеусе. Суть в том, что вы заводите какой-нибудь глобальный массив, который хранит текущее значение дисплея в виде массива байтов (unsigned char). Т. е. в нем хранятся уже закодированные для семисегментника значения - один из возможных символов - числа 0-9, знак "-", может быть какие-то буквы и т. д. Как происходит кодирование - на данном этапе неважно. Потом необходимо реализовать прерывание по таймеру для обновления дисплея, которое вызывает функцию обновления с небольшой частотой (меньше килогерц, т. к. это все-таки отнимает ресурсы. Можно уменьшить вплоть до ~50 Гц. Но я не знаю как это в протеусе это будет выглядеть визуально). Функция обновления будет по одному запихивать через первый сдвиговый регистр каждый из 8 значений для каждого сегмента. Это будут значения типа 0b00000000 - сегмент пустой, 0b11111111 - цифра 8 с точкой и также прочие символы, код которых я так по памяти не скажу - думаю тут и так понятно. При этом переключение между символами происходит засчет второго сдвигового регистра. Если у вас индикатор с общим катодом, то на этот второй регистр нужно подавать сначала 0b011111111, если с общим анодом - 0b100000000, а затем мы этот нолик или единичку сдвигаем чтобы зажечь новую секцию. Т. е. алгоритм работы функции обновления такой:
Код:
unsigned char indicator_data[8] = { ... }
indicator_update() {
for(i=0; i<8; i++) { send_shift_reg_U3(0b011111111 >> i); // общий катод; двигаем ноль на i вправо send_shift_reg_U2(indicator_data[i]); }
}
Функции по отсылке байт в регистры U2 и U3 напишете - это уже ваше дело, SPI использовать, или просто портами вручную управлять. Их задача "отключить" вывод регистров, засунуть в них байт данных (при этом обеспечить нужное тактирование входа) и "включить" его заново.
Напишите сначала это, потом будет проще уже с остальной логикой разобраться.
PS. Да, если вы новичок в электронике. Не забудьте добавить на схему необходимый обвес к микроконтроллеру, ограничительные резисторы везде где надо и транзисторы для управления секциями, перед тем как это паять.
PS2. Блин, плохо посмотрел на схему - у вас же сдвиговые регистры последовательно соединены В общем у вас вместо send_shift_reg_U3 и send_shift_reg_U2 должна быть одна функция, которая принимает не один байт, а сразу два:
Код:
send_indicator_data(unsigned short); //прототип
...
unsigned short data = (((unsigned short)(0b011111111 >> i)) << 8) & indicator_data[i]; send_indicator_data(data);
Надеюсь, не напугал конструкцией. Тут просто два байта в одну переменную типа short забиваются.
С выводом на индикаторы, как раз проблем не возникает, основная проблема это ввод цифр
Pawlo писал(а):
void show_dig() { SS=0; //Ни чего не передаем if (dig_num==0) { dig_data=show_data; //Если показываем первую цифру обновляем переменную dig_num++; } spi(dig_num); //Отправляем байт для отображения разряда spi(led_table[dig_data%10]); //Получаем разряд из dig_data и отправляем байт с цифрой dig_data/=10; dig_num<<=1; //Смещаем бит для отображения следующего разряда SS=1; //Показываем разряд }
я эту функцию уже расписал... основная загвоздка это правильный перевод входящих команд в число для отображения за отображаемое число отвечает переменная show_data. я ее представляю в виде show_data=12345678 или show_data=55223388, или взаимосвязь представить так show_data = a[k]?
Переделайте для начала, чтобы было как я сказал. show_dig() должна брать массив с кодами для семисегментника и отображать все цифры сразу.
Семисегментник - устройство для отображения не только цифр, но и символов. Вот например захотите вы кроме числа отобразить еще где-нибудь точку, или знак "-", или букву "H". И вам придется писать кривые костыли.
Для перевода числа (-423423) в коды пишется уже отдельная функция генерации массива кодов. Мой вариант отделяет код обновления дисплея и код генерации кодов на основе числа (типа -423423), строки ("-4234.23"), да чего угодно еще. Т. е. таких функций может быть и несколько. Если вам нужно отображать только цифры, то и пишете только нужную функцию.
Вам то конечно может не потребоваться такая лишняя функциональность. Но был вопрос,
Цитата:
... а как это более правильно реализовать?
. Такой подход придает коду гибкость. И так делать правильно.
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения