Страница 1 из 2

кодирование знаков на семисегментнике

Добавлено: Ср июн 24, 2009 12:01:04
DrWatson
Не знал куда выложить, поэтому на всякий случай создал тему здесь.
Недавно наваял простенькую программку для кодирования символов на семисегментник. В принципе интерфейс должен быть интуитивно понятным. Надеюсь кому-то еще пригодится.
Жду вопросов, конструктивной критики и предложений.

Добавлено: Ср июн 24, 2009 12:13:48
Arlleex
я уже где то спрашивал, что мол, можно зажигать сетодиоды так:

0b00000001
например, или вот так:
DDRD 0b10110001 - горят 4 светодиода
мне толком не было понятно.

если так можно, то скажите плиз, можно ли зажечь сразу все светодиоды на порту? порт не вылетит? мне кажется вылетит с такой нагрузкой. а что таогда делать? импульсно включать их тогда?

Добавлено: Ср июн 24, 2009 12:32:17
DrWatson
Смотрим по даташиту: обычно у каждой линии порта нагрузочная способность 40мА, а на весь кристалл по шинам питания ток также должен быть ограничен (обычно 200мА). Если у нас на каждой линии порта ток будет по 20мА, то при зажигании всех 8 светодиодов по одной из шин питания МК пойдет ток 160мА - что вполне допустимо, так как меньше предельных 200. А если светодиоды сверхяркие, то можно ток на них и по 10мА сделать, поставив ограничительные резисторы сопротивлением побольше.

Добавлено: Ср июн 24, 2009 14:22:01
ARV
Палыч, вы забыли о том, что обычно еще дается ограничение на суммарный ток одного порта... и он обычно около 100 мА, так что все 8 линий по 20 мА нежелательно грузить.

Добавлено: Ср июн 24, 2009 15:08:21
DrWatson
Точно, оно оказывается в примечаниях в Даташите на МК указано.
Для ATmega16 стр.286 Даташита:
Although each I/O port can sink more than the test conditions (20 mA at Vcc = 5V, 10 mA at Vcc = 3V) under steady state
conditions (non-transient), the following must be observed:
PDIP Package:
1] The sum of all IOL, for all ports, should not exceed 400 mA.
2] The sum of all IOL, for port A0 - A7, should not exceed 200 mA.
3] The sum of all IOL, for ports B0 - B7,C0 - C7, D0 - D7 and XTAL2, should not exceed 300 mA
If IOL exceeds the test condition, VOL may exceed the related specification. Pins are not guaranteed to sink current greater
than the listed test condition.
Но если я правильно понял, здесь при бОльших чем указано токах не гарантируется указанное в таблице значение напряжения низкого уровня. То есть для управления 8 светодиодами можно с порта взять и по максимуму 40*8=320мА<400мА, просто это может сказаться на напряжениях логических уровней на других выходах (низкий - завысить, либо высокий занизить) и другие цифровые микросхемы подключенные к остальным портам могут эти уровни неадекватно воспринять.
Вот только почему они в таблице "Absolute Maximum Ratings" ток по выводам питания указали 200мА, грозя за превышение убийством МК, а в примечаниях - 400мА по сути по отдельно взятому выводу питания.
Для верности, конечно, лучше руководствоваться минимальными значениями предельно допустимых параметров.

Добавлено: Ср июн 24, 2009 15:33:18
SeregaT
Stalker46 писал(а):если так можно, то скажите плиз, можно ли зажечь сразу все светодиоды на порту? порт не вылетит?
Не вылетит. Проверено :) В даташите указаны допустимые токи (у меги 8 вроде до 40 ма на канал и 300 ма общего потребления).

Добавлено: Ср июн 24, 2009 17:25:38
Пухич
Вот только почему они в таблице "Absolute Maximum Ratings" ток по выводам питания указали 200мА, грозя за превышение убийством МК, а в примечаниях - 400мА по сути по отдельно взятому выводу питания.
Вот-вот. Очень специфический момент. Учитывая, что нет точных данных от фирмы "Атмел" относительно расчета коэффициента нагрузки в зависимости от потреблений, а кроме того нету интенсивности отказов. Т.е. про надежность мы ничего не знаем...... Соответственно непонятно - как же его грузить?
Для верности, конечно, лучше руководствоваться минимальными значениями предельно допустимых параметров.
Да и из них как-то не всегда хорошо выходит....

Добавлено: Ср июн 24, 2009 22:21:28
nik-as
ИМХО для верности лучше повторители ставить типа 155ЛП9, или инверторы типа 155ЛН3.
А ещё преобразователи кодов существуют типа 155ПП5 которые могут не только разгрузить МП
но и высвободить порты для других целей.
В этом случае контроллер точно не пострадает по причине перегрузки.

Добавлено: Ср июн 24, 2009 23:31:15
Brigadir
Вернемся к программке Палыча. Это что? Очередная игрушка для малых детей?

Добавлено: Чт июн 25, 2009 08:31:39
DrWatson
Brigadir писал(а):Вернемся к программке Палыча. Это что? Очередная игрушка для малых детей?
Вот появился и вопрос по существу темы.
Скорее это инструмент для ускорения процесса кодирования символов для семисегментника в Си.
Эта программка должна быть полезной, если сегменты индикатора подключены к порту не по порядку (бит 0 - a, ..., бит 7 - h), а так, как удобнее развести плату. Т.е. в ней задается к какому биту порта какой сегмент подключен, определяется тип индикатора (ОА или ОК) и рисуем нужные нам цифры и др. знаки (щелкая мышью по соответствующим сегментам), в ответ на что программа показывает, какой код нужно выдать в порт, чтоб получился нужный нам символ. Также генерируется массив в синтаксисе Си для кодирования, допустим, цифр.

Добавлено: Чт июн 25, 2009 08:46:24
nik-as
Программка действительно нужная, но если бы вы добавили кодирование символов для вывода
на дешифратор для СИД, ей бы вообще цены не было. :)

Добавлено: Чт июн 25, 2009 08:52:14
DrWatson
Аббревиатуру расшифруйте пожалуйста, а то я что-то не догоняю.

Добавлено: Чт июн 25, 2009 09:01:26
nik-as
СИД - Семисегментный индикатор

Добавлено: Чт июн 25, 2009 09:08:30
DrWatson
Шутку понял - оценил. :lol:
Но в случае с МК мы обычно стараемся обойтись без дешифратора для СИД.
Оффтоп: И немного поправлю Вас в части орфографии, если Вы не против. Я один, а когда к одному человеку обращаются на Вы, то букву "В" ставят прописную (большую). По всей видимости, это придумано для того, чтобы различить обращение к нескольким людям и вежливое обращение к одному человеку.

Добавлено: Чт июн 25, 2009 09:21:45
nik-as
К сожалению это не шутка, аббревиатура придумана не мной.
а буква В маленькая только по тому что лень лишний раз shift нажать. :))

Добавлено: Чт июн 25, 2009 09:55:11
ARV
по поводу "Вы". лично я преотлично знаю русский язык, но постоянное общение в интернете вырабатывает особую манеру письменного общения - с этим нельзя бороться. в частности, привычка ставить точки в конце предложения, но не начинать новое с большой буквы :) вот и в отношении "Вы" и "вы" сложилось так, что (лично я) использую "Вы" только в том случае, если хочу подчеркнуть исключительную официальность общения, т.е. без намека на товарищество. ну, иногда, если хочу вежливо оскорбить - тоже использую "Вы" - т.е. прямо с противоположным правилам языка смыслом. правда, порой использую "Вы" именно для подчеркивания уважения - это, обычно, видно и по самому тексту, так что спутать сложно :) такая вот у меня манера... это касается форумов, в частной почтовой переписке я стараюсь следовать настоящим, а не естественно переродившимся, правилам.

что касается программы - честно говоря, ее смысл сводится к преобразованию двоичного кода в шестнадцатеричный. т.е. биты-сегменты мы клацаем мышкой, а число в HEX получается автоматом.

тасовать сегменты элементарно и без программы - я вот один раз сделал файлик, в котором расписал все сегменты и символы, которые из них можно построить, и теперь пользуюсь в любой программе. этот файлик любой желающий найдет среди исходников моих термостатов, которые я на сайте у себя выкладывал.

хуже всего дело обстоит в том случае, когда сегменты и общие катоды-аноды индикаторов перемешаны среди нескольких портов, например, семегнты ABCD и общий катод первого индикатораподключены к порту В, сегменты EF и второй катод к порту D, а остальные - к порту С. тут и ваша программка не поможет, и возни с выводом немало. универсальное решение практически сделал molchec, он назвал это "программным драйвером". то есть его драйвер позволяет наладить индикацию при произвольном размещении сегментов по портам, хоть по одному сегменту на порт, и при этом переделок в программе не придется делать - только определить в массивах назначение выводов. но эта универсальность оборачивается объемом кода...

Добавлено: Чт июн 25, 2009 10:43:39
Настя
Не могу не присоединиться, точнее переборола свою лень.
Способов отрисовки разряда семисегментника множество
и это множество реализуется без особого напряжения ума.

Первая подсказка. Каждая IO линия каждого порта имеет свой "вес".
И обсчет "готовых" символов делается в момент компиляции.
Пример на ассме (не многим отличается от Си)

Код: Выделить всё

#define     _. .1   ; RB0
#define     _C .2   ; RB1
#define     _D .4   ; RB2
#define     _E .8   ; RB3
#define     _B .16  ; RB4
#define     _A .32  ; RB5
#define     _F .64  ; RB6
#define     _G .128 ; RB7

; если индикатор с общим анодом, то сумму
; нужно отнять от 255, например, для 
; символа "1" написать 255-(_B+_C)
#define     _0 addlw (_A+_B+_C+_D+_E+_F)
#define     _1 addlw (_B+_C)
#define     _2 addlw (_A+_B+_G+_E+_D)
#define     _3 addlw (_A+_B+_G+_C+_D)
#define     _4 addlw (_F+_G+_B+_C)
#define     _5 addlw (_A+_F+_G+_C+_D)
#define     _6 addlw (_A+_F+_G+_C+_D+_E)
#define     _7 addlw (_A+_B+_C)
#define     _8 addlw (_A+_B+_C+_D+_E+_F+_G)
#define     _9 addlw (_A+_B+_C+_D+_F+_G)
#define     _Н addlw (_B+_C+_E+_F+_G)
Как видим - это всё лишь арифметика. И при этом
я даже не задумываюсь, а сколько там символу "9"
соответствует число, которое будет отправлено в порт.

При всей простоте подхода это решение (как и многие другие)
накладывает ограничения на свободу разводки печатной платы.
Классическая школа программирования из "кода в код" "навяливает"
подключение разряда на линии одного порта. Это неудобно
с т.зр. рисования печатной платы. Всё прекрасно работает и на
разных портах. Правда Протеус не переваривает на частоте
более 1мгц тактовой. На Си выглядит не менее сложно.

Ниже Си пример подключения вразноброд линий двух разрядов
к разным портам (чтобы понять идею, см. печатную плату;
схему не рисовала, т.к. по железу всё и так понятно )

Код: Выделить всё

// === сопоставление сигнальных линий индикатора
// первый сегмент (десятки)
#define A1 RB5
#define B1 RB4
#define C1 RA0
#define D1 RA7
#define E1 RA6
#define F1 RB7
#define G1 RB6
#define H1 RA1
[b]#define Y1 RA2 // общ катод[/b]
// второй сегмент (единицы)
#define A2 RB5
#define B2 RB6
#define C2 RA6
#define D2 RA0
#define E2 RA1
#define F2 RB4
#define G2 RA7
#define H2 RB7
[b]#define Y2 RA3 // общ катод[/b]
Далее описываем символы (форма записи элементарна,
первое что пришло в голову)

Код: Выделить всё

// === массив констант с описанием символов
const unsigned char sim[10] = {
//	0bABCDEFGH
	0b11111100, // 0
	0b01100000, // 1
	0b11011010, // 2
	0b11110010, // 3
	0b01100110, // 4
	0b10110110, // 5
	0b10111110, // 6
	0b11100000, // 7
	0b11111110, // 8
	0b11110110, // 9
};
Далее собственно отрисовка

Код: Выделить всё

// === рисуем сегменты
void ris (unsigned char zn, unsigned char s)
// zn - знакоместо, s - собственно символ
{	if (zn == 1) {
	tmp = sim[s];
	A1 = tmp.b0;
	B1 = tmp.b1;
	C1 = tmp.b2;
	D1 = tmp.b3;
	E1 = tmp.b4;
	F1 = tmp.b5;
	G1 = tmp.b6;
	H1 = tmp.b7;
	}
	if (zn == 2) {
	tmp = sim[s];
	A2 = tmp.b0;
	B2 = tmp.b1;
	C2 = tmp.b2;
	D2 = tmp.b3;
	E2 = tmp.b4;
	F2 = tmp.b5;
	G2 = tmp.b6;
	H2 = tmp.b7;
	}
}
Ну и третье. Кому ну очень много индикаторов надо - сделайте
так как во втором приложенном файле - мне потребовалось три
сигнальных линии для управления 64-ю светодиодными сегментами.

ARV - и я того же мнения.

Добавлено: Чт июн 25, 2009 10:51:12
Настя
да и вообще - тема не для МЯЯЯУ!

Добавлено: Чт июн 25, 2009 11:56:01
DrWatson
Спасибо за комментарии, а Насте отдельное спасибо за пример кода - буду знать.
И небольшое замечание, если Настя не против: вместо

Код: Выделить всё

255-(_B+_C)
все-таки лучше использовать запись

Код: Выделить всё

~(_B+_C)
такая запись нагляднее отражает суть производимого действия.
Помещая тему в "МЯЯЯУ!", я и не предполагал, что она дорастет до раздела "Микроконтроллеры и ПЛИС".

Добавлено: Чт июн 25, 2009 13:28:52
Настя
DrWatson писал(а): вместо

Код: Выделить всё

255-(_B+_C)

все-таки лучше использовать запись

Код: Выделить всё

~(_B+_C)

такая запись нагляднее отражает суть производимого действия
да как угодно, хоть так

Код: Выделить всё

tmp = (_B+_C);
tmp^=0xFF;
:)))