mraaf Ответов: 3

Как преобразовать double или string в unsigned char*


Здравствуйте Эксперты,
Я пытаюсь передать байты данных в кадр CAN (SDS). Данные представлены в виде двойника (4.00-20.00). Данные должны быть отправлены как unsigned char*. При приведенном ниже коде микроконтроллер считывает только первую цифру.

Ценю любую помощь.

Спасибо
мрааф

Что я уже пробовал:

CString strTT126;
double dTT126 = (m_nSliderTT126/8.4)-3.81;
strTT126.Format("%.02f", dTT126);
LPBYTE pByte = (LPBYTE)strTT126.GetBuffer(strTT126.GetLength());

SDSWriteFIFO(Ident, (unsigned char*)pByte); // pass mA value size of 1 byte in SDS frame

3 Ответов

Рейтинг:
5

mraaf

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

int CSoftingCANL2::SDSWriteFIFO(unsigned long Ident, double nDigit){

CString strAllDigits;
unsigned char pData[4] = {NULL};

strAllDigits.Format("%.2f", nDigit);
int nLength = 3;

for(int i = 0; i < strAllDigits.GetLength(); i++)
{
        pData[0] = 0x00; // EOID 0
	pData[1] = 0xCE; // Attribute 206 for transmit
	pData[2] = (unsigned char)strAllDigits.GetAt(i); // Get all ASCII character of the double
	int nfrc = CANL2_send_data(hcan1, Ident, 0, nLength, (unsigned char*)pData);
}
return nfrc;}


Рейтинг:
1

Jochen Arndt

Я предполагаю, что ваш проект настроен на Unicode.

Затем CString класс есть wchar_t основывающийся. Эти символы Unicode имеют ширину 16 бит, а символы ASCII (коды от 0x00 до 0x7f) имеют очищенный старший байт. Но ваш микроконтроллер, вероятно, ожидает символов ASCII, и очищенный старший байт рассматривается как индикатор конца строки.

Самым простым решением было бы использование CStringA класс. То A указывает, что это строка ANSI:

CStringA strTT126;
double dTT126 = (m_nSliderTT126/8.4)-3.81;
strTT126.Format("%.02f", dTT126);

SDSWriteFIFO(Ident, (const unsigned char*)strTT126.GetString());
Обратите внимание также, что я использовал GetString() функция-член для передачи строки. Это может быть использовано, когда SDSWriteFIFO() параметр имеет тип const unsigned char*.

Если параметр не const и это функция, написанная вами, попробуйте сделать этот параметр const. В противном случае вам придется использовать GetBuffer() вместо того, как уже используется. Но тогда не забудь позвонить ReleaseBuffer() впоследствии:
LPSTR buf = strTT126.GetBuffer(strTT126.GetLength());
SDSWriteFIFO(Ident, (unsigned char*)buf);
strTT126.ReleaseBuffer();


mraaf

Йохен,
Похоже, компилятор не поддерживал CStringA. Так что GetString () не работает. Я использую VC++ 6.0.
SDSWriteFIFO () написан мной, но параметр должен быть unsigned char* в соответствии с библиотекой.

LPSTR buf = strTT126.GetBuffer(0); / / это также передает первый байт строки
SDSWriteFIFO (Ident, (unsigned char*)buf);
strTT126.Метод releasebuffer();

Jochen Arndt

Вы должны попробовать использовать более свежий компилятор.

Но при использовании VC6 это не проблема Unicode.
Опубликованный код просто передает строковый указатель на функцию SDSWriteFIFO () (приведение от char* к unsigned char* не является проблемой). Если ваш микро получает только один символ, проблема, вероятно, находится в этой функции.

mraaf

И да, он ожидает ASCII-символов.

mraaf

Я использую CString:: GetAt (), чтобы получить каждый символ, не уверен, что это лучший способ, но микроконтроллер, кажется, получает все байты строки.

CString strAllDigits, strDigit1, strDigit2, strDigit3, strDigit4, strDigit5;
unsigned char pData[5];

стралдигитс.Формат ( "%. 2f", dTT126); // 4.00 - 20.00

// Получить 1-ю цифру
strDigit1.Формат ("%c", strAllDigits.GetAt(0));
unsigned char * pDigit1 = (unsigned char*)strDigit1.GetBuffer(0); / / 1-й символ
strDigit1.Метод releasebuffer();

// Получить 2-ю цифру
strDigit2.Формат ("%c", strAllDigits.Гетат(1));
unsigned char * pDigit2 = (unsigned char*)strDigit2.GetBuffer(0); / / 2-й символ
strDigit2.Метод releasebuffer();

// Получить 3-ю цифру
strDigit3.Формат ("%c", strAllDigits.Гетат(2));
unsigned char * pDigit3 = (unsigned char*)strDigit3.GetBuffer(0); / / 3-й символ
strDigit3.Метод releasebuffer();

// Получить 4-ю цифру
strDigit4.Формат ("%c", strAllDigits.Гетат(3));
unsigned char * pDigit4 = (unsigned char*)strDigit4.GetBuffer(0); / / 4-й символ
strDigit4.Метод releasebuffer();

// Получить 5-ю цифру
if (strlen(strAllDigits) > 4)
strDigit5.Формат ("%c", strAllDigits.Гетат(4));
unsigned char * pDigit5 = (unsigned char*)strDigit5.GetBuffer(0); / / 5-й символ
strDigit5.Метод releasebuffer();

pData[0] = * pDigit1; / / первый ASCII-символ данных
pData[1] = * pDigit2; / / второй ASCII-символ данных
pData[2] = * pDigit3; / / третий ASCII-символ данных
pData[3] = * pDigit4; / / четвертый ASCII-символ данных
pData[4] = * pDigit5; / / пятый ASCII-символ данных

SDSWriteFIFO (Ident, (unsigned char*)pData);

Jochen Arndt

???

При использовании
LPSTR buf = strTT126.GetBuffer();
buf уже является указателем на строку ASCII. Так что нет никакой необходимости копировать это в другой буфер. И даже если вы хотите скопировать строку, это можно сделать гораздо проще (при условии, что pData достаточно велик, чтобы вместить строку):
strcpy(pData, strTT126.GetString());

Обратите внимание также, что в приведенном выше коде pData не завершается NULL. Таким образом, SDSWriteFIFO () не может определить длину строки.

От вашего первого комментария к моему решению:
LPSTR buf = strTT126.GetBuffer(0);
Пройти ноль не получится. Это должна быть фактическая длина (я забыл об этом в своем решении).

Рейтинг:
1

W∴ Balboos, GHB

Возможно ли для вас использовать примитивы?

Вы можете создать союз:

union {
  *double number;
  *unsigned char letters;
};

Затем вы можете прочитать число в число и из него с помощью букв.


mraaf

Спасибо, попробуйте это сделать раньше, но он возвращает тот же результат. Он должен быть в самой функции SDSWriteFIFO ().