通过RS232串口向条形码扫描器发送数据

3
我有一个通过RS232串口连接的条形码扫描仪。我需要编写一个程序来将此设备与PC连接并传输数据。我已经编写了一些基本方法来初始化通信链接,并尝试通过发送BEEP命令来测试,但它没有像预期的那样响起。所以我认为我的源代码有问题。请有人帮助我完成源代码。以下是已编写的源代码。
01) DeviceRS232.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 <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);
        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

2) DeviceRS232.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");
        return 1;
    }

    fdRS232 = fd;
    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);
}

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

3) main.cpp

#include <iostream>
extern "C"
{
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
}
#include "DeviceRS232.h"

using namespace std;

int main()
{

    //char sendBuffer[4096] = "                        ";
    unsigned char sendBeep[] = {0x05, 0xE6, 0x04, 0x00, 0x0D, 0x00, 0x00};
    unsigned char ledOn[] = {0x05, 0xE7, 0x04, 0x00, 0x0D, 0x00};
    unsigned char val[7];

    cout << "********************** RS232 - SSI **********************" << endl << endl;
    DeviceRS232 dev_rs232;
    dev_rs232.setDefaultAttributes();
    dev_rs232.openSerialPort();

    //----------------------------------------------------
    //for(int x=0; x<10; x++)
    //{
    //    dev_rs232.sendDataBuffer(sendBeep, sizeof(sendBeep));
    //}
    //----------------------------------------------------

    int sizeSent = dev_rs232.sendDataBuffer(sendBeep, sizeof(sendBeep));
    if( sizeSent > 0)
    {
        printf("Data sent: %d...\n", sizeSent);
    }

    sleep(10);

    dev_rs232.closeSerialPort();
    cout << "*********************************************************" << endl;


    return 0;
}

考虑到条形设备的串口通信协议规范,sendBeep[] = {0x05, 0xE6, 0x04, 0x00, 0x0D, 0x00, 0x00}是用于发送哔声的无符号字符数组。

(编辑以添加输出) 输出:

********************** RS232 - SSI **********************

Data sent: 7...
*********************************************************

Process returned 0 (0x0)   execution time : 10.006 s
Press ENTER to continue.

欢迎提供所有帮助和建议,谢谢。


你尝试过将计算机的串行端口连接到另一台计算机[或同一台计算机,使用第二个串行端口]并检查是否正在发送数据吗?你的接线使用DTR / RTS吗? - Mats Petersson
@Mats Petersson:实际上,我无法使用两台点对点计算机完成此操作,因为资源不足。如果您能给我一些设置模拟器的提示,请告诉我。 - Dig The Code
你的电脑有USB接口吗?如果有,你可能可以获取一个连接到USB的串口,并首先使用例如minicom来“监听”串口。当然,你可能想要更改你的代码,以发送一些可读的文本,而不是像你现在的消息一样发送“不可见”的十六进制数字。 - Mats Petersson
1
请问您可以指引我们查看设备通信协议的文档吗?这样我们才能确认您是否正在发送正确的数据。 - Shane Wealti
@Shane Wealti:感谢您提醒我再次阅读规范。我的数据包存在问题(最后2个字节是消息的校验和,等于消息数据的二进制补码之和)。我已经更正了字节结构并重试了一次。这次成功了。感谢您的帮助。 - Dig The Code
@DigTheCode:你能告诉我你用的是哪一种条形码吗?我刚买了一个扫描器,正试图弄清楚在Linux下如何访问它。你能告诉我你尝试过哪个型号吗? - Ragav
1个回答

1
#include <iostream>
extern "C"
{
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
}
#include "DeviceRS232.h"

using namespace std;

int main()
{

    unsigned char sendBuffer[4096] = "Test test test...";
    unsigned char sendBeep[] = {0x05, 0xE6, 0x04, 0x00, 0x11, 0x46, 0x00};
    unsigned char ledOn[] = {0x05, 0xE7, 0x04, 0x00, 0x0D, 0x00};
    unsigned char val[7];

    //-------------------------------------------------------------------------
    unsigned char commonBuffer[257];

    int iChecksum;
    int i;
    commonBuffer[ 1 ] = (unsigned char)0xC6;
    commonBuffer[ 2 ] = (unsigned char)0x04;
    commonBuffer[ 3 ] = (unsigned char)0x08; // Permanant Chnage
    commonBuffer[ 4 ] = (unsigned char)0x11; // Beep after setting. FF for No Beep
    commonBuffer[ 5 ] = (unsigned char)0xEE; // Decorder parameter to set (238)
    commonBuffer[ 6 ] = (unsigned char)0x01; // Value to set

    commonBuffer[ 0 ] = (unsigned char)0x07; // Length

    iChecksum = 0;
    for (i = 0; i < 7; i++)
    {
        iChecksum += commonBuffer[i];
    }

    commonBuffer[i++] = (char)(((-iChecksum) >> 8) & 0xFF); // Add Checksum into the command
    commonBuffer[i++] = (char)((-iChecksum) & 0xFF);
    //-------------------------------------------------------------------------


    cout << "********************** RS232 - SSI **********************" << endl << endl;
    DeviceRS232 dev_rs232;
    dev_rs232.setDefaultAttributes();
    dev_rs232.openSerialPort();

    //----------------------------------------------------
    //for(int x=0; x<10; x++)
    //{
    //    dev_rs232.sendDataBuffer(sendBeep, sizeof(sendBeep));
    //}
    //----------------------------------------------------

    int sizeSent = dev_rs232.sendDataBuffer(commonBuffer, sizeof(commonBuffer));
    if( sizeSent > 0)
    {
        printf("Data sent: %d...\n", sizeSent);
    }

    sleep(1);

    dev_rs232.closeSerialPort();
    cout << "*********************************************************" << endl;


    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接