Как преобразовать два числа в wchar_t

realchel
Offline
Зарегистрирован: 05.02.2018

Всем добрый день.

Просьба не пинать. Янвых ответов не нашёл. Передаю с компа по com порту из внешнего приложения, русский текст, каждый символ кодируется в два байта. На стороне ардуинки считываю по каждому символу два числа. Как теперь число преобразовать, в символ wchar_t.

Может как то с указателями поиграться?

b707
Offline
Зарегистрирован: 26.05.2017

realchel пишет:

Всем добрый день.

Просьба не пинать. Янвых ответов не нашёл. Передаю с компа по com порту из внешнего приложения, русский текст, каждый символ кодируется в два байта. На стороне ардуинки считываю по каждому символу два числа. Как теперь число преобразовать, в символ wchar_t.

Может как то с указателями поиграться?

а как вы собираетесь использовать Wchar на ардуине? - от этого зависит, как (и стоит ли вообще) преобразовывать

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014
union 
{
    wchar_t rus,
    char[2] raw,
} foo;

//...
foo temp;
temp.raw[0]=0xD0;
temp.raw[1]=0x81;
Serial.println(temp.rus);
//...

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

realchel
Offline
Зарегистрирован: 05.02.2018

b707 пишет:

realchel пишет:

Всем добрый день.

Просьба не пинать. Янвых ответов не нашёл. Передаю с компа по com порту из внешнего приложения, русский текст, каждый символ кодируется в два байта. На стороне ардуинки считываю по каждому символу два числа. Как теперь число преобразовать, в символ wchar_t.

Может как то с указателями поиграться?

а как вы собираетесь использовать Wchar на ардуине? - от этого зависит, как (и стоит ли вообще) преобразовывать

 

Ну собственно использовать для вывода на LCD1602, нашел библиотеку(сделал из двух) и заставил ее работать с русскими буквами. В ней функция есть которая конвертит получаемые с  ком порта символы в wchar_t. И она работает если передавать с терминала ардуинки. Как только на я на с# нарисовал простое консольное приложение, которое использует класс Serial, для передачи текстовых строк в ком порт, начались свисто пляски. Во первых в описании класса явно указано что все символы старше 127 он передает как 63(знак вопроса) и рекомендуют конвертить в Юникод. Как законвертил, в ардуино начали приходить 2 байта. Вот как их теперь преобразовать.

Либо может подскажет как в с# передавать однобайтный символы. Пока писал подумал, что надо не строку отправлять, а именно байты в цикле, попробую вечером.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

realchel пишет:

 Во первых в описании класса явно указано что все символы старше 127 он передает как 63(знак вопроса) и рекомендуют конвертить в Юникод. 

Это вы где такое нарыли ? 

Вот процедура которая конвертит русский юникод во что то гругое :)

void txtConv(String *msg, char *in, uint8_t size){
   //String rusian = "Ёё0123456789 АБВГДЕЁЖЗИКЛМНОПРСТУФХСЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя";
   uint8_t j=0;
   uint8_t i=0;
   uint8_t *buff= (uint8_t*)in;
   while (i<size){
      uint8_t temp=(uint8_t)(*msg)[i];
      if (temp== 0xD0) {
         i++;
         temp=(uint8_t)(*msg)[i];
         if (temp<0x90) {
            if (temp==0x81) { //Ё
               buff[j++]=0xA1; 
            } else {
               //..
            }
         } else if (temp<0xC0) {  //А...Я,а...п
            buff[j++]=temp+0x20;   
         } else {
            //..
         }
      } else if (temp==0xD1) {
         i++;
         temp=(uint8_t)(*msg)[i];
         if (temp<0x80) {
            //.. 
         } else if (temp<0x90) { //р...я
            buff[j++]=temp+0x60; 
         } else {
            if (temp==0x91){ //ё
               buff[j++]=0xF1;  
            } else {
               //..  
            }
         }
      } else {
          buff[j++]=temp;  
      }
      i++;
   }
   buff[j]=0; //терминатор
}

Сляпана на скорую руку, суржик, память не бережет, полно прочей гадости, но как то работает. Для вывода на LCD нужно еще преобразовать эти символы в соответствии с таблицей кодировки LCD.... Как то так, наверное....

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Русский текст в какой кодировке-то? Если в UTF-8, то там wchat_t не обойдёсси, в UTF-8 до 6 символов на байт ;)

Если надо безопасную передачу UTF-8 - просто кодируйте в строковое HEX-представление все байты строки, передавайте эту строку в порт, а на стороне дуни расшифровывайте побайтово - класс String вполне себе нормально обращается с UTF-8. Т.е. на входе в порт у вас строка типа D0ED1850... - выкусываете попарно, преобразуете в чиселку, эту чиселку в виде char - скармливаете String, в псевдокоде вот так:

String input = "ABCDED1850";

String converted;
for(int i=0;i<input.length();i+=2)
{
  String substr = input.substring(i,i+2);
  char ch = FromHex(substr);
  converted += ch;
}

И усё - хоть таджикский передавай.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Ну естественно тут не полная перекодировка, пролетают только англицкие и русские символы.  0xD0 и 0xD1 соответствуют B11010000, что говорит нам о том, что символ закодирован двумя октетами. Исходил из того, что нужно передать русские сообщения набранные в коде написаном в ардуино ИДЕ. И что в потоке данных не может быть китайских, португальских и прочих букв, только англицкие и русские.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

DIYMan пишет:

И усё - хоть таджикский передавай.

Ну не знаю... Англицкий так передать может не получиться, они кодируются одним байтом. Иными словами

String "ABCГДФ" так нормально прочитать не получится :)

realchel
Offline
Зарегистрирован: 05.02.2018

brokly пишет:

realchel пишет:

 Во первых в описании класса явно указано что все символы старше 127 он передает как 63(знак вопроса) и рекомендуют конвертить в Юникод. 

Это вы где такое нарыли ? 

Вот процедура которая конвертит русский юникод во что то гругое :)

void txtConv(String *msg, char *in, uint8_t size){
   //String rusian = "Ёё0123456789 АБВГДЕЁЖЗИКЛМНОПРСТУФХСЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя";
   uint8_t j=0;
   uint8_t i=0;
   uint8_t *buff= (uint8_t*)in;
   while (i<size){
      uint8_t temp=(uint8_t)(*msg)[i];
      if (temp== 0xD0) {
         i++;
         temp=(uint8_t)(*msg)[i];
         if (temp<0x90) {
            if (temp==0x81) { //Ё
               buff[j++]=0xA1; 
            } else {
               //..
            }
         } else if (temp<0xC0) {  //А...Я,а...п
            buff[j++]=temp+0x20;   
         } else {
            //..
         }
      } else if (temp==0xD1) {
         i++;
         temp=(uint8_t)(*msg)[i];
         if (temp<0x80) {
            //.. 
         } else if (temp<0x90) { //р...я
            buff[j++]=temp+0x60; 
         } else {
            if (temp==0x91){ //ё
               buff[j++]=0xF1;  
            } else {
               //..  
            }
         }
      } else {
          buff[j++]=temp;  
      }
      i++;
   }
   buff[j]=0; //терминатор
}

Сляпана на скорую руку, суржик, память не бережет, полно прочей гадости, но как то работает. Для вывода на LCD нужно еще преобразовать эти символы в соответствии с таблицей кодировки LCD.... Как то так, наверное....

Воть

https://msdn.microsoft.com/ru-ru/library/y2sxhat8(v=vs.110).aspx

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

realchel пишет:

Воть

https://msdn.microsoft.com/ru-ru/library/y2sxhat8(v=vs.110).aspx

Забейте, ардуино хреначит все подряд. Если символ закодирован 8 байтами, то все 8 и улетят.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Поэтому если передать стринг с любым содержимым (в том числе не англицких букв), и принять этот поток в точно такой же стринг, то оба стринга окажуться одинаковыми. 

Кстати, нужно слазить в реализацию стринга и посмотреть как он считает количество символов :)

realchel
Offline
Зарегистрирован: 05.02.2018

brokly пишет:

Поэтому если передать стринг с любым содержимым (в том числе не англицких букв), и принять этот поток в точно такой же стринг, то оба стринга окажуться одинаковыми.

Я конечно ламер, но не настолько:)

Я и начал голову ломать когда у меня на LCD одни вопросы стали появляться. Сделал из экрана отладочный экран и начал смотреть что же с порта приходит. и там все что старше 127 приходит как 63

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Ага...

Вот код:

String test="ABCДЛГ";
Serial.println(test.length());
Serial.println(sizeof("ABCДЛГ"));
Serial.print('|');
Serial.print(test);
Serial.println('|');

Если его выполнить, то на экране терминала мы видим :

9
10
|ABCДЛГ|
 
Или в HEX:
 
39 0D 0A 31 30 0D 0A 7C 41 42 43 D0 94 D0 9B D0 93 7C 0D 0A 

Заметьте, ни одного вопросительного знака - это раз. 

И длинна строки ни разу не 6 или 12

ЗЫ Толькао сей час заметил, что ТС используем метод write .... ЗАЧЕМ !? 

И сразу... КАК ?

realchel, покажите код, как вы это делаете !?

realchel
Offline
Зарегистрирован: 05.02.2018

brokly пишет:

realchel, покажите код, как вы это делаете !?

Ничего не понял. Я никакой код не прилагал. В Вашем примере Вы работает внутри ардуино(если я правильно понял) Внутри ардуино все работает. Проблема с получением данных из внешнего приложения. Код С# приложения могу скинуть.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

А ясно, я не внимательно прочитал ваше первое сообщение. Делов то, передавайте не как текстовый массив, а как байтовый. Тогда не будет никаких вопросительных знаков. 

Но на главный вопрос темы я вам ответил, используйте юниты.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

realchel, у Вас проблемы на передающей стороне. Нужно либо заменить C# чем-то более адекватным, либо заставить C# передавать то, что нужно Вам, а не то, что хочется ему.

realchel
Offline
Зарегистрирован: 05.02.2018

brokly пишет:

Но на главный вопрос темы я вам ответил, используйте юниты.

Не совсем понял.

В общем в С# я байты передаю так

string my_str = args[1];
byte[] my_bytes = System.Text.Encoding.UTF8.GetBytes(my_str);
port.Write(my_bytes, 0, my_bytes.Length);

передаю одну букву русску "Д" (для теста)

в ардуино вывожу на экран что получаю

  while (Serial.available() > 0)
    {
      getfromCom=true;
      // display each character to the LCD
      str = Serial.read();
      //lcd.print(lcd.asciiutf8(str));//Вывод на экран LCD, в т.ч. по-русски. Перевод из ASCII в UTF-8.
      lcd.print(str);//Вывод на экран LCD, в т.ч. по-русски. Перевод из ASCII в UTF-8.
    }

у меня показывает 208148

как мне правильно использовать эту функции

//lcd.print(lcd.asciiutf8(str));//Вывод на экран LCD, в т.ч. по-русски. Перевод из ASCII в UTF-8.

сама функция вот 

wchar_t *LCD_1602_RUS::asciiutf8(unsigned char ascii)
{
	if (ascii == 168) *char_utf8 = 0x401; //код ASCII буквы Ё
	else if (ascii == 184) *char_utf8 = 0x451; //код ASCII буквы ё
	else if ((ascii >= 192) && (ascii <= 255)) //остальные буквы русского алфавита
	{
		*char_utf8 = ascii + 848;
	}
	else *char_utf8 = ascii;

	return char_utf8;
}

Может она мне не нужна. Я же уже получаю юникод. как правильно вызвать Lcd.print их несколько, возможно свою дописать?

void LCD_1602_RUS::print(const char *str){
	cursor_col += LiquidCrystal_I2C::print(str);
}
void LCD_1602_RUS::print(int val, int base){
  cursor_col += LiquidCrystal_I2C::print(val, base);
}
void LCD_1602_RUS::print(unsigned int val, int base){
  cursor_col += LiquidCrystal_I2C::print(val, base);
}
void LCD_1602_RUS::print(long val, int base){
  cursor_col += LiquidCrystal_I2C::print(val, base);
}
void LCD_1602_RUS::print(unsigned long val, int base){
  cursor_col += LiquidCrystal_I2C::print(val, base);
}
void LCD_1602_RUS::print(char val, int base){
  cursor_col += LiquidCrystal_I2C::print(val, base);
}
void LCD_1602_RUS::print(unsigned char val, int base){
  cursor_col += LiquidCrystal_I2C::print(val, base);
}
void LCD_1602_RUS::print(const String &str){
  cursor_col += LiquidCrystal_I2C::print(str);
}
void LCD_1602_RUS::print(double val, int base){
  cursor_col += LiquidCrystal_I2C::print(val, base);
}
void LCD_1602_RUS::print(const wchar_t *_str){

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Не получаете вы юникод. Вы получаете два байта (должны, во всяком случае). Читаете их по очереди и выводите как byte.

Делайте два Serial.read() в элементы массива raw union-а, который брукли показал в #2, после этого в элементе rus union-а у вас, теоретически, должен появиться нужный wchar. Его и суйте в LCD.

realchel
Offline
Зарегистрирован: 05.02.2018

sadman41 пишет:

Не получаете вы юникод. Вы получаете два байта (должны, во всяком случае). Читаете их по очереди и выводите как byte.

Делайте два Serial.read() в элементы массива raw union-а, который брукли показал в #2, после этого в элементе rus union-а у вас, теоретически, должен появиться нужный wchar. Его и суйте в LCD.

Попробвал, тестирую передаю Русскую Д, на экране показывает P

union RusSym
{
    wchar_t rus;
    char raw[2];
} ;


  RusSym rusSym;
    while (Serial.available() > 0)
    {
      getfromCom=true;
      // display each character to the LCD
      rusSym.raw[0] = Serial.read();
      rusSym.raw[1] = Serial.read();
            
      lcd.print(lcd.asciiutf8(rusSym.rus));//Вывод на экран LCD, в т.ч. по-русски. Перевод из ASCII в UTF-8.
      //lcd.print(rusSym.rus);//Вывод на экран LCD, в т.ч. по-русски. Перевод из ASCII в UTF-8.
    }

Куда еще капнуть?

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

realchel пишет:

Попробвал, тестирую передаю Русскую Д, на экране показывает P

...

Куда еще капнуть?

Давайте начнем с начала.

1. Уверены ли Вы, что Ваш дисплей вообще поддерживает кириллицу?

2. Знаете ли Вы, что сам по себе дисплей (если он поддерживает кириллицу) с юникодом работать не может? (впрочем, если не поддерживает - все равно работать не может)

3. На основании какой информации Вы решили, что разрабатываемый Вами способ может привести к появлению кириллицы на экране LCD?

sadman41
Offline
Зарегистрирован: 19.10.2016

А зачем вы из char еще раз делаете wchar через asciiutf8() ?  lcd.print(rusSym.rus) работает? Или может там надо байты местами махнуть... Что-то я с этой библиотекой как-то ковырялся, но забыл уж всё. Вроде как она по коду wchar-а грузит в дисплей пользовательский символ на лету. Но пользовательских символов немного, можно оконфузится.

realchel
Offline
Зарегистрирован: 05.02.2018

andriano пишет:

realchel пишет:

Попробвал, тестирую передаю Русскую Д, на экране показывает P

...

Куда еще капнуть?

Давайте начнем с начала.

1. Уверены ли Вы, что Ваш дисплей вообще поддерживает кириллицу?

2. Знаете ли Вы, что сам по себе дисплей (если он поддерживает кириллицу) с юникодом работать не может? (впрочем, если не поддерживает - все равно работать не может)

3. На основании какой информации Вы решили, что разрабатываемый Вами способ может привести к появлению кириллицы на экране LCD?

 

1. не поддерживает.

2. знаю

3. Я взял библиотеку и она работает если в коде указывать строки по русски и если передавать через встренный в IDE терминал. Мне же надо получить текстовую строку из вне. Поэтому начал разбираться

realchel
Offline
Зарегистрирован: 05.02.2018

sadman41 пишет:

А зачем вы из char еще раз делаете wchar через asciiutf8() ?  lcd.print(rusSym.rus) работает? Или может там надо байты местами махнуть... Что-то я с этой библиотекой как-то ковырялся, но забыл уж всё. Вроде как она по коду wchar-а грузит в дисплей пользовательский символ на лету. Но пользовательских символов немного, можно оконфузится.

нашел модификацию класса в которая работает с LCD не поддерживающим керилицу и эта функция конвертит

sadman41
Offline
Зарегистрирован: 19.10.2016

realchel пишет:

нашел модификацию класса в которая работает с LCD не поддерживающим керилицу и эта функция конвертит

Ну. Посмотрите, что она делает: берет один байт и делает из него два (wchar), чтобы можно было скормить его обычному print(wchar_t). А у вас уже сформирован wchar в юнионе. Зачем еще раз из первого байта wchar-а делать wchar?

Вобщем, вам нужно убедиться, что при посылке "Б" в unione (rusSym.rus) образуется 1041. Тогда всё должно фурычить.

realchel
Offline
Зарегистрирован: 05.02.2018

sadman41 пишет:

realchel пишет:

нашел модификацию класса в которая работает с LCD не поддерживающим керилицу и эта функция конвертит

Ну. Посмотрите, что она делает: берет один байт и делает из него два (wchar), чтобы можно было скормить его обычному print(wchar_t). А у вас уже сформирован wchar в юнионе. Зачем еще раз из первого байта wchar-а делать wchar?

Вобщем, вам нужно убедиться, что при посылке "Б" в unione (rusSym.rus) образуется 1041. Тогда всё должно фурычить.

Я конечно же пробовал прсто print

выводит "-27440"

подчеркну использую не стандартную библиотеку "LiquidCrystal_I2C" а прозводному от нее класс. который позволяет на китайском экране выводить русские буквы. И если указывать русский текст прям в скетче то все работает. вот пример скетча

#include <LCD_1602_RUS.h>
LCD_1602_RUS lcd(0x3F, 16, 2);

void setup()
{
	lcd.begin();
	lcd.backlight();
}

void loop()
{
  lcd.setCursor(0, 0);
  lcd.print(L"Привет.Мир.");

  
delay(200);
}

А вот для вывода полученные с компорта строки, была найдена еще одна с функцией asciiutf8. И она начинает работать но если использовать терминал встроенный в IDE, а если передавать из внешнего приложение, нифига.

sadman41
Offline
Зарегистрирован: 19.10.2016

А с приведением типа - print((wchar_t) rusSym.rus) ?

У принта клинит иногда, как я замечал. Си, собака, нечестный.

P.S. Надо заставить этот чертов компилятор применить void LCD_1602_RUS::print(const wchar_t *_str)

realchel
Offline
Зарегистрирован: 05.02.2018

sadman41 пишет:

А с приведением типа - print((wchar_t) rusSym.rus) ?

У принта клинит иногда, как я замечал. Си, собака, нечестный.

P.S. Надо заставить этот чертов компилятор применить void LCD_1602_RUS::print(const wchar_t *_str)

а как конвертнуть в const wchar_t *_str

sadman41
Offline
Зарегистрирован: 19.10.2016

Подозреваю, что как (wchar_t*) &rusSym.rus

Вобщем, тут суть какая: LCD рисовать не умеет русские символы. Ему подсовываются латинские, похожие на русские буквы. А если нет подходящих, то загружаются пользовательские и рисуются картинкой. Что послать на дисплей - определяется кодом, который лежит в этом двухбайтном wchart_t.

Т.е. нужно сделать так, чтобы с сишарпа в ардуину полетело двухбайтовое 1041, если хотите напечатать "Б". Далее через юнион его собираете и принту скармливаете как wchar. А далее должно сработать то, что написано выше.

realchel
Offline
Зарегистрирован: 05.02.2018

Зайду с другой стороны. 

Используя  lcd.print(str);

Передавая с монитора в IDE, например для буквы Д, LCD выводит число 196, код Д в кодировке Кодовая таблица 1251 – MS Windows. И если использовать на это число lcd.print(lcd.asciiutf8(str)) то будет выведена буква Д. Дак вот как мне те два символа что приходят из вне преобразовать в 1 символ? Приходит у меня если передавать букву Д 208 и 148

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

realchel пишет:

Зайду с другой стороны. 

Используя  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}; (через указатель на него)

 

realchel
Offline
Зарегистрирован: 05.02.2018

andriano пишет:

 

1. utf8, который, судя по всему Вам нужен, это ни разу не wchar_t.

2. Попытайтесь вывести массив char str[] = {208,148,0}; (через указатель на него)

 

Не не работает, какие то кракозябры. Ладно забью массив и тупо буду менять два символа на один

ven-til
Offline
Зарегистрирован: 13.02.2018

realchel пишет:

Зайду с другой стороны. 

Используя  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).

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

realchel пишет:

andriano пишет:

2. Попытайтесь вывести массив char str[] = {208,148,0}; (через указатель на него)

Не не работает, какие то кракозябры.

Интересно...

А что именно находится в str, когда lcd.print(lcd.asciiutf8(str)) выдает на экран букву Д? И что возвращает lcd.asciiutf8(str)? Надо как-то локализовывать проблему.

sadman41
Offline
Зарегистрирован: 19.10.2016

В #16 видно, что делает функция - подменяет код символа и делает его двубайтным.

realchel
Offline
Зарегистрирован: 05.02.2018

ven-til пишет:

 

 

В 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).

Во сне я тоже к этому решение пришёл(попробую только вечером). Честно говоря не думал что такой гемор конвертить. на С++ не пишу. Хотя и на Шарпе не проще:)

realchel
Offline
Зарегистрирован: 05.02.2018

andriano пишет:

Интересно...

А что именно находится в str, когда lcd.print(lcd.asciiutf8(str)) выдает на экран букву Д? И что возвращает lcd.asciiutf8(str)? Надо как-то локализовывать проблему.

[/quote]

в str находится два байт 208 и 148.

lcd.asciiutf8(str) из cp-1251 переводит в unicode прибавляя 848(Ё и ё возвращаются константно). Т.е. по сути мне  надо конвертнуть из utf-8 в unicode если я правильно читаю таблицу

wchar_t *LCD_1602_RUS::asciiutf8(unsigned char ascii)
{
	if (ascii == 168) *char_utf8 = 0x401; //код ASCII буквы Ё
	else if (ascii == 184) *char_utf8 = 0x451; //код ASCII буквы ё
	else if ((ascii >= 192) && (ascii <= 255)) //остальные буквы русского алфавита
	{
		*char_utf8 = ascii + 848;
	}
	else *char_utf8 = ascii;

	return char_utf8;
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

realchel пишет:

в str находится два байт 208 и 148.

lcd.asciiutf8(str) из cp-1251 переводит в unicode прибавляя 848(Ё и ё возвращаются константно). Т.е. по сути мне  надо конвертнуть из utf-8 в unicode если я правильно читаю таблицу

Или засылать с сишарпа байты в cp-1251, а на стороне ардуины совать их в lcd.asciiutf8(), которая на самом деле, как выходит, выдает юникод.

 

realchel
Offline
Зарегистрирован: 05.02.2018

Если честно чуствую себя идиотом:) Но точно помню что пробовал такой вариант. Как говорится коллективный разум помог.

В Шарпе сразу получаю в кодировке 1251 и передаю байты, все заработало. Всем спасибо. Кому интересно обращайтесь . Вот код на шарпе, консолька с двумя входными параметрами, порт и текст.

using System;
using System.IO.Ports;

namespace WorkWithSerialPort
{
    class Program
    {
        static int Main(string[] args)
        {
            int errNumber = 0;
            if (args.Length < 2)
            {
                Console.WriteLine("Должно быть указано минимум два параметра.");
                Console.WriteLine("Нажмите любую кнопку!");
                Console.ReadKey();
            }
            else
            {
                try
                {
                    SerialPort port = new SerialPort(args[0], args.Length > 2 ? Convert.ToInt16(args[1]) : 9600, Parity.None, 8, StopBits.One);
                    port.Open();
                    string my_str = args[1];
                    byte[] my_bytes = System.Text.Encoding.GetEncoding(1251).GetBytes(my_str);
                    port.Write(my_bytes, 0, my_bytes.Length);

                    port.Close();
                }
                catch (Exception e)
                {
                    if (e.Source != null)
                        Console.WriteLine("Возникла ошибка: {0}", e.ToString());
                    errNumber= - 1;
                }
            }
            return errNumber;
        }
    }
}