這是某個控制卡的通訊協議
協議格式:
位元組頭(2bit)+功能碼(1bit)+位元組長度(1bit)+資料位(nbit)+校驗位(2bit)+位元組尾(2bit)
位元組頭:C1 C2
位元組尾:0A 0D
位元組長度(1bit)= 資料位(nbit)+校驗位(2bit)
校驗位:
計算方法:先把位元組頭+功能碼+位元組長度+資料位累加求和,累加的值高16bit的值加到低16bit上,即把累加中最高位的進位加到最低位上,最后進行取反。
使能輸出設定:(括號內為校驗位2byte)
下發: C1 C2 08 04 xx aa (00 00) 0A 0D(xx:1-4 1:X軸 2:Y軸 3:Z軸 4:B軸 aa:0輸出低電平 1輸出高電平)
回報: C1 C2 08 04 xx 00 (00 00) 0A 0D
備注:子命令決議失敗:C9 C8 FF 02 (00 00) 0A 0D
請問如何根據上面的這些資料寫出控制驅動器使能開關的函式?
uj5u.com熱心網友回復:
void CCard::Off(short axis){
//C1 C2 08 04 xx aa (00 00) 0A 0D(xx:1-4 1:X軸 2:Y軸 3:Z軸 4:B軸 aa:0輸出低電平 1輸出高電平)
int a;
if (axis == 1)
a = 0xC1C2080401000A0D;
else if(axis == 2)
a = 0xC1C2080402000A0D;
else if (axis == 3)
a = 0xC1C2080403000A0D;
else if (axis == 4)
a = 0xC1C2080404000A0D;
}
//上面我這樣寫對嗎,接下來怎么辦,無從下手啊
uj5u.com熱心網友回復:
下發: C1 C2 08 04 xx aa (00 00) 0A 0D(xx:1-4 1:X軸 2:Y軸 3:Z軸 4:B軸 aa:0輸出低電平 1輸出高電平)回報: C1 C2 08 04 xx 00 (00 00) 0A 0D
下發,回報分別是用在哪的?括號里的校驗位怎么用?我上面那樣刪掉了括號里的校驗位對嗎?
uj5u.com熱心網友回復:
都是對應位元組了,你直接對應的寫進去即可,一般不用這么一個變數保存,一個是一個包不知有8位元組,16位元組,還有一個原因是有些包長度不定。unsigned char* package = new unsigned char[10];
package[0] = 0xC1;
package[1] = 0xC2;
package[3] = 0x08;
...
...
...
uj5u.com熱心網友回復:
那得出來0xC1C2080401000A0D這串數字怎么用,還有括號里的校驗位,下發、回報這些是怎么回事uj5u.com熱心網友回復:
你說的是這樣吧?unsigned char* package = new unsigned char[10];
package[0] = 0xC1;
package[1] = 0xC2;
package[2] = 0x08;
package[3] = 0x04;
package[4] = 0x00;
package[5] = 0x00+axis;
package[6] = 0x00;
package[7] = 0x00;//校驗位
package[8] = 0x0A;
package[9] = 0x0D;
校驗位是要也寫進去嗎?
uj5u.com熱心網友回復:
你仔細看看說明,資料包一般包含:頭標志,長度,校驗,尾標志,你這里的末尾就是換行回車,校驗應該有說明是怎么計算,最簡單是異或校驗和CRCuj5u.com熱心網友回復:
把通訊協議拼裝成 位元組陣列來使用不要這樣用 0xC1C2080401000A0D 計算機或者單片機無法表示特別大的數
uj5u.com熱心網友回復:
位元組長度(1bit)= 資料位(nbit)+校驗位(2bit) 這不應該是bit,都應該是byte位元組校驗占用兩個位元組
uj5u.com熱心網友回復:
校驗方法知道,但是不知咋用校驗位:
計算方法:先把位元組頭+功能碼+位元組長度+資料位累加求和,累加的值高16bit的值加到低16bit上,即把累加中最高位的進位加到最低位上,最后進行取反。
這個是例程:
u16 checksum(u8 *buffer,u16 size)
{
u32 cksum=0;
u8 i=0;
for(i=0;i<size;i++)
{
cksum +=*buffer++;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum +=(cksum >>16);
return ~cksum;
}
uj5u.com熱心網友回復:
嗯嗯,這個懂了,現在用這個方法了
unsigned char* package = new unsigned char[10];
package[0] = 0xC1;
package[1] = 0xC2;
uj5u.com熱心網友回復:
u16 cs = checksum(data, size);
計算后的校驗位根據要求進行賦值
比如校驗后結果為0xAABB
則
大端模式
package[n] = cs>>8;//校驗位 高位
package[n+1] = cs&0xFF;//校驗位 地位
小端模式
package[n] = cs&0xFF;//校驗位 高位
package[n+1] = cs>>8;//校驗位 地位
uj5u.com熱心網友回復:
package[n] = cs&0xFF;//校驗位 高位package[n+1] = cs>>8;//校驗位 地位
這句用來干嘛
uj5u.com熱心網友回復:
校驗結果是unsigned int16,占2個位元組,省去用memcpy呼叫堆疊多余浪費時間,所以直接用位運算取出這2個位元組保存到陣列而已。uj5u.com熱心網友回復:
package[n] = cs&0xFF;package[n+1] = cs>>8;
這兩個package是校驗位?
uj5u.com熱心網友回復:
設備間一般以位元組流定義通訊協議,主要是因為不同CPU架構/編譯器的存盤大小端有差異
//發送資料幀
int TransFrame(BYTE bFun /*功能碼*/,
BYTE bDataLen /*資料長度*/,
BYTE *pbData /*資料*/)
{
//注意這里*********(根據協議選擇大端、小端)
#define _BIG_ENDIAN //大端模式?
//檢查引數
ASSERT(bDataLen > 0);
ASSERT(pbData);
if(bDataLen == 0 || pbData=https://bbs.csdn.net/topics/=NULL)
return 0;
//總目標發送長度
int iTxLen = 0
+ 2 //位元組頭
+ 1 //功能碼
+ 1 //位元組長度
+ bDataLen //資料長度
+ 2 //校驗
+ 2 //位元組尾
+ 0;
//申請緩沖區
BYTE *pTxData = new BYTE[iTxLen];
//構造發送資料幀
int iOfst = 0;
//位元組頭
pTxData[iOfst] = 0xC1; iOfst++;
pTxData[iOfst] = 0xC2; iOfst++;
//功能碼
pTxData[iOfst] = bFun; iOfst++;
//位元組長度
pTxData[iOfst] = bDataLen+2; iOfst++;
//資料
memcpy(pTxData+iOfst, pbData, bDataLen); iOfst+=bDataLen;
//計算校驗
{
//之前所有資料的累計和
ULONG uSumL = 0;
for(int n=0; n<iOfst; n++) { uSumL += pTxData[n]; }
//(高16位+低16位)后取反
WORD wSum = (WORD)(~(HIWORD(uSumL) + LOWORD(uSumL)));
#ifdef _BIG_ENDIAN //大端模式
pTxData[iOfst] = HIBYTE(wSum); iOfst++;
pTxData[iOfst] = LOBYTE(wSum); iOfst++;
#else //!_BIG_ENDIAN //小端模式
pTxData[iOfst] = LOBYTE(wSum); iOfst++;
pTxData[iOfst] = HIBYTE(wSum); iOfst++;
#endif //_BIG_ENDIAN
////////////////////////////
}
//位元組尾
pTxData[iOfst] = 0x0A; iOfst++;
pTxData[iOfst] = 0x0D; iOfst++;
//檢驗長度
ASSERT(iOfst == iTxLen);
//這里用串口等通訊介面發送資料
//WriteFile(hCom, pTxData, iTxLen,……)
//接收&等待回應
//ReadFile(hCom, pRxData, iRxBuffLen, ……)
//決議接收資料
//結束清理
delete [] pTxData;
return 1;
}
BOOL SendCmd(BYTE bAix /*軸:1=X 2=Y 3=Z 4=B*/,
BYTE bOut /*輸出 0電平 1高電平*/
)
{
BYTE bData[]= {bAix/*軸*/, bOut/*輸出*/};
return TransFrame(0x08/*功能碼*/, 0x02/*資料長度*/, bData /*資料*/);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/261143.html
標籤:基礎類
上一篇:無法決議的外部符號問題
