Официальный сайт компании Arduino по адресу arduino.cc
Как преобразовать два числа в wchar_t
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Ср, 28/02/2018 - 15:54
Всем добрый день.
Просьба не пинать. Янвых ответов не нашёл. Передаю с компа по com порту из внешнего приложения, русский текст, каждый символ кодируется в два байта. На стороне ардуинки считываю по каждому символу два числа. Как теперь число преобразовать, в символ wchar_t.
Может как то с указателями поиграться?
Всем добрый день.
Просьба не пинать. Янвых ответов не нашёл. Передаю с компа по com порту из внешнего приложения, русский текст, каждый символ кодируется в два байта. На стороне ардуинки считываю по каждому символу два числа. Как теперь число преобразовать, в символ wchar_t.
Может как то с указателями поиграться?
а как вы собираетесь использовать Wchar на ардуине? - от этого зависит, как (и стоит ли вообще) преобразовывать
Хотя я тоже не понимаю зачем. Если вы передаете массив с содержанием русских буковок, так примите его как есть в переменную такого же типа и все.
Всем добрый день.
Просьба не пинать. Янвых ответов не нашёл. Передаю с компа по com порту из внешнего приложения, русский текст, каждый символ кодируется в два байта. На стороне ардуинки считываю по каждому символу два числа. Как теперь число преобразовать, в символ wchar_t.
Может как то с указателями поиграться?
а как вы собираетесь использовать Wchar на ардуине? - от этого зависит, как (и стоит ли вообще) преобразовывать
Ну собственно использовать для вывода на LCD1602, нашел библиотеку(сделал из двух) и заставил ее работать с русскими буквами. В ней функция есть которая конвертит получаемые с ком порта символы в wchar_t. И она работает если передавать с терминала ардуинки. Как только на я на с# нарисовал простое консольное приложение, которое использует класс Serial, для передачи текстовых строк в ком порт, начались свисто пляски. Во первых в описании класса явно указано что все символы старше 127 он передает как 63(знак вопроса) и рекомендуют конвертить в Юникод. Как законвертил, в ардуино начали приходить 2 байта. Вот как их теперь преобразовать.
Либо может подскажет как в с# передавать однобайтный символы. Пока писал подумал, что надо не строку отправлять, а именно байты в цикле, попробую вечером.
Во первых в описании класса явно указано что все символы старше 127 он передает как 63(знак вопроса) и рекомендуют конвертить в Юникод.
Это вы где такое нарыли ?
Вот процедура которая конвертит русский юникод во что то гругое :)
Сляпана на скорую руку, суржик, память не бережет, полно прочей гадости, но как то работает. Для вывода на LCD нужно еще преобразовать эти символы в соответствии с таблицей кодировки LCD.... Как то так, наверное....
Русский текст в какой кодировке-то? Если в UTF-8, то там wchat_t не обойдёсси, в UTF-8 до 6 символов на байт ;)
Если надо безопасную передачу UTF-8 - просто кодируйте в строковое HEX-представление все байты строки, передавайте эту строку в порт, а на стороне дуни расшифровывайте побайтово - класс String вполне себе нормально обращается с UTF-8. Т.е. на входе в порт у вас строка типа D0ED1850... - выкусываете попарно, преобразуете в чиселку, эту чиселку в виде char - скармливаете String, в псевдокоде вот так:
И усё - хоть таджикский передавай.
Ну естественно тут не полная перекодировка, пролетают только англицкие и русские символы. 0xD0 и 0xD1 соответствуют B11010000, что говорит нам о том, что символ закодирован двумя октетами. Исходил из того, что нужно передать русские сообщения набранные в коде написаном в ардуино ИДЕ. И что в потоке данных не может быть китайских, португальских и прочих букв, только англицкие и русские.
И усё - хоть таджикский передавай.
Ну не знаю... Англицкий так передать может не получиться, они кодируются одним байтом. Иными словами
String "ABCГДФ" так нормально прочитать не получится :)
Во первых в описании класса явно указано что все символы старше 127 он передает как 63(знак вопроса) и рекомендуют конвертить в Юникод.
Это вы где такое нарыли ?
Вот процедура которая конвертит русский юникод во что то гругое :)
Сляпана на скорую руку, суржик, память не бережет, полно прочей гадости, но как то работает. Для вывода на LCD нужно еще преобразовать эти символы в соответствии с таблицей кодировки LCD.... Как то так, наверное....
Воть
https://msdn.microsoft.com/ru-ru/library/y2sxhat8(v=vs.110).aspx
Воть
https://msdn.microsoft.com/ru-ru/library/y2sxhat8(v=vs.110).aspx
Забейте, ардуино хреначит все подряд. Если символ закодирован 8 байтами, то все 8 и улетят.
Поэтому если передать стринг с любым содержимым (в том числе не англицких букв), и принять этот поток в точно такой же стринг, то оба стринга окажуться одинаковыми.
Кстати, нужно слазить в реализацию стринга и посмотреть как он считает количество символов :)
Поэтому если передать стринг с любым содержимым (в том числе не англицких букв), и принять этот поток в точно такой же стринг, то оба стринга окажуться одинаковыми.
Я конечно ламер, но не настолько:)
Я и начал голову ломать когда у меня на LCD одни вопросы стали появляться. Сделал из экрана отладочный экран и начал смотреть что же с порта приходит. и там все что старше 127 приходит как 63
Ага...
Вот код:
Если его выполнить, то на экране терминала мы видим :
Заметьте, ни одного вопросительного знака - это раз.
И длинна строки ни разу не 6 или 12
ЗЫ Толькао сей час заметил, что ТС используем метод write .... ЗАЧЕМ !?
И сразу... КАК ?
realchel, покажите код, как вы это делаете !?
realchel, покажите код, как вы это делаете !?
Ничего не понял. Я никакой код не прилагал. В Вашем примере Вы работает внутри ардуино(если я правильно понял) Внутри ардуино все работает. Проблема с получением данных из внешнего приложения. Код С# приложения могу скинуть.
А ясно, я не внимательно прочитал ваше первое сообщение. Делов то, передавайте не как текстовый массив, а как байтовый. Тогда не будет никаких вопросительных знаков.
Но на главный вопрос темы я вам ответил, используйте юниты.
realchel, у Вас проблемы на передающей стороне. Нужно либо заменить C# чем-то более адекватным, либо заставить C# передавать то, что нужно Вам, а не то, что хочется ему.
Но на главный вопрос темы я вам ответил, используйте юниты.
Не совсем понял.
В общем в С# я байты передаю так
передаю одну букву русску "Д" (для теста)
в ардуино вывожу на экран что получаю
у меня показывает 208148
как мне правильно использовать эту функции
сама функция вот
Может она мне не нужна. Я же уже получаю юникод. как правильно вызвать Lcd.print их несколько, возможно свою дописать?
Не получаете вы юникод. Вы получаете два байта (должны, во всяком случае). Читаете их по очереди и выводите как byte.
Делайте два Serial.read() в элементы массива raw union-а, который брукли показал в #2, после этого в элементе rus union-а у вас, теоретически, должен появиться нужный wchar. Его и суйте в LCD.
Не получаете вы юникод. Вы получаете два байта (должны, во всяком случае). Читаете их по очереди и выводите как byte.
Делайте два Serial.read() в элементы массива raw union-а, который брукли показал в #2, после этого в элементе rus union-а у вас, теоретически, должен появиться нужный wchar. Его и суйте в LCD.
Попробвал, тестирую передаю Русскую Д, на экране показывает P
Куда еще капнуть?
Попробвал, тестирую передаю Русскую Д, на экране показывает P
...
Куда еще капнуть?
Давайте начнем с начала.
1. Уверены ли Вы, что Ваш дисплей вообще поддерживает кириллицу?
2. Знаете ли Вы, что сам по себе дисплей (если он поддерживает кириллицу) с юникодом работать не может? (впрочем, если не поддерживает - все равно работать не может)
3. На основании какой информации Вы решили, что разрабатываемый Вами способ может привести к появлению кириллицы на экране LCD?
А зачем вы из char еще раз делаете wchar через asciiutf8() ? lcd.print(rusSym.rus) работает? Или может там надо байты местами махнуть... Что-то я с этой библиотекой как-то ковырялся, но забыл уж всё. Вроде как она по коду wchar-а грузит в дисплей пользовательский символ на лету. Но пользовательских символов немного, можно оконфузится.
Попробвал, тестирую передаю Русскую Д, на экране показывает P
...
Куда еще капнуть?
Давайте начнем с начала.
1. Уверены ли Вы, что Ваш дисплей вообще поддерживает кириллицу?
2. Знаете ли Вы, что сам по себе дисплей (если он поддерживает кириллицу) с юникодом работать не может? (впрочем, если не поддерживает - все равно работать не может)
3. На основании какой информации Вы решили, что разрабатываемый Вами способ может привести к появлению кириллицы на экране LCD?
1. не поддерживает.
2. знаю
3. Я взял библиотеку и она работает если в коде указывать строки по русски и если передавать через встренный в IDE терминал. Мне же надо получить текстовую строку из вне. Поэтому начал разбираться
А зачем вы из char еще раз делаете wchar через asciiutf8() ? lcd.print(rusSym.rus) работает? Или может там надо байты местами махнуть... Что-то я с этой библиотекой как-то ковырялся, но забыл уж всё. Вроде как она по коду wchar-а грузит в дисплей пользовательский символ на лету. Но пользовательских символов немного, можно оконфузится.
нашел модификацию класса в которая работает с LCD не поддерживающим керилицу и эта функция конвертит
Ну. Посмотрите, что она делает: берет один байт и делает из него два (wchar), чтобы можно было скормить его обычному print(wchar_t). А у вас уже сформирован wchar в юнионе. Зачем еще раз из первого байта wchar-а делать wchar?
Вобщем, вам нужно убедиться, что при посылке "Б" в unione (rusSym.rus) образуется 1041. Тогда всё должно фурычить.
нашел модификацию класса в которая работает с LCD не поддерживающим керилицу и эта функция конвертит
Ну. Посмотрите, что она делает: берет один байт и делает из него два (wchar), чтобы можно было скормить его обычному print(wchar_t). А у вас уже сформирован wchar в юнионе. Зачем еще раз из первого байта wchar-а делать wchar?
Вобщем, вам нужно убедиться, что при посылке "Б" в unione (rusSym.rus) образуется 1041. Тогда всё должно фурычить.
Я конечно же пробовал прсто print
выводит "-27440"
подчеркну использую не стандартную библиотеку "LiquidCrystal_I2C" а прозводному от нее класс. который позволяет на китайском экране выводить русские буквы. И если указывать русский текст прям в скетче то все работает. вот пример скетча
А вот для вывода полученные с компорта строки, была найдена еще одна с функцией asciiutf8. И она начинает работать но если использовать терминал встроенный в IDE, а если передавать из внешнего приложение, нифига.
А с приведением типа - print((wchar_t) rusSym.rus) ?
У принта клинит иногда, как я замечал. Си, собака, нечестный.
P.S. Надо заставить этот чертов компилятор применить void LCD_1602_RUS::print(const wchar_t *_str)
А с приведением типа - print((wchar_t) rusSym.rus) ?
У принта клинит иногда, как я замечал. Си, собака, нечестный.
P.S. Надо заставить этот чертов компилятор применить void LCD_1602_RUS::print(const wchar_t *_str)
а как конвертнуть в const wchar_t *_str
Подозреваю, что как (wchar_t*) &rusSym.rus
Вобщем, тут суть какая: LCD рисовать не умеет русские символы. Ему подсовываются латинские, похожие на русские буквы. А если нет подходящих, то загружаются пользовательские и рисуются картинкой. Что послать на дисплей - определяется кодом, который лежит в этом двухбайтном wchart_t.
Т.е. нужно сделать так, чтобы с сишарпа в ардуину полетело двухбайтовое 1041, если хотите напечатать "Б". Далее через юнион его собираете и принту скармливаете как wchar. А далее должно сработать то, что написано выше.
Зайду с другой стороны.
Используя lcd.print(str);
Передавая с монитора в IDE, например для буквы Д, LCD выводит число 196, код Д в кодировке Кодовая таблица 1251 – MS Windows. И если использовать на это число lcd.print(lcd.asciiutf8(str)) то будет выведена буква Д. Дак вот как мне те два символа что приходят из вне преобразовать в 1 символ? Приходит у меня если передавать букву Д 208 и 148
Зайду с другой стороны.
Используя lcd.print(str);
Передавая с монитора в IDE, например для буквы Д, LCD выводит число 196, код Д в кодировке Кодовая таблица 1251 – MS Windows. И если использовать на это число lcd.print(lcd.asciiutf8(str)) то будет выведена буква Д. Дак вот как мне те два символа что приходят из вне преобразовать в 1 символ? Приходит у меня если передавать букву Д 208 и 148
1. utf8, который, судя по всему Вам нужен, это ни разу не wchar_t.
2. Попытайтесь вывести массив char str[] = {208,148,0}; (через указатель на него)
1. utf8, который, судя по всему Вам нужен, это ни разу не wchar_t.
2. Попытайтесь вывести массив char str[] = {208,148,0}; (через указатель на него)
Не не работает, какие то кракозябры. Ладно забью массив и тупо буду менять два символа на один
Зайду с другой стороны.
Используя lcd.print(str);
Передавая с монитора в IDE, например для буквы Д, LCD выводит число 196, код Д в кодировке Кодовая таблица 1251 – MS Windows. И если использовать на это число lcd.print(lcd.asciiutf8(str)) то будет выведена буква Д. Дак вот как мне те два символа что приходят из вне преобразовать в 1 символ? Приходит у меня если передавать букву Д 208 и 148
В utf8 для русских букв первый байт 0xD0(208) или 0xD1(209) - следовательно если первый байт был 0xD0/0xD1, то для вывода на экран используем только второй байт, но преобразуем его в windows-1251. В данном случае если первым был 0xD0, то ко второму просто прибавляем 0x30(48), а если был 0xD1, то прибавляем 0x70(112). Что касается букв Ё и ё - если после 0xD0 пришел байт 0x81(129), то его заменяем на 0xA8(168), а если после 0xD1 пришел байт 0x91(145), то заменям на 0xB8(184).
2. Попытайтесь вывести массив char str[] = {208,148,0}; (через указатель на него)
Не не работает, какие то кракозябры.
Интересно...
А что именно находится в str, когда lcd.print(lcd.asciiutf8(str)) выдает на экран букву Д? И что возвращает lcd.asciiutf8(str)? Надо как-то локализовывать проблему.
В #16 видно, что делает функция - подменяет код символа и делает его двубайтным.
В utf8 для русских букв первый байт 0xD0(208) или 0xD1(209) - следовательно если первый байт был 0xD0/0xD1, то для вывода на экран используем только второй байт, но преобразуем его в windows-1251. В данном случае если первым был 0xD0, то ко второму просто прибавляем 0x30(48), а если был 0xD1, то прибавляем 0x70(112). Что касается букв Ё и ё - если после 0xD0 пришел байт 0x81(129), то его заменяем на 0xA8(168), а если после 0xD1 пришел байт 0x91(145), то заменям на 0xB8(184).
Во сне я тоже к этому решение пришёл(попробую только вечером). Честно говоря не думал что такой гемор конвертить. на С++ не пишу. Хотя и на Шарпе не проще:)
Интересно...
А что именно находится в str, когда lcd.print(lcd.asciiutf8(str)) выдает на экран букву Д? И что возвращает lcd.asciiutf8(str)? Надо как-то локализовывать проблему.
[/quote]
в str находится два байт 208 и 148.
lcd.asciiutf8(str) из cp-1251 переводит в unicode прибавляя 848(Ё и ё возвращаются константно). Т.е. по сути мне надо конвертнуть из utf-8 в unicode если я правильно читаю таблицу
в str находится два байт 208 и 148.
lcd.asciiutf8(str) из cp-1251 переводит в unicode прибавляя 848(Ё и ё возвращаются константно). Т.е. по сути мне надо конвертнуть из utf-8 в unicode если я правильно читаю таблицу
Или засылать с сишарпа байты в cp-1251, а на стороне ардуины совать их в lcd.asciiutf8(), которая на самом деле, как выходит, выдает юникод.
Если честно чуствую себя идиотом:) Но точно помню что пробовал такой вариант. Как говорится коллективный разум помог.
В Шарпе сразу получаю в кодировке 1251 и передаю байты, все заработало. Всем спасибо. Кому интересно обращайтесь . Вот код на шарпе, консолька с двумя входными параметрами, порт и текст.