- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个条形码阅读器,它通过 RS232 串行端口连接到 PC。我正在编写一个 C++ 代码来向条形码扫描器发送命令并将响应返回给 PC。目前程序可以正确发送数据到设备,但无法读取条码扫描器的响应。在这种情况下,一旦我们向条形码阅读器发送命令,它就会以肯定或否定的确认回应。
e.g:- Send BEEP command.
1. Host(PC) send a BEEP command to barcode scanner
2. Barcode scanner make a beep sound and send the acknowledgement back
to host (PC)
3. Host (PC) read the acknowledgement
在下面的代码中,前两步工作正常,但我无法正确编写第三步。请有人帮助我更正我的源代码以异步读取条码扫描器的响应。
主要.cpp
#include <iostream>
extern "C"
{
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
}
#include "DeviceRS232.h"
#include "Message.h"
int main()
{
unsigned char recvBuffer[257];
unsigned char ledOn[] = {0x05, 0xE7, 0x04, 0x00, 0x0D, 0x00};
unsigned char SSIBuffer[] = {0x00, 0xC6, 0x04, 0x08, 0x11, 0xEE, 0x01};
unsigned char requestRevision[] = {0x00, 0x04, 0xA3, 0x04, 0x00};
unsigned char sendBeep[] = {0x00, 0xE6, 0x04, 0x00, 0x05};
Message beepCommand(sendBeep, sizeof(sendBeep)/sizeof(sendBeep[0]));
std::cout << "*********************************************************" << std::endl << std::endl;
DeviceRS232 dev_rs232;
dev_rs232.setDefaultAttributes();
dev_rs232.openSerialPort();
// Send BEEP command several times.
std::cout << "---Start sending beep---" << std::endl;
for(int x=0; x<1; x++)
{
int sizeSent = dev_rs232.sendDataBuffer(beepCommand.getCommandData(), beepCommand.getLen());
if( sizeSent > 0)
{
std::cout << "Data sent: " << sizeSent << std::endl;
}
memset(recvBuffer, 0, sizeof(recvBuffer));
int recvSize = dev_rs232.receiveDataBuffer(recvBuffer, sizeof(recvBuffer));
std::cout << "Date Received, Data: " << recvBuffer << " Size: " << recvSize << std::endl;
sleep(2);
/**
while(true)
{
memset(recvBuffer, 0, sizeof(recvBuffer));
int recvSize = dev_rs232.receiveDataBuffer(recvBuffer, sizeof(recvBuffer));
if(recvSize > 0)
std::cout << "Date Received, Data: " << recvBuffer << " Size: " << recvSize << std::endl;
sleep(2);
}*/
}
std::cout << "---End sending beep-----\n" << std::endl;
dev_rs232.closeSerialPort();
std::cout << "*********************************************************" << std::endl;
return 0;
}
消息.h
#ifndef MESSAGE_H
#define MESSAGE_H
#include <iostream>
#include <string>
#include <numeric>
extern "C"
{
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
}
class Message
{
public:
Message(); // default constructor
virtual ~Message(); // destructor
Message(const std::basic_string<unsigned char> msg) : commandMsg(msg)
{
printf("msg[0]:%x\n", msg[4]);
std::cout << "length: " << commandMsg.length() << std::endl;
//commandMsg[0] = commandMsg.length();
appendChecksum();
};
Message(const unsigned char *msg, int msglen) : commandMsg(msg, msglen)
{
commandMsg[0] = commandMsg.length();
appendChecksum();
};
const unsigned char *getCommandData() const
{
return commandMsg.c_str();
}
int getLen() const
{
return commandMsg.length();
}
protected:
private:
int appendChecksum();
std::basic_string<unsigned char> commandMsg;
};
#endif // MESSAGE_H
消息.cpp
#include "Message.h"
Message::Message()
{
//ctor
}
Message::~Message()
{
//dtor
}
int Message::appendChecksum()
{
int sum = -std::accumulate(commandMsg.begin(), commandMsg.end(), 0);
commandMsg.push_back(0xFF & (sum >> 8));
commandMsg.push_back(0xFF & sum);
}
设备RS232.h
#ifndef DEVICERS232_H
#define DEVICERS232_H
extern "C"
{
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <stdlib.h>
}
#include <string>
#define MAX_SERIAL_PORT_NO 30
class DeviceRS232
{
public:
DeviceRS232();
virtual ~DeviceRS232();
int fdRS232; // file descriptor for the serial port
void setSerialPort(std::string sp);
void setBaudRate(long baud);
void setDataBits(int dataBit);
void setStopBits(int stopBit);
void setNumberOfParityBits(int nparityBits);
void setDefaultAttributes();
long getBaudRate();
std::string getSerialPort();
int openSerialPort();
int readUserConfiguration();
int sendDataBuffer(const unsigned char *dataBuffer, size_t bufferSize);
int receiveDataBuffer(unsigned char *dataBuffer, size_t bufferSize);
void closeSerialPort();
protected:
std::string serialPort; // Serial port like /dev/ttyS0
long baudRate; // Scanner baud rate
int dataBits; // data bits
int stopBits; // stop bits
int numberOfParityBits; // number of parity bits
termios oldSerialPortSetting; // Current values of termios structure for /dev/ttyS0
termios newSerialPortSetting; // new termios attributes for /dev/ttyS0
private:
};
#endif // DEVICERS232_H
设备RS232.cpp
#include "DeviceRS232.h"
DeviceRS232::DeviceRS232()
{
//ctor
}
DeviceRS232::~DeviceRS232()
{
//dtor
}
void DeviceRS232::setSerialPort(std::string sp)
{
serialPort = sp;
}
void DeviceRS232::setBaudRate(long baud)
{
baudRate = baud;
}
void DeviceRS232::setDataBits(int dataBit)
{
dataBits = dataBit;
}
void DeviceRS232::setStopBits(int stopBit)
{
stopBits = stopBit;
}
void DeviceRS232::setNumberOfParityBits(int nparityBits)
{
numberOfParityBits = nparityBits;
}
void DeviceRS232::setDefaultAttributes()
{
std::string sp = "/dev/ttyS0";
long baud = 9600;
int dataBit = 1;
int stopBit = 1;
int nparityBits = 0;
setSerialPort(sp);
setBaudRate(baud);
setDataBits(dataBit);
setStopBits(stopBit);
setNumberOfParityBits(nparityBits);
}
long DeviceRS232::getBaudRate()
{
return baudRate;
}
std::string DeviceRS232::getSerialPort()
{
return serialPort;
}
int DeviceRS232::openSerialPort()
{
int fd, baudr, status, portStatus;
setDefaultAttributes();
switch(getBaudRate())
{
case 50 : baudr = B50;
break;
case 75 : baudr = B75;
break;
case 110 : baudr = B110;
break;
case 134 : baudr = B134;
break;
case 150 : baudr = B150;
break;
case 200 : baudr = B200;
break;
case 300 : baudr = B300;
break;
case 600 : baudr = B600;
break;
case 1200 : baudr = B1200;
break;
case 1800 : baudr = B1800;
break;
case 2400 : baudr = B2400;
break;
case 4800 : baudr = B4800;
break;
case 9600 : baudr = B9600;
break;
case 19200 : baudr = B19200;
break;
case 38400 : baudr = B38400;
break;
case 57600 : baudr = B57600;
break;
case 115200 : baudr = B115200;
break;
case 230400 : baudr = B230400;
break;
case 460800 : baudr = B460800;
break;
case 500000 : baudr = B500000;
break;
case 576000 : baudr = B576000;
break;
case 921600 : baudr = B921600;
break;
case 1000000 : baudr = B1000000;
break;
default : printf("invalid baudrate\n");
return(1);
break;
}
// Open serial port
fd = open(getSerialPort().c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if(fd == -1)
{
printf("Unable to open serial port...\n");
perror(getSerialPort().c_str());
return 1;
}
fdRS232 = fd;
fcntl(fdRS232, F_SETFL, FNDELAY);
status = tcgetattr(fdRS232, &oldSerialPortSetting);
if(status == -1)
{
close(fdRS232);
printf("Unable to get serial port attributes...\n");
return 1;
}
memset(&newSerialPortSetting, 0, sizeof(newSerialPortSetting));
newSerialPortSetting.c_cflag = baudr | CS8 | CLOCAL | CREAD; //
newSerialPortSetting.c_iflag = IGNPAR;
newSerialPortSetting.c_oflag = 0;
newSerialPortSetting.c_lflag = 0;
newSerialPortSetting.c_cc[VMIN] = 0;
newSerialPortSetting.c_cc[VTIME] = 0;
status = tcsetattr(fdRS232, TCSANOW, &newSerialPortSetting);
if(status==-1)
{
close(fdRS232);
perror("unable to adjust portsettings ");
return 1;
}
// Get the status of opened serial port
if(ioctl(fdRS232, TIOCMGET, &portStatus) == -1)
{
perror("Unable to get port status");
return 1;
}
// Tern on DTR and RTS
portStatus |= TIOCM_DTR;
portStatus |= TIOCM_RTS;
// Set the status of the port with new DTR, RTS values
if(ioctl(fdRS232, TIOCMSET, &portStatus) == -1)
{
perror("Unable to set port status...");
return 1;
}
return 0;
}
int DeviceRS232::sendDataBuffer(const unsigned char *dataBuffer, size_t bufferSize)
{
return write(fdRS232, dataBuffer, bufferSize);
}
int DeviceRS232::receiveDataBuffer(unsigned char *dataBuffer, size_t bufferSize)
{
/**int recvSize = 0;
recvSize = read(fdRS232, dataBuffer, bufferSize);
return recvSize;*/
unsigned char recvBuffer[255];
unsigned char *ptrChar;
int nBytes;
ptrChar = recvBuffer;
memset(recvBuffer, 0x00, sizeof(recvBuffer));
while((nBytes = read(fdRS232, ptrChar, recvBuffer+sizeof(recvBuffer) - ptrChar -1)) > 0)
{
ptrChar += nBytes;
//printf("while - %d\n", nBytes);
}
//printf("recvBuffer : %x\n", recvBuffer[0]);
//printf("recvBuffer : %x\n", recvBuffer[1]);
//printf("recvBuffer : %x\n", recvBuffer[2]);
//printf("recvBuffer : %x\n", recvBuffer[3]);
//printf("recvBuffer : %x\n", recvBuffer[4]);
dataBuffer = recvBuffer;
return nBytes;
}
void DeviceRS232::closeSerialPort()
{
int portStatus;
if(ioctl(fdRS232, TIOCMGET, &portStatus) == -1)
{
perror("Unable to get the port status");
}
// Tern off DTR and RTS
portStatus &= ~TIOCM_DTR;
portStatus &= ~TIOCM_RTS;
// Set the status of the port with new DTR, RTS values
if(ioctl(fdRS232, TIOCMSET, &portStatus) == -1)
{
perror("Unable to set port status...");
}
close(fdRS232);
}
我的错误方法是 int DeviceRS232::receiveDataBuffer(unsigned char *dataBuffer, size_t bufferSize)
控制台输出如下:
*********************************************************
---Start sending beep---
Data sent: 7
Date Received, Data: Size: 0
---End sending beep-----
*********************************************************
Process returned 0 (0x0) execution time : 2.004 s
Press ENTER to continue.
最佳答案
正如其他人所指出的,一个可疑区域是您发送的字节数。条形码阅读器并不总是发送 257 个字节,而是可能只需要命令中的字节数,而不是更多。
此外,您的代码有许多重复操作,用于计算消息末尾的校验和。这表明类将有助于简化设计。那么,这里是一个 Message
为此类:
#include <vector>
#include <numeric>
#include <string>
class Message
{
public:
Message(const std::basic_string<unsigned char> msg) : mymsg(msg) {
mymsg[0] = mymsg.length(); appendChecksum(); };
Message(const unsigned char *msg, int msglen) : mymsg(msg, msglen) {
mymsg[0] = mymsg.length(); appendChecksum(); };
const unsigned char *getData() const { return mymsg.c_str(); }
size_t getLen() const { return mymsg.length(); }
private:
int appendChecksum();
std::basic_string<unsigned char> mymsg;
};
int Message::appendChecksum()
{
int sum = -std::accumulate(mymsg.begin(), mymsg.end(), 0);
mymsg.push_back(0xff & (sum >> 8));
mymsg.push_back(0xff & sum);
return sum;
}
现在在您的 main
中例程,您可以删除几十行代码并改用这些代码(如果您使用的是 C++11):
Message setparams{{0x00, 0xc6, 0x04, 0x08, 0x11, 0xee, 0x01}};
Message beep{{0x00, 0xe6, 0x04, 0x00, 0x05}};
Message getrevision{{0x00, 0xA3, 0x04, 0x00}};
Message ledOn{{0x00, 0xe7, 0x04, 0x00, 0x0d, 0x00}};
如果您不使用 C++11(这太可惜了!),您可以改用这种不太干净的样式:
unsigned char parms[] = {0x00, 0xc6, 0x04, 0x08, 0x11, 0xee, 0x01};
Message setparams(parms,sizeof(parms)/sizeof(parms[0]));
请注意,第一个字节设置为零而不是长度。这样做是因为构造函数会在计算和附加校验和之前自动计算并在该字节中设置适当的长度。当然,还有其他方法可以做到这一点,但我会把它留给你。
最后,在你的循环中,你现在可以使用这一行:
int sizeSent = dev_rs232.sendDataBuffer(beep.getData(), beep.getLen());
这可能会或可能不会真正解决问题,但它会帮助您从一个更干净的程序开始。
此外,还有一些风格和设计建议:
using namespace std
的习惯iostream
而不是 printf
setDefaultAttributes()
创 build 备后,立即让构造函数设置合理的默认值static const
.这将使程序更易于理解和维护。boost::asio
而不是自己滚动祝你好运!
编辑:根据您敏锐(且正确!)的观察,Message
当输入普通 unsigned char *
时,构造函数无法正常工作,我添加了第二个构造函数并修改了非 C++11 版本的代码。对于给您带来的不便,我们深表歉意,感谢您让我诚实。
关于c++ - 通过 RS232 串行端口从条码扫描器读取异步数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22760054/
我是编程初学者(学习Java)。我正在尝试编写一个程序,其中列出了四个不同的选项供用户选择。 这是其中的一部分: import java.util.*; public class fight
这个问题已经有答案了: nextDouble() throws an InputMismatchException when I enter a double (2 个回答) 已关闭 8 年前。 我的
为什么下面的代码返回 false? Scanner sc = new Scanner("-v "); sc.useDelimiter("-[a-zA-Z]\\s+"); System.out.prin
我这里有一个由两部分组成的问题。因此,我正在为一个作业编写代码,尝试从文本文件中读取整数作为坐标。例如,我有一个标题为 test1 的文本文件,其内容如下:50 00 510 53 310 0。现在,
当我尝试通过单步执行每一行来调试简单的 Java 代码时,我可以成功调试它。但是,如果我通过进入每一行来调试它,我最终会得到“找不到源”。 import java.util.*; public
我正在尝试接受一个字符串输入,该输入由多行以“,”和“;”分隔的数字组成. 示例: 1,2;3,4;5,6; 9,8;7,6; 0,1; ; 代码: ArrayList alist = new Arr
我想问一个关于我的代码的问题。 对于它的低效和困惑我深表歉意,我还在努力学习java。 System.out.println("Please choose the number corresp
现在选择菜单上的每个选项都可以正常工作(感谢 Tarek Salah 和 dasblinkenlight 的帮助)。现在的问题是,当我选择一个需要我输入新单词的选项(例如选项 3,用户必须输入歌曲名称
我有一个数据文件,其中多个连续行上有斜杠分隔的整数。 这是我想用来读取和打印所有这些整数的一小段代码: import java.util.Scanner; import java.io.File; c
这个问题在这里已经有了答案: Scanner class skips over whitespace (5 个答案) 关闭 7 年前。 我做了一个简单的程序,允许用户输入一个名字然后问候他。 imp
我想使用手写的降序解析器来解析一些文本。我使用了带有以下分隔符的 Scanner:"\\s*"。不幸的是,这个模式匹配一个空字符串的事实似乎让每个 hasNextFoo 和 nextFoo 都不再
Stackoverflow,你好。我无法理解这段代码的输出 public static void main (String[] args) { String context = "0100 5
我需要编写一个java程序,获取所有计算机网络接口(interface)并扫描子网内的IP地址和MAC地址。 我不太确定该怎么做,但我发现有一个方法叫做: Arping.scan(deviceName
Sonar 提示 Scanner 应该一直关闭,对吗? Scanner scanner = new Scanner("simple string") 此扫描仪不是从文件等扫描。为什么要关闭它? 最佳答
我正在使用 Java Scanner 对象来解析文本文件。我需要扫描部分文件两次(出于性能原因,这样我就不必临时存储其内容)。 因此,是否有一种方法可以将扫描仪“倒回”到特定文件位置? 或者,有没有一
我正在为我的一门类(class)做一个实验室,因此我更多地是在寻找解释而不是实际代码。 对于此作业的一部分,我需要从用户那里读取数字,直到按下 control-d。我在一个方法中有一个 while 循
我正在尝试构建一个程序,我想在其中输入(使用扫描仪)一些数字,例如 5,3,6,65,33,1,24,12,然后使用 2 个线程打印它们。第一个线程将打印从低到高,第二个线程将打印从高到低。我将在这里
我编写了一段简短的 Java 代码来计算用户使用 Scanner 输入的两个整数的乘积。用户被迫输入整数值。代码如下所示。 import java.util.Scanner; public class
我在我的 java 项目中遇到以下异常。 Exception in thread "main" java.util.NoSuchElementException at java.util.Sc
我有一串 float ,例如 1.0000\0.0000\0.0000\0.00000\1.0000\0.0000\0.0000 我需要解析它。我使用 Java 扫描仪并使用反斜杠作为分隔符。它已经以
我是一名优秀的程序员,十分优秀!