Click here to Skip to main content
15,887,776 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello Experts,
I am trying to pass bytes of data in to CAN (SDS) frame. The data is in form of double (4.00 - 20.00). The data has to be sent as unsigned char*. With below code, only the first digit is read by the microcontroller.

Appreciate any helps.

Thank you
mraaf

What I have tried:

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
Posted
Updated 17-May-17 21:13pm

I guess that your project is set to Unicode.

Then the CString class is wchar_t based. These Unicode chars are 16 bit wide and ASCII characters (codes 0x00 to 0x7f) have the high byte cleared. But your micro controller probably expects ASCII characters and the cleared high byte is treated as the end of string indicator.

The simplest solution would be using the CStringA class. The A indicates that it is an ANSI string:
CStringA strTT126;
double dTT126 = (m_nSliderTT126/8.4)-3.81;
strTT126.Format("%.02f", dTT126);

SDSWriteFIFO(Ident, (const unsigned char*)strTT126.GetString());
Note also that I have used the GetString() member function to pass the string. This can be used when the SDSWriteFIFO() parameter is of type const unsigned char*.

If the parameter is not const and that is a function written by you, try to make that parameter const. Otherwise you have to use GetBuffer() instead as already used. But then don't forget to call ReleaseBuffer() afterwards:
LPSTR buf = strTT126.GetBuffer(strTT126.GetLength());
SDSWriteFIFO(Ident, (unsigned char*)buf);
strTT126.ReleaseBuffer();
 
Share this answer
 
v2
Comments
mraaf 15-May-17 6:04am    
Jochen,
Seems the compiler didn't support CStringA. So GetString() doesn't work. I am using VC++ 6.0.
SDSWriteFIFO() is written by me but the parameter has to be unsigned char* as per library.

LPSTR buf = strTT126.GetBuffer(0); // this also pass first byte of the string
SDSWriteFIFO(Ident, (unsigned char*)buf);
strTT126.ReleaseBuffer();
Jochen Arndt 15-May-17 6:44am    
You should try to use a more recent compiler.

But when using VC6 it is not a Unicode problem.
The posted code just passes a string pointer to the SDSWriteFIFO() function (casting from char* to unsigned char* is not the problem). If your micro receives only a single character, the problem is probably located in that function.
mraaf 15-May-17 6:11am    
And yes, it expects ASCII characters.
mraaf 16-May-17 3:14am    
I'm using CString::GetAt() to get each character, not sure this is best way but the microcontroller seems to receive all bytes of the string.

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

strAllDigits.Format("%.2f", dTT126); // 4.00 - 20.00

// Get 1st digit
strDigit1.Format("%c", strAllDigits.GetAt(0));
unsigned char* pDigit1 = (unsigned char*)strDigit1.GetBuffer(0); // 1st char
strDigit1.ReleaseBuffer();

// Get 2nd digit
strDigit2.Format("%c", strAllDigits.GetAt(1));
unsigned char* pDigit2 = (unsigned char*)strDigit2.GetBuffer(0); // 2nd char
strDigit2.ReleaseBuffer();

// Get 3rd digit
strDigit3.Format("%c", strAllDigits.GetAt(2));
unsigned char* pDigit3 = (unsigned char*)strDigit3.GetBuffer(0); // 3rd char
strDigit3.ReleaseBuffer();

// Get 4th digit
strDigit4.Format("%c", strAllDigits.GetAt(3));
unsigned char* pDigit4 = (unsigned char*)strDigit4.GetBuffer(0); // 4th char
strDigit4.ReleaseBuffer();

// Get 5th digit
if(strlen(strAllDigits) > 4)
strDigit5.Format("%c", strAllDigits.GetAt(4));
unsigned char* pDigit5 = (unsigned char*)strDigit5.GetBuffer(0); // 5th char
strDigit5.ReleaseBuffer();

pData[0] = *pDigit1; // First ASCII character of data
pData[1] = *pDigit2; // Second ASCII character of data
pData[2] = *pDigit3; // Third ASCII character of data
pData[3] = *pDigit4; // Forth ASCII character of data
pData[4] = *pDigit5; // Fifth ASCII character of data

SDSWriteFIFO(Ident, (unsigned char*)pData);
Jochen Arndt 16-May-17 3:37am    
???

When using
LPSTR buf = strTT126.GetBuffer();
buf is already a pointer to an ASCII string. So there is no need to copy that to another buffer. And even if you want to copy the string it can be done much simpler (provided that pData is large enough to hold the string):
strcpy(pData, strTT126.GetString());

Note also that in your above code pData is not NULL terminated. So SDSWriteFIFO() can not determine the string length.

From your first comment to my solution:
LPSTR buf = strTT126.GetBuffer(0);
Passing zero will not work. It must be the actual length (I forget that in my solution).
Is it possible for you to use primitives?

You can create a union:
C++
union {
  *double number;
  *unsigned char letters;
};

You can then read the number in to number and out via letters.
 
Share this answer
 
v2
Comments
mraaf 15-May-17 23:23pm    
Thanks, try it before but it returns same result. It must be in SDSWriteFIFO() function itself.
So I end up with this solution for crafting double in to the SDS frame. The data is limited to 1 byte per frame. The output is verified true with physical measurement.

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;}
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900