Перекодировка

Заметил, что некоторые уважаемые люди до сих пор для перекодировки 7ми сегментника применяют казалось бы совсем ненужные вещи — бумагу или спец программы. Хочу предложить простенький метод (для асма, под С тоже наверно что-то такое можно сделать), который позволит забыть о доп инструментах:

;формирует таблицу символов datatab
;         bit  7     6     5     4     3     2     1     0
;     Das <- [segh][segg][segf][sege][segd][segc][segb][sega]
sega	equ 0
segb	equ 1
segc	equ 2
segd	equ 3
sege	equ 4
segf	equ 5
segg	equ 6
segh	equ 7
char0	equ (1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<sege)|(1<<segf);00
char1	equ (1<<segb)|(1<<segc)	;01
char2	equ (1<<sega)|(1<<segb)|(1<<segd)|(1<<sege)|(1<<segg);02
char3	equ (1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<segg);03
char4	equ (1<<segb)|(1<<segc)|(1<<segf)|(1<<segg);04
char5	equ (1<<sega)|(1<<segf)|(1<<segg)|(1<<segc)|(1<<segd);05
char6	equ (1<<sega)|(1<<segf)|(1<<segg)|(1<<segd)|(1<<sege)|(1<<segc);06
char7	equ (1<<sega)|(1<<segb)|(1<<segc);07
char8	equ (1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<sege)|(1<<segf)|(1<<segg);08
char9	equ (1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<segf)|(1<<segg);09

datatab dcb char0,char1,char2,char3,char4,char5,char6,char7,char8,char9


Меняем расположение сегментов (sega-segh) в порте и автоматом получаем новую таблицу образов символов. Все просто до безобразия :)
Для AVR:

;         bit  7     6     5     4     3     2     1     0
;     Das <- [sega][segf][segb][segh][segg][segc][sege][segd]
.equ sega	= 7
.equ segb	= 5
.equ segc	= 2
.equ segd	= 0
.equ sege	= 1
.equ segf	= 6
.equ segg	= 3
.equ segh	= 4
.equ char0	= (1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<sege)|(1<<segf);00
.equ char1	= (1<<segb)|(1<<segc);01
.equ char2	= (1<<sega)|(1<<segb)|(1<<segd)|(1<<sege)|(1<<segg);02
.equ char3	= (1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<segg);03
.equ char4	= (1<<segb)|(1<<segc)|(1<<segf)|(1<<segg);04
.equ char5	= (1<<sega)|(1<<segf)|(1<<segg)|(1<<segc)|(1<<segd);05
.equ char6	= (1<<sega)|(1<<segf)|(1<<segg)|(1<<segd)|(1<<sege)|(1<<segc);06
.equ char7	= (1<<sega)|(1<<segb)|(1<<segc);07
.equ char8	= (1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<sege)|(1<<segf)|(1<<segg);08
.equ char9	= (1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<segf)|(1<<segg);09

datatab: .DB char0,char1,char2,char3,char4,char5,char6,char7,char8,char9


Таблицу, естественно, размещайте где положено. Успехов всем!
  • +4
  • 07 апреля 2011, 15:30
  • psv

Комментарии (21)

RSS свернуть / развернуть
Была у меня мысль нечто подобное сделать, всё руки не дошли. Теперь умыкну :)
Это дело в отдельный файл да в include прописать.
0
Офигенно!
0
Прекрасная идея!
Вот, для Паскаля. Здесь сама табличка и код для примера.
Программа выводит числа от 0 до 9 на индикатор, подключенный к порту B (под ATTiny2313, но работать будет везде, где есть порт B :)).

program _7segtabletest;

const
// Сегмент индикатора  = Пин
      segment_A        = 0;
      segment_B        = 1;
      segment_C        = 2;
      segment_D        = 3;
      segment_E        = 4;
      segment_F        = 5;
      segment_G        = 6;
      segment_DP       = 7;

 Char_7seg: array[0..9] of byte =
(
{0} (1 shl segment_F) or (1 shl segment_E) or (1 shl segment_D) or (1 shl segment_C) or (1 shl segment_B) or (1 shl segment_A),
{1} (1 shl segment_C) or (1 shl segment_B),
{2} (1 shl segment_D) or (1 shl segment_E) or (1 shl segment_G) or (1 shl segment_B) or (1 shl segment_A),
{3} (1 shl segment_G) or (1 shl segment_D) or (1 shl segment_C) or (1 shl segment_B) or (1 shl segment_A),
{4} (1 shl segment_G) or (1 shl segment_F) or (1 shl segment_C) or (1 shl segment_B),
{5} (1 shl segment_G) or (1 shl segment_F) or (1 shl segment_D) or (1 shl segment_C) or (1 shl segment_A),
{6} (1 shl segment_G) or (1 shl segment_F) or (1 shl segment_E) or (1 shl segment_D) or (1 shl segment_C) or (1 shl segment_A),
{7} (1 shl segment_C) or (1 shl segment_B) or (1 shl segment_A),
{8} (1 shl segment_G) or (1 shl segment_F) or (1 shl segment_E) or (1 shl segment_D) or (1 shl segment_C) or (1 shl segment_B) or (1 shl segment_A),
{9} (1 shl segment_G) or (1 shl segment_F) or (1 shl segment_D) or (1 shl segment_C) or (1 shl segment_B) or (1 shl segment_A)
);

begin
DDRB := 255; //Все пины порта В на выход.

R22 := 0; // Очищаем р22
while true do // Endless loop
 begin
  PORTB := Char_7seg[R22]; //Выкидываем текущее значение
  Delay_ms(1000); // Ждем секундочку
  Inc(r22); // Инкремент
  if R22 = 10 then r22 := 0; //Следим за тем, чтобы не улететь за край массива.
 end;
end.
0
Метод, прямо скажем, очевидный.
Но с другой стороны — нужно оно разве что если оформить инклудом и таскать из проекта в проект. Однократно проще посчитать числа, чем катать такую табличку.
0
  • avatar
  • Vga
  • 07 апреля 2011, 19:40
Проще имхо сделать
SegArr[10]={
0b00111111,
0b00000110,

};

Потом делать PORTB = SeqArr[цифра];
+1
а теперь так же легко и непринужденно поменяйте местами сегменты c и h, а остальные сдвиньте по кольцу :)
0
Однократно проще посчитать числа, чем катать такую табличку.
Согласен. За то и благодарим автора — все поленились, а он накатал. Бери и пользуйся :)
0
Зачем считать? не пойму. Скопировали. Сконфигурировали для макетки. Разводим плату — циферки поменяли. Ошиблись — циферки поменяли и все
0
Что считать? не понял вас.
0
Почему однократно проще посчитать? Тем более что однократно редко бывает. А если добавить еще и другие символы
0
Не проще, а быстрее! Вашу таблицу ведь придумать надо, написать и отладить :)
0
ну вот теперь-то она готова. всеобщее счастье!
0
Наверное, я хреново объяснил. Вся работа в новом проекте — скопировать все из предыдущего и поменять цифры, которые соответствуют положению сегментов в байте. Неужто дольше пересчета? Ничего катать, придумывать, писать и отлаживать не нужно! Ну да ладно.
0
  • avatar
  • psv
  • 07 апреля 2011, 23:33
Вот поэтому лучше оформить инклудом, чтобы потом
const
  _7seg_a=0;
  _7seg_b=1;
  ...
  _7seg_dp=7;
{$I 7seg_codetable.inc}

Или аналогично для С, только немного другой синтаксис. Заодно можно кроме цифр забить другие отображаемые на семисегментнике знаки.
0
Короче, вы нас не поняли. Мы про то же и говорим.
0
Вот бы так же просто решалась задача, когда сегменты не на одном порту висят, а растасканы по пинам разных портов, причем даже не подряд — вразброс.

Вообще, пока только один метод нашёл — каждый пин включается отдельной командой. Куча if-ов получается, код разбухает… Плюс у авров в ините надо DDR включать… ужас-ужас, в общем. (не, вру — просто ужас)
0
статья «работа с портами ввода-вывода на C++» вам в этом поможет
0
Это где про «виртуальные порты»?
Да, интересно. Спасибо.
Зря я «учебный курс» игнорирую, видать.

Но все равно громоздко. Куча ифов заменяется на кучу битовых операций.
Ведь если у порта используются, к примеру, пины 1,2,5 и 7 — уже не напишешь
PORTB = (PORTB & 0x0f) | (value & 0xf0) >> 4;
— придётся несколько действий с разными масками писать, чтобы value на биты раздербанить.
Тем более, если в эти пины надо отображать из value биты 2,0, 7 и 8, а остальные — по другим портам (а шо поделать, у схемотехника свои сображения).

И таки хочется задефайнить распределение пинов где-нибудь в начале, или в хедере.
0
Давно не занимаюсь таким гемором как разбрасывание сегментов по портам. Если по каким-либо соображениям сегменты не могут попасть на один порт — добавляю 74HC595 (а то и две — для разрядов) и применяю ту же (выше описаную) схему перекодировки.
0
  • avatar
  • psv
  • 16 июня 2011, 23:59
Я ж говорю — у схемотехника свои соображения, а мне как программисту приходится работать со схемой, какую дали.
И я даже знаю эти соображения — во-первых, очень нужные спецфункции пинов на всех портах (и на индикатор отдаётся что осталось), во-вторых, дополнительный чип (хотя и копеечный) на тысячной серии даст уже хорошую сумму затрат, явно превышающую зарплату программиста за несколько часов потраченных на соответствующую процедуру.
0
вот еще немного:
// 7-segment symbols
#define I7S_ALL_ON  (0)
#define I7S_ALL_OFF (0xff)
#define I7S_SPACE   (I7S_ALL_OFF)
#define I7S_MINUS   I7S_SG
#define I7S_POINT   I7S_SH
#define I7S_0    ((U8)(I7S_SA & I7S_SB & I7S_SC & I7S_SD & I7S_SE & I7S_SF))
#define I7S_1    ((U8)(I7S_SB & I7S_SC))
#define I7S_2    ((U8)(I7S_SA & I7S_SB & I7S_SD & I7S_SE & I7S_SG))
#define I7S_3    ((U8)(I7S_SA & I7S_SB & I7S_SC & I7S_SD & I7S_SG))
#define I7S_4    ((U8)(I7S_SB & I7S_SC & I7S_SF & I7S_SG))
#define I7S_5    ((U8)(I7S_SA & I7S_SC & I7S_SD & I7S_SF & I7S_SG))
#define I7S_6    ((U8)(I7S_SA & I7S_SC & I7S_SD & I7S_SE & I7S_SF & I7S_SG))
#define I7S_7    ((U8)(I7S_SA & I7S_SB & I7S_SC))
#define I7S_8    ((U8)(I7S_SA & I7S_SB & I7S_SC & I7S_SD & I7S_SE & I7S_SF & I7S_SG))
#define I7S_9    ((U8)(I7S_SA & I7S_SB & I7S_SC & I7S_SD & I7S_SF & I7S_SG))
#define I7S_A    ((U8)(I7S_SA & I7S_SB & I7S_SC & I7S_SE & I7S_SF & I7S_SG))
#define I7S_b    ((U8)(I7S_SC & I7S_SD & I7S_SE & I7S_SF & I7S_SG))
#define I7S_C    ((U8)(I7S_SA & I7S_SD & I7S_SE & I7S_SF))
#define I7S_Cm   ((U8)(I7S_SA & I7S_SB & I7S_SC & I7S_SD))
#define I7S_c    ((U8)(I7S_SD & I7S_SE & I7S_SG))
#define I7S_d    ((U8)(I7S_SB & I7S_SC & I7S_SD & I7S_SE & I7S_SG))
#define I7S_E    ((U8)(I7S_SA & I7S_SD & I7S_SE & I7S_SF & I7S_SG))
#define I7S_F    ((U8)(I7S_SA & I7S_SE & I7S_SF & I7S_SG))
#define I7S_H    ((U8)(I7S_SB & I7S_SC & I7S_SE & I7S_SF & I7S_SG))
#define I7S_h    ((U8)(I7S_SC & I7S_SE & I7S_SF & I7S_SG))
#define I7S_L    ((U8)(I7S_SD & I7S_SE & I7S_SF))
#define I7S_n    ((U8)(I7S_SC & I7S_SE & I7S_SG))
#define I7S_o    ((U8)(I7S_SC & I7S_SD & I7S_SE & I7S_SG))
#define I7S_P    ((U8)(I7S_SA & I7S_SB & I7S_SE & I7S_SF & I7S_SG))
#define I7S_q    ((U8)(I7S_SA & I7S_SB & I7S_SC & I7S_SF & I7S_SG))
#define I7S_r    ((U8)(I7S_SE & I7S_SG))
#define I7S_t    ((U8)(I7S_SD & I7S_SE & I7S_SF & I7S_SG))
#define I7S_Y    ((U8)(I7S_SB & I7S_SC & I7S_SD & I7S_SF & I7S_SG))
#define I7S_U    ((U8)(I7S_SB & I7S_SC & I7S_SD & I7S_SE & I7S_SF))
#define I7S_u    ((U8)(I7S_SC & I7S_SD & I7S_SE))
#define I7S_Pcyr ((U8)(I7S_SA & I7S_SB & I7S_SC & I7S_SE & I7S_SF))
#define I7S_Gcyr ((U8)(I7S_SA & I7S_SE & I7S_SF))

0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.