Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Таблицы
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > PIC
Algol
День добрый!
Недавно начал осваивать Си (HT-PICC) и все было хорошо, пока мне не приспичило сделать таблицу перекодировки. На асме я писал вот так, все просто и понятно - перед вызовом процедуры кидаем в W цифру, образ которой хотим получить

TABLE
ADDWF PCL,1
RETLW B'11101011' ;0
RETLW B'01100000' ;1
RETLW B'11000111' ;2
RETLW B'11100101' ;3

Вопрос к знатокам, как мне сделать тоже самое, но только на Си?
psL
Цитата(Algol @ Jul 31 2006, 12:28) *
День добрый!
Недавно начал осваивать Си (HT-PICC) и все было хорошо, пока мне не приспичило сделать таблицу перекодировки. На асме я писал вот так, все просто и понятно - перед вызовом процедуры кидаем в W цифру, образ которой хотим получить

TABLE
ADDWF PCL,1
RETLW B'11101011' ;0
RETLW B'01100000' ;1
RETLW B'11000111' ;2
RETLW B'11100101' ;3

Вопрос к знатокам, как мне сделать тоже самое, но только на Си?


char conv[]={ 0xEB, 0x60, 0xA7, 0xE5 };

...

char in=1;
char out=conv[in];
upc2
Использовать конструкцию "switch case"
Algol
upc2
Конструкция switch - case не даст тождественного результата, хотя это самый очевидный путь. Работать будет, но с потерей производительности прямо пропорционально объему таблицы. Но все равно, спасибо, за совет.

psL
Огромное спасибо за ценный пример! Использовать перечислимый тип мне честно сказать даже и в голову не пришло бы. smile.gif
upc2
1.Согласен, что массив в по сравнению с switch - case эффективней.Но здесь надо следить за
индексом.При преобразовании цифр он прекрасно подходит.А если символы?Надо составлять
таблицу для индекса или размещать их согласно своего номера в базе?А если данные берутся из
потока?
2.Надо исходить из конкретного компилятора.Настройте проект на генерацию AS. файла и
посмотрите коды.При разных вариантах на ассемблере.В некоторых случаях даже конструкция IF
эффективней.
3.Что вы имеете под-<<Конструкция switch - case не даст тождественного результата>>?
Algol
По п.1 согласен, что с буквами будут дополнительные сложности, но в данном случае мне трубовались только цифры.
Под тождественным результатом, я имел ввиду производительность, т.е. эффект от IF будет тот же что и от массива, а быстродействие ниже.

По поводу п.3 провел сейчас небольшое исследование сгенеринного кода. В общем то массив представляется как и надо - командами retlw. Однако на его организацию уходит около 60 байт!!! Сравнил с кодом на асме - там всего 13 байт для 10 цифр.
_Bill
Цитата(Algol @ Aug 1 2006, 09:30) *
По п.1 согласен, что с буквами будут дополнительные сложности, но в данном случае мне трубовались только цифры.
Под тождественным результатом, я имел ввиду производительность, т.е. эффект от IF будет тот же что и от массива, а быстродействие ниже.

По поводу п.3 провел сейчас небольшое исследование сгенеринного кода. В общем то массив представляется как и надо - командами retlw. Однако на его организацию уходит около 60 байт!!! Сравнил с кодом на асме - там всего 13 байт для 10 цифр.

И как Вы этот массив описываете? Как доступ к нему осуществляется?
Algol
В случае Си, так как посоветовал psL. В случае асма см. первый пост + CALL TABLE
_Bill
Цитата(Algol @ Aug 1 2006, 16:05) *
В случае Си, так как посоветовал psL. В случае асма см. первый пост + CALL TABLE

Я имел в виду Си.
upc2
Откуда 60 байт?
Программа на Си

void main(void)
{
char in,out;
char conv[]={0xEB,0x60,0xE5};
in=1;
out=conv[in];

}


Вот , что сделал компилятор PICC PL8.05



1 0000 0183 CLRF 0x3
2 0001 3000 MOVLW 0
3 0002 008A MOVWF 0xa
4 0003 2804 GOTO 0x4
5 0004 0183 CLRF 0x3
6 0005 2BF4 GOTO 0x3f4
.........................


1013 03F4 30EB MOVLW 0xeb
1014 03F5 1283 BCF 0x3, 0x5
1015 03F6 008E MOVWF 0xe
1016 03F7 3060 MOVLW 0x60
1017 03F8 008F MOVWF 0xf
1018 03F9 30E5 MOVLW 0xe5
1019 03FA 0090 MOVWF 0x10
1020 03FB 018C CLRF 0xc
1021 03FC 0A8C INCF 0xc, F
1022 03FD 080F MOVF 0xf, W
1023 03FE 008D MOVWF 0xd
1024 03FF 2804 GOTO 0x4
Костян
Цитата(psL @ Jul 31 2006, 08:29) *
char conv[]={ 0xEB, 0x60, 0xA7, 0xE5 };

...

char in=1;
char out=conv[in];


Для таблиц экономичней так
const conv[]={ 0xEB, 0x60, 0xA7, 0xE5 };
...

char in=1;
char out=conv[in];

В итоге код в два раза меньше. В первом случае нужно сохранить значение и записать его в ОЗУ (две инструкции. Во втором случае только retlw (одна инструкция ).
upc2
С точки зрения экономичности совершенно одинаково,

void main(void)
{
char out;
const char conv[]={0xEB,0x60,0xE5};
char in=1;
out=conv[in];
}


2 0001 3000 MOVLW 0
3 0002 008A MOVWF 0xa
4 0003 2804 GOTO 0x4
5 0004 0183 CLRF 0x3
6 0005 2BF7 GOTO 0x3f7
7 0006 0782 ADDWF 0x2, F
8 0007 34EB RETLW 0xeb
9 0008 3460 RETLW 0x60
10 0009 34E5 RETLW 0xe5
....................................

1016 03F7 1283 BCF 0x3, 0x5
1017 03F8 018C CLRF 0xc
1018 03F9 0A8C INCF 0xc, F
1019 03FA 3000 MOVLW 0
1020 03FB 008A MOVWF 0xa
1021 03FC 3001 MOVLW 0x1
1022 03FD 2006 CALL 0x6
1023 03FE 008D MOVWF 0xd
1024 03FF 2804 GOTO 0x4

но согласен с быстродействием выполнения программы.
dialex
Цитата(upc2 @ Aug 4 2006, 10:01) *
Совершенно одинаково

void main(void)
{
char out;
const char conv[]={0xEB,0x60,0xE5};
char in=1;
out=conv[in];
}


2 0001 3000 MOVLW 0
3 0002 008A MOVWF 0xa
4 0003 2804 GOTO 0x4
5 0004 0183 CLRF 0x3
6 0005 2BF7 GOTO 0x3f7
7 0006 0782 ADDWF 0x2, F
8 0007 34EB RETLW 0xeb
9 0008 3460 RETLW 0x60
10 0009 34E5 RETLW 0xe5
....................................

1016 03F7 1283 BCF 0x3, 0x5
1017 03F8 018C CLRF 0xc
1018 03F9 0A8C INCF 0xc, F
1019 03FA 3000 MOVLW 0
1020 03FB 008A MOVWF 0xa
1021 03FC 3001 MOVLW 0x1
1022 03FD 2006 CALL 0x6
1023 03FE 008D MOVWF 0xd
1024 03FF 2804 GOTO 0x4

сделай так
const char conv[]={0xEB,0x60,0xE5};
char out;
void main(void)
{
char in=1;
out=conv[in];
}
upc2
Сделал.

3 0002 008A MOVWF 0xa
4 0003 2804 GOTO 0x4
5 0004 300C MOVLW 0xc
6 0005 0084 MOVWF 0x4
7 0006 300E MOVLW 0xe
8 0007 200D CALL 0xd
9 0008 0183 CLRF 0x3
10 0009 2BF7 GOTO 0x3f7
11 000A 0604 XORWF 0x4, W
12 000B 0180 CLRF 0
13 000C 0A84 INCF 0x4, F
14 000D 0604 XORWF 0x4, W
15 000E 1D03 BTFSS 0x3, 0x2
16 000F 280A GOTO 0xa
17 0010 3400 RETLW 0
18 0011 0782 ADDWF 0x2, F
19 0012 34EB RETLW 0xeb
20 0013 3460 RETLW 0x60
21 0014 34E5 RETLW 0xe5
.............................................
1016 03F7 1283 BCF 0x3, 0x5
1017 03F8 018D CLRF 0xd
1018 03F9 0A8D INCF 0xd, F
1019 03FA 3000 MOVLW 0
1020 03FB 008A MOVWF 0xa
1021 03FC 3001 MOVLW 0x1
1022 03FD 2011 CALL 0x11
1023 03FE 008C MOVWF 0xc
1024 03FF 2804 GOTO 0x4
Костян
В итоге с const мы видем наличие 'retlw0x60'. Без нее:MOVLW 0x60 MOVWF 0xf . Получаем экономию в два раза + не забиваем ОЗУ.

Лучше наблюдать на большом обьеме данных (около 100 единиц).

Например:
const conv[]={ 0xEB, 0x60, 0xA7, 0xE5,.......................................,'~' };
...
unsigned char in=0;
while (conv[in]!='~') {PORTB=conv[in];in++;}



сравниваем с (незабываем смотреть на ОЗУ):

char conv[]={ 0xEB, 0x60, 0xA7, 0xE5,.......................................,'~' };
...
unsigned char in=0;
while (conv[in]!='~') {PORTB=conv[in];in++;}
upc2
Цитата(Костян @ Aug 4 2006, 12:56) *
В итоге с const мы видем наличие 'retlw0x60'. Без нее:MOVLW 0x60 MOVWF 0xf . Получаем экономию в два раза + не забиваем ОЗУ.

Лучше наблюдать на большом обьеме данных (около 100 единиц).

Например:
const conv[]={ 0xEB, 0x60, 0xA7, 0xE5,.......................................,'~' };
...
unsigned char in=0;
while (conv[in]!='~') {PORTB=conv[in];in++;}



сравниваем с (незабываем смотреть на ОЗУ):

char conv[]={ 0xEB, 0x60, 0xA7, 0xE5,.......................................,'~' };
...
unsigned char in=0;
while (conv[in]!='~') {PORTB=conv[in];in++;}


Я согласен с вами.Код с const эффективней.Обращение к таблице будет быстрее.
Кроме того ,без const, для каждого элемента массива будет выделяться отдельная ячейка RAM.
giran
А подскажите, как разместить таблицу, например const unsigned char table[..] с какого-то заданного адреса в памяти программ (аналог ORG XYZ в MPASMе)? Пытаюсь в лоб

Код
const unsigned char table[..] @ 0xXYZ;

на что компилятор грязно ругается
Пытаюсь сделать таблицу перекодировки кодов букв русских символов в коды индикатора HD44780. Если для латиницы коды совпадают с ASCII, то с русскими там полный бардак.
Костян
Цитата(giran @ Aug 8 2006, 06:50) *
Пытаюсь сделать таблицу перекодировки кодов букв русских символов в коды индикатора HD44780. Если для латиницы коды совпадают с ASCII, то с русскими там полный бардак.

Попробуйте так ("Г"+x), где х-десятичное число, устраняющее разницу в ASCII коде.
А вот с ручным размещением таблиы нужно быть осторожным. Таблицы retlw размещаются в подпрограмме, причем при возврате с нее, можно вернутся только на адрес 0..255 (в стек загружается только младшие 8 бит счетчика команд).
giran
То есть что-то типа такого:
Код
const unsigned char table[64]={
0x41, //А
0xA0, //Б
0x42, //В
0xA1, //Г
0xE0, //Д
0x45, //Е
0xA2, //Ё
0xA3, //Ж......
0xC7  // я}


а обращаться
Код
  table['Г'-0xC0]

(C0- код "А" в ASCII а дальше они по порядку, кроме ёЁ). Тогда и абсолютной адресации вроде не надо. Попробую.
Костян
Цитата(giran @ Aug 8 2006, 08:24) *
То есть что-то типа такого:
Код
const unsigned char table[64]={
0x41, //А
0xA0, //Б
0x42, //В
0xA1, //Г
0xE0, //Д
0x45, //Е
0xA2, //Ё
0xA3, //Ж......
0xC7  // я}

Не нужно оперировать кодами букв, за Вас это сделает Mplab
const table[]={'П','р','и','в','е','т',' ','м','и','р','`'};
...............
unsigned char i=0;
While (table[i]!='`')
{
write(table[i]+x); //отправляем на индикатор букву и с помощью x добиваемся коректного отображеня на ЖКИ


i++;

}
giran
Цитата
Не нужно оперировать кодами букв

Вы немного не поняли, в table[] не текст сообщения (типа "Хело, волд"), а коды русских букв по "Таблице кодов символов контроллера Epson, набор "Russian"": http://www.gaw.ru/html.cgi/txt/lcd/chips/hd44780/start.htm
giran
Вообщем, вот окончательный вариант, если кому пригодится, правда без русских букв ёЁ, но это 2-мя отдельными if-ами. Вывожу на 16-знаковый ЖКИ hd44780r, проверил в железе, работает.
Код
const unsigned char rusTable[64]= {
0x41, 0xA0, 0x42, 0xA1, 0xE0, 0x45, 0xA3, 0xA4, 0xA5, 0xA6, 0x4B, 0xA7, 0x4D, 0x48, 0x4F, 0xA8,
0x50, 0x43, 0x54, 0xA9, 0xAA, 0x58, 0xE1, 0xAB, 0xAC, 0xE2, 0xAD, 0xAE, 0xAD, 0xAF, 0xB0, 0xB1,
0x61, 0xB2, 0xB3, 0xB4, 0xE3, 0x65, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0x6F, 0xBE,
0x70, 0x63, 0xBF, 0x79, 0xE4, 0x78, 0xE5, 0xC0, 0xC1, 0xE6, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7};

const unsigned  char Message[16]= {"Привет,мир World"};

main()         {
        unsigned char i,currentPOS;
        TRISB=0x00;    
        di();
//---------инициализация lcd-----------
    lcd=0;
    delay(1300);
    lcd=0x30;
    bitset (lcd, en); bitclr (lcd, en);// _/\_
    delay(7);    
    bitset (lcd, en); bitclr (lcd, en);// _/\_
    delay(230);
    wr_command_lcd(0x20);
    wr_command_lcd(0x28);    
    wr_command_lcd(0x0C);
    wr_command_lcd(0x06);
    wr_command_lcd(0x01);
    delay(230);
//----------Загрузка строки --------
wr_command_lcd(0x80);
    for    (i=0;i<8;i++) {
        currentPOS=    Message[i];
        if (currentPOS > 0x7F) currentPOS=rusTable[Message[i]-0xC0];
        wr_data_lcd(currentPOS);    }
wr_command_lcd(0xC0);
    for    (i=8;i<16;i++) {
        currentPOS=    Message[i];
        if (currentPOS > 0x7F) currentPOS=rusTable[Message[i]-0xC0];
        wr_data_lcd(currentPOS);    }
upc2
Цитата(giran @ Aug 9 2006, 08:39) *
Вообщем, вот окончательный вариант, если кому пригодится, правда без русских букв ёЁ, но это 2-мя отдельными if-ами. Вывожу на 16-знаковый ЖКИ hd44780r, проверил в железе, работает.
Код
const unsigned char rusTable[64]= {
0x41, 0xA0, 0x42, 0xA1, 0xE0, 0x45, 0xA3, 0xA4, 0xA5, 0xA6, 0x4B, 0xA7, 0x4D, 0x48, 0x4F, 0xA8,
0x50, 0x43, 0x54, 0xA9, 0xAA, 0x58, 0xE1, 0xAB, 0xAC, 0xE2, 0xAD, 0xAE, 0xAD, 0xAF, 0xB0, 0xB1,
0x61, 0xB2, 0xB3, 0xB4, 0xE3, 0x65, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0x6F, 0xBE,
0x70, 0x63, 0xBF, 0x79, 0xE4, 0x78, 0xE5, 0xC0, 0xC1, 0xE6, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7};

const unsigned  char Message[16]= {"Привет,мир World"};

main()         {
        unsigned char i,currentPOS;
        TRISB=0x00;    
        di();
//---------инициализация lcd-----------
    lcd=0;
    delay(1300);
    lcd=0x30;
    bitset (lcd, en); bitclr (lcd, en);// _/\_
    delay(7);    
    bitset (lcd, en); bitclr (lcd, en);// _/\_
    delay(230);
    wr_command_lcd(0x20);
    wr_command_lcd(0x28);    
    wr_command_lcd(0x0C);
    wr_command_lcd(0x06);
    wr_command_lcd(0x01);
    delay(230);
//----------Загрузка строки --------
wr_command_lcd(0x80);
    for    (i=0;i<8;i++) {
        currentPOS=    Message[i];
        if (currentPOS > 0x7F) currentPOS=rusTable[Message[i]-0xC0];
        wr_data_lcd(currentPOS);    }
wr_command_lcd(0xC0);
    for    (i=8;i<16;i++) {
        currentPOS=    Message[i];
        if (currentPOS > 0x7F) currentPOS=rusTable[Message[i]-0xC0];
        wr_data_lcd(currentPOS);    }


Да первая группа русских букв идет после 7F , но вычитать надо 80, а не С0.
Анализа второй группы после DF не вижу.
Поясните как вы с мелкими буквами выкрутились.
dialex
const unsigned char rus_codes[66]=
{
0x41,0xa0,0x42,0xa1,0xe0,0x45,0xa2,0xa3, // АБВГДЕЁЖ
0XA4,0XA5,0XA6,0X4B,0XA7,0X4D,0X48,0X4F, // ЗИЙКЛМНО
0XA8,0X50,0X43,0X54,0XA9,0XAA,0X58,0XE1,0XAB, // ПРСТУФХЦЧ
0XAC,0XE2,0XAD,0XAE,0X62,0XAF,0XB0,0XB1, // ШЩЪЫЬЭЮЯ
0X61,0XB2,0XB3,0XB4,0XE3,0X65,0XB5,0XB6, //абвгдеёж
0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0x6f, //зийклмно
0xbe,0x70,0x63,0xbf,0x79,0xe4,0x78,0xe5,0xc0, // прстуфхцч
0xc1,0xe6,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7
} ;


// кодировка win1251 -- буквы русские, вроде работает
if(c>=0xc0 || c==0xb8 || c==0xa8)
{
if(c=='Ё')
c=6;
else if(c=='ё')
c='е'-'А' + 2;
else if(c<='Е')
c=c-'А';
else if(c<='ж')
c=c-'А'+1;
else
c=c-'А'+2;
c=rus_codes[c];
}
upc2
dialex Спасибо я разобрался.Различие в таблицах кодов ASCII и win1251 .Все правильно.
Костян
Цитата(giran @ Aug 9 2006, 00:30) *
Вы немного не поняли, в table[] не текст сообщения (типа "Хело, волд"), а коды русских букв по "Таблице кодов символов контроллера Epson, набор "Russian"": http://www.gaw.ru/html.cgi/txt/lcd/chips/hd44780/start.htm

Хм.. действительно, аброкадабра. Я свои примеры приводил для смешенной ASCII таблицы (иногда смешена и латиница). Запутал в данном случае.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.