serial_port.cpp
https://blog.csdn.net/u014695839/article/details/81209082
#include
#include
#include
int main(int argc, char** argv)//argc是命令行总的参数个数
//argv[]为保存命令行参数的字符串指针,其中第0个参数是程序的全名,以后的参数为命令行后面跟的用户输入的参数
{
ros::init(argc, argv, "serial_port");
//创建句柄(虽然后面没用到这个句柄,但如果不创建,运行时进程会出错)
ros::NodeHandle n;
//创建一个serial类
serial::Serial sp;
//创建timeout
serial::Timeout to = serial::Timeout::simpleTimeout(100);
//设置要打开的串口名称
sp.setPort("/dev/ttyUSB0");
//设置串口通信的波特率
sp.setBaudrate(115200);
//串口设置timeout
sp.setTimeout(to);
try
{
//打开串口
sp.open();
}
catch(serial::IOException& e)//捕捉输入输出异常
{
ROS_ERROR_STREAM("Unable to open port.");
return -1;
}
//判断串口是否打开成功
if(sp.isOpen())
{
ROS_INFO_STREAM("/dev/ttyUSB0 is opened.");
}
else
{
return -1;
}
ros::Rate loop_rate(500);
while(ros::ok())
{
//获取缓冲区内的字节数
size_t n = sp.available();
if(n!=0)
{
uint8_t buffer[1024];
//读出数据
n = sp.read(buffer, n);
for(int i=0; i
http://docs.ros.org/kinetic/api/serial/html/structserial_1_1Timeout.html
static Timeout serial::Timeout::simpleTimeout ( uint32_t timeout )
Convenience function to generate Timeout structs using a single absolute timeout.
Parameters
timeout A long that defines the time in milliseconds until a timeout occurs after a call to read or write is made.
Returns
Timeout struct that represents this simple timeout provided.
使用一个绝对超时生成超时结构的便利函数。
参数
超时:长时间,以毫秒为单位定义时间,直到在发出读写调用后发生超时。
返回
超时结构,表示提供的这个简单超时。
ROS_INFO_STREAM
日志消息分为五个不同的严重级别:
DEBUG INFO WARN ERROR FATAL
生成一次性日志消息
ROS_DEBUG_STREAM_ONCE(message);
ROS_INFO_STREAM_ONCE (message);
ROS_WARN_STREAM_ONCE (message);
ROS_ERROR_STREAM_ONCE (message);
ROS_FATAL_STREAM_ONCE (message);
生成频率受控的日志消息
ROS_DEBUG_STREAM_THROTTLE(interval, message);
ROS_INFO_STREAM_THROTTLE(interval, message);
ROS_WARN_STREAM_THROTTLE(interval, message);
ROS_ERROR_STREAM_THROTTLE(interval, messge);
ROS_FATAL_STREAM_THROTTLE(interval, message);
std::cout << std::hex << (buffer[i] & 0xff) << " ";
std::cout<<“是向终端屏幕输出”,<<是左移运算符
std::hex 使用十六进制基本格式读取/写入整数值。
std::cout<<"Hello world!!!"<
如果在#include后加上using namespace std
那么就可以写成cout<<"Hello world!!!"<
std::endl
https://blog.csdn.net/xfox101/article/details/1696612
我们知道,最后出现的"/n"可以实现一个换行,不过我们在用C++时教程中总是有意无意地让我们使用endl,两者看上去似乎一样——究竟其中有什么玄妙?查书,书上说endl是一个操纵符(manipulator),它不但实现了换行操作,而且还对输出缓冲区进行刷新。什么意思呢?原来在执行输出操作之后,数据并非立刻传到输出设备,而是先进入一个缓冲区,当适宜的时机(如设备空闲)后再由缓冲区传入,也可以通过操纵符flush进行强制刷新:
cout << "Hello, World! " << “Flush the screen now!!!” << flush;
这样当程序执行到operator<<(flash)之前,有可能前面的字符串数据还在缓冲区中而不是显示在屏幕上,但执行operator<<(flash)之后,程序会强制把缓冲区的数据全部搬运到输出设备并将其清空。而操纵符endl相当于<< “/n” << flush的简写版本,它先输出一个换行符,再实现缓冲区的刷新。大概这是因为一般的输出都是以换行结尾,而结尾处又是习惯进行刷新的时期,方便起见就把两者结合成了endl。读者有兴趣的话,回去也可以为我们的MyOutstream实现一个类似的myflush和myendl操纵符,相关的用于刷新C函数是fflush。
不过可能在屏幕上显示是手动刷新与否区别看来都不大。但对于文件等输出对象就不大一样了:过于频繁的刷新意味着老是写盘,会影响速度。因此通常是写入一定的字节数后再刷新,如何操作?靠的就是这些操纵符。
& 0xff
https://blog.csdn.net/wangyang1354/article/details/52290461
0xFF的二进制表示就是:1111 1111。 高24位补0:0000 0000 0000 0000 0000 0000 1111 1111;
&0xff可以将高的24位置为0,低8位保持原样。这样做的目的就是为了保证二进制数据的一致性。
在32位的电脑中数字都是以32格式存放的,如果是要求一个byte(8位)类型的数字,对于int这种32位的整形,高24位具有随机性(从所有的数字形式来看,前面的24位取值并不确定,我把它视为具有一定的随机性,比如int型的整数,高24位的取值都是不确定的。),低8位才是实际的数据。
java.lang.Integer.toHexString() 方法的参数是int(32位)类型,如果输入一个byte(8位)类型的数字,这个方法会把这个数字的高24为也看作有效位,这就必然导致错误,使用& 0XFF操作,可以把高24位置0以避免这样错误的发生。
串口通讯超时
COMMTIMEOUTS:COMMTIMEOUTS主要用于串口超时参数设置。COMMTIMEOUTS结构如下:
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout;
DWORD ReadTotalTimeoutMultiplier;
DWORD ReadTotalTimeoutConstant;
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutConstant;
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
间隔超时=ReadIntervalTimeout
总超时 = ReadTotalTimeoutMultiplier * 字节数 + ReadTotalTimeoutConstant
串口读取事件分为两个阶段(我以Win32 API函数ReadFile读取串口过程来说明一下)
第一个阶段是:串口执行到ReadFile()函数时,串口还没有开始传输数据,所以串口缓冲区的第一个字节是没有装数据的,这时候总超时起作用,如果在总超时时间内没有进行串口数据的传输,ReadFile()函数就返回,当然 没有读取到任何数据。而且,间隔超时并没有起作用。
第二阶段:假设总超时为20秒,程序运行到ReadFile(),总超时开始从0 计时,如果在计时到达10秒时,串口开始了数据的传输,那么从接收的第一个字节开始,间隔超时就开始计时,假如间隔超时为1ms,那么在读取完第一个字节后,串口开始等待1ms,如果1ms之内接收到了第二个字节,就读取第二个字节,间隔超时重置为0并计时,等待第三个字节的到来,如果第三个字节到来的时间超过了1ms,那么ReadFile()函数立即返回,这时候总超时计时是没到20秒的。如果在20秒总计时时间结束之前,所有的数据都遵守数据间隔为1ms的约定并陆陆续续的到达串口缓冲区,那么就成功进行了一次串口传输和读取;如果20秒总计时时间到,串口还陆陆续续的有数据到达,即使遵守字节间隔为1ms的约定,ReadFile()函数也会立即返回,这时候总超时就起作用了。