利用串口設(shè)備控件,可以實(shí)現(xiàn)用戶的自由協(xié)議通訊。默認(rèn)的協(xié)議格式如下:
協(xié)議頭(2字節(jié)) | 命令(2字節(jié)) | 數(shù)據(jù)長(zhǎng)度(1字節(jié)) | 數(shù)據(jù)(N) | 校驗(yàn)(1字節(jié) 可選) |
---|---|---|---|---|
0xFF55 | Cmd | len | data | checksum |
添加串口設(shè)備,并指定正確的通訊參數(shù)。
HMI下只有三路串口:COM1-232;COM2-485;COM3-422;
2.IDE會(huì)在“sintt_app.c”自動(dòng)生成相應(yīng)代碼
void app_init()
{
//串口初始化
uart_obj1.head1 = UART_CMD_HEAD1;//幀頭1
uart_obj1.head2 = UART_CMD_HEAD2;//幀頭2
uart_obj1.enableCheckSum = false; //不開啟校驗(yàn)和
uart_obj1.pkgMinLen = 5;//幀最小長(zhǎng)度,不啟用校驗(yàn)和為5,啟用校驗(yàn)和設(shè)為6
uart_obj1.mParse = parseProtocol_uart_obj1;//串口接收數(shù)據(jù)回調(diào)函數(shù)
sintt_uart_init(&uart_obj1, "COM1", 115200, 8, 0, 1);//這里設(shè)置的是HMI的設(shè)置,如果在win32下模擬運(yùn)行,需要設(shè)置為電腦連接的串口,串口號(hào)必須小于10.
}
//串口接收數(shù)據(jù)回調(diào)函數(shù),協(xié)議解析回調(diào)函數(shù)
int parseProtocol_uart_obj1(void *var, const uint8_t *pData, uint16_t len) {
SINTT_UART *uart_var = (SINTT_UART*) var;
uint16_t remainLen = len; // 剩余數(shù)據(jù)長(zhǎng)度
uint16_t dataLen; // 數(shù)據(jù)包長(zhǎng)度
uint16_t frameLen; // 幀長(zhǎng)度
//以下部分需要根據(jù)協(xié)議格式進(jìn)行相應(yīng)的修改,解析出每一幀的數(shù)據(jù)
while (remainLen >= uart_var->pkgMinLen) {
// 找到一幀數(shù)據(jù)的數(shù)據(jù)頭
while ((remainLen >= 2) && ((pData[0] != uart_var->head1) || (pData[1] != uart_var->head2))) {
pData++;
remainLen--;
continue;
}
if (remainLen < uart_var->pkgMinLen) {
break;
}
dataLen = pData[4];
frameLen = dataLen + uart_var->pkgMinLen;
if (frameLen > remainLen) {
// 數(shù)據(jù)內(nèi)容不全
break;
}
// 支持checksum校驗(yàn),需要時(shí)在CommDef.h文件中打開PRO_SUPPORT_CHECK_SUM宏
if (uart_var->enableCheckSum) { //啟用校驗(yàn)和
// 檢測(cè)校驗(yàn)碼
if (uart_var->getCheckSum(pData, frameLen - 1) == pData[frameLen - 1]) {
// 解析一幀數(shù)據(jù)
procParse_uart_obj1(pData, frameLen);
} else {
}
} else { // 解析一幀數(shù)據(jù)
procParse_uart_obj1(pData, frameLen);
}
pData += frameLen;
remainLen -= frameLen;
}
return len - remainLen; //已解析指令長(zhǎng)度
}
//解析每一幀數(shù)據(jù),用戶只需關(guān)注這個(gè)函數(shù)解析指令
void procParse_uart_obj1(const uint8_t *pData, uint16_t len) {
//以下例程假設(shè)定義了變量:rotate_speed、rotate_speed1、line_radius
uint16_t cmd = (pData[2] << 8) | pData[3];
uint32_t *addr;
switch (cmd) {
case UART_CMD_0: //16位無符號(hào)型數(shù)據(jù)存儲(chǔ)
//rotate_speed=(pData[5]<<8)|pData[6];
//sintt_notify_var_changed(&rotate_speed);//通知UI線程更新數(shù)據(jù)
break;
case UART_CMD_1: //32位無符號(hào)型數(shù)據(jù)存儲(chǔ)
//rotate_speed1=(pData[5]<<24)|(pData[6]<<16)|(pData[7]<<8)|pData[8];
//sintt_notify_var_changed(&rotate_speed1);//通知UI線程更新數(shù)據(jù)
break;
case UART_CMD_2: //float型數(shù)據(jù)存儲(chǔ),發(fā)送數(shù)據(jù)時(shí)也參考
//addr=(uint32_t)(&line_radius);
//*addr=(pData[5]<<24)|(pData[6]<<16)|(pData[7]<<8)|pData[8];
//sintt_notify_var_changed(&line_radius);//通知UI線程更新數(shù)據(jù)
break;
}
}
解析指令的例程中定義了三個(gè)變量,uint16_t rotate_speed、uint32_t rotate_speed1、float line_radius,用戶可參考增加指令和變量。
發(fā)送數(shù)據(jù):
例程代碼如下:
1)發(fā)送16位數(shù)
uint8_t mdata[20];
int len=0;
int sendData=1234;
mdata[len++]=uart_obj1.head1;
mdata[len++]=uart_obj1.head2;
mdata[len++]=UART_CMD_0>>16;
mdata[len++]=UART_CMD_0;
mdata[len++]=0x02;
mdata[len++]=sendData>>8;
mdata[len++]=sendData;
uart_obj1.mSend(&uart_obj1,mdata,len);
2)發(fā)送32位數(shù)
uint8_t mdata[20];
int len=0;
int sendData=1234567;
mdata[len++]=uart_obj1.head1;
mdata[len++]=uart_obj1.head2;
mdata[len++]=UART_CMD_1>>16;
mdata[len++]=UART_CMD_1;
mdata[len++]=0x04;
mdata[len++]=sendData>>24;
mdata[len++]=sendData>>16;
mdata[len++]=sendData>>8;
mdata[len++]=sendData;
uart_obj1.mSend(&uart_obj1,mdata,len);
3)發(fā)送浮點(diǎn)數(shù)
uint8_t mdata[20];
int len=0;
float temp=123.45f;
uint32_t *p=&temp;
mdata[len++]=uart_obj1.head1;
mdata[len++]=uart_obj1.head2;
mdata[len++]=UART_CMD_2>>16;
mdata[len++]=UART_CMD_2;
mdata[len++]=0x04;
mdata[len++]=(*p)>>24;
mdata[len++]=(*p)>>16;
mdata[len++]=(*p)>>8;
mdata[len++]=(*p);
uart_obj.mSend(&uart_obj,mdata,len);