mbot_linux_serial.cpp文件//包含对应头文件
#include "mbot_linux_serial.h"
using namespace std;//设定工作空间的名称
using namespace boost::asio;//设定工作空间的名称
//串口相关对象
//创建一个 io_service实例
boost::asio::io_service iosev;
//构造一个串口,将"/dev/ttySUB0"转移给实例iosev
boost::asio::serial_port sp(iosev, "/dev/ttyUSB0");
boost::system::error_code err;
/********************************************************
串口发送接收相关常量、变量、共用体对象
********************************************************/
const unsigned char ender[2] = {0x0d, 0x0a};//数据尾
const unsigned char header[2] = {0x55, 0xaa};//数据头
//发送左右轮速控制速度共用体
union sendData
{
short d;
unsigned char data[2];
}leftVelSet,rightVelSet;
//接收数据(左轮速、右轮速、角度)共用体(-32767 - +32768)
union receiveData
{
short d;
unsigned char data[2];
}leftVelNow,rightVelNow,angleNow;
/********************************************************
函数功能:串口参数初始化
入口参数:无
出口参数:
********************************************************/
void serialInit()
{
sp.set_option(serial_port::baud_rate(115200));//设置波特率
sp.set_option(serial_port::flow_control(serial_port::flow_control::none));//流量控制
sp.set_option(serial_port::parity(serial_port::parity::none));//奇偶校验
sp.set_option(serial_port::stop_bits(serial_port::stop_bits::one));//停止位
sp.set_option(serial_port::character_size(8)); //字符大小
}
/********************************************************
函数功能:将对机器人的左右轮子控制速度,打包发送给下位机
入口参数:机器人线速度、角速度
出口参数:
********************************************************/
void writeSpeed(double Left_v, double Right_v,unsigned char ctrlFlag)
{
unsigned char buf[11] = {0};//
int i, length = 0;
leftVelSet.d = Left_v;//mm/s
rightVelSet.d = Right_v;
// 设置消息头
for(i = 0; i < 2; i++)
buf[i] = header[i]; //buf[0] buf[1]
// 设置机器人左右轮速度
length = 5;
buf[2] = length; //buf[2]
for(i = 0; i < 2; i++)
{
buf[i + 3] = leftVelSet.data[i]; //buf[3] buf[4]
buf[i + 5] = rightVelSet.data[i]; //buf[5] buf[6]
}
// 预留控制指令
buf[3 + length - 1] = ctrlFlag; //buf[7]
// 设置校验值、消息尾
buf[3 + length] = getCrc8(buf, 3 + length);//buf[8]
buf[3 + length + 1] = ender[0]; //buf[9]
buf[3 + length + 2] = ender[1]; //buf[10]
// 通过串口下发数据
boost::asio::write(sp, boost::asio::buffer(buf));
}
/********************************************************
函数功能:从下位机读取数据
入口参数:机器人左轮轮速、右轮轮速、角度,预留控制位
出口参数:bool
********************************************************/
bool readSpeed(double &Left_v,double &Right_v,double &Angle,unsigned char &ctrlFlag)
{
char i, length = 0;
unsigned char checkSum;
unsigned char buf[150]={0};
//=========================================================
//此段代码可以读数据的结尾,进而来进行读取数据的头部
try
{
boost::asio::streambuf response;
boost::asio::read_until(sp, response, "\r\n",err);
copy(istream_iterator<unsigned char>(istream(&response)>>noskipws),
istream_iterator<unsigned char>(),
buf);
}
catch(boost::system::system_error &err)
{
ROS_INFO("read_until error");
}
//=========================================================
// 检查信息头
if (buf[0]!= header[0] || buf[1] != header[1]) //buf[0] buf[1]
{
ROS_ERROR("Received message header error!");
return false;
}
// 数据长度
length = buf[2]; //buf[2]
// 检查信息校验值
checkSum = getCrc8(buf, 3 + length); //buf[10] 计算得出
if (checkSum != buf[3 + length]) //buf[10] 串口接收
{
ROS_ERROR("Received data check sum error!");
return false;
}
// 读取速度值
for(i = 0; i < 2; i++)
{
leftVelNow.data[i] = buf[i + 3]; //buf[3] buf[4]
rightVelNow.data[i] = buf[i + 5]; //buf[5] buf[6]
angleNow.data[i] = buf[i + 7]; //buf[7] buf[8]
}
// 读取控制标志位
ctrlFlag = buf[9];
Left_v =leftVelNow.d;
Right_v =rightVelNow.d;
Angle =angleNow.d;
return true;
}
/********************************************************
函数功能:获得8位循环冗余校验值
入口参数:数组地址、长度
出口参数:校验值
********************************************************/
unsigned char getCrc8(unsigned char *ptr, unsigned short len)
{
unsigned char crc;
unsigned char i;
crc = 0;
while(len--)
{
crc ^= *ptr++;
for(i = 0; i < 8; i++)
{
if(crc&0x01)
crc=(crc>>1)^0x8C;
else
crc >>= 1;
}
}
return crc;
}
|