串口自由协议通讯
发布时间: 2022-11-23 预览次数:


利用串口设备控件image.png,可以实现用户的自由协议通讯。默认的协议格式如下:


协议头(2字节)命令(2字节)数据长度(1字节)数据(N)校验(1字节 可选)
0xFF55Cmdlendatachecksum

  1. 添加串口设备,并指定正确的通讯参数。

    HMI下只有三路串口:COM1-232;COM2-485;COM3-422;


image.png


2.IDE会在“sintt_app.c”自动生成相应代码


void app_init()

{

        //串口初始化

uart_obj1.head1 = UART_CMD_HEAD1;//帧头1

uart_obj1.head2 = UART_CMD_HEAD2;//帧头2

uart_obj1.enableCheckSum = false; //不开启校验和

uart_obj1.pkgMinLen = 5;//帧最小长度,不启用校验和为5,启用校验和设为6

uart_obj1.mParse = parseProtocol_uart_obj1;//串口接收数据回调函数

sintt_uart_init(&uart_obj1, "COM1", 115200, 8, 0, 1);//这里设置的是HMI的设置,如果在win32下模拟运行,需要设置为电脑连接的串口,串口号必须小于10.

}

//串口接收数据回调函数,协议解析回调函数

int parseProtocol_uart_obj1(void *var, const uint8_t *pData, uint16_t len) {

SINTT_UART *uart_var = (SINTT_UART*) var;

uint16_t remainLen = len; // 剩余数据长度

uint16_t dataLen; // 数据包长度

uint16_t frameLen; // 帧长度


//以下部分需要根据协议格式进行相应的修改,解析出每一帧的数据

while (remainLen >= uart_var->pkgMinLen) {

// 找到一帧数据的数据头

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) {

// 数据内容不全

break;

}

// 支持checksum校验,需要时在CommDef.h文件中打开PRO_SUPPORT_CHECK_SUM宏

if (uart_var->enableCheckSum) { //启用校验和

// 检测校验码

if (uart_var->getCheckSum(pData, frameLen - 1) == pData[frameLen - 1]) {

// 解析一帧数据

procParse_uart_obj1(pData, frameLen);

} else {


}

} else { // 解析一帧数据

procParse_uart_obj1(pData, frameLen);

}


pData += frameLen;

remainLen -= frameLen;

}


return len - remainLen; //已解析指令长度

}


//解析每一帧数据,用户只需关注这个函数解析指令

void procParse_uart_obj1(const uint8_t *pData, uint16_t len) {

//以下例程假设定义了变量:rotate_speed、rotate_speed1、line_radius

uint16_t cmd = (pData[2] << 8) | pData[3];

uint32_t *addr;

switch (cmd) {

case UART_CMD_0: //16位无符号型数据存储

//rotate_speed=(pData[5]<<8)|pData[6];

//sintt_notify_var_changed(&rotate_speed);//通知UI线程更新数据

break;

case UART_CMD_1: //32位无符号型数据存储

//rotate_speed1=(pData[5]<<24)|(pData[6]<<16)|(pData[7]<<8)|pData[8];

//sintt_notify_var_changed(&rotate_speed1);//通知UI线程更新数据

break;

case UART_CMD_2: //float型数据存储,发送数据时也参考

//addr=(uint32_t)(&line_radius);

//*addr=(pData[5]<<24)|(pData[6]<<16)|(pData[7]<<8)|pData[8];

//sintt_notify_var_changed(&line_radius);//通知UI线程更新数据

break;

}

}

解析指令的例程中定义了三个变量,uint16_t rotate_speed、uint32_t rotate_speed1、float line_radius,用户可参考增加指令和变量。


发送数据:


例程代码如下:

1)发送16位数

        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)发送32位数

        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)发送浮点数

        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);


串口设备.gif





上一篇: 已经没有了
下一篇: 已经没有了