linux下,PC机串口通信开发

发布时间:2024年01月12日
?1、查看电脑的串口
~/share/bin/PC$ dmesg | grep tty
[    0.083244] printk: console [tty0] enabled
[    0.329145] 00:02: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
[    0.351177] 00:03: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a 16550A
[    0.420781] tty tty48: hash matches

从回复信息中可以看出电脑有两个串口,分别是ttyS0,ttyS1

USB口的话,信息显示是ttyUSB0

?2、添加串口调试代码

简单实现控制灯开的函数

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>      /*文件控制定义*/
#include <termios.h>    /*PPSIX 终端控制定义*/
#include <sys/ioctl.h>
#include <errno.h>
#include <sys/select.h>
#include <sstream>
#include <iomanip>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

using namespace std;

static int lightOn();
static int sendRecv(uint8_t *sBuf, uint16_t sSize, uint8_t *rBuf, uint16_t rSize);
static int Open(const char* device, int baudrate, char parity = 'N', int bytesize = 8, int stopbits = 1);
static int set_parity(int fd,int databits,int stopbits,int parity,int baudrate);
int Read(void* buf, size_t maxLen);
int Write(const void* buf, size_t len);
std::string toHex(uint8_t *buf, uint16_t size);

int m_fd;

int main()
{
    Open("/dev/ttyS0", 9600);

    lightOn();

    return 0;
}

int Open(const char* device, int baudrate, char parity/* = 'N'*/, int bytesize/* = 8*/, int stopbits/* = 1*/)
{
    printf("enter %s\n", __func__);

    m_fd = ::open(device, O_RDWR | O_NOCTTY | O_NDELAY);
    if (m_fd < 0){
        perror("打开COM口时出错");
        return -1;
    }

    //if( set_parity(m_fd,8,1,'N') < 0)
    if( set_parity(m_fd, bytesize, stopbits, parity, baudrate) < 0){
        perror("Set Parity Error\n");
        return -1;
    }

    tcflush(m_fd, TCIOFLUSH);

    printf("leave %s\n", __func__);

    return 0;
}

int set_parity(int fd,int databits,int stopbits,int parity,int baudrate)
{
    struct termios optnew;
    speed_t speed = B19200;

    if ( fd >0 ) {
            /* Read with blocking behavior */
            fcntl(fd, F_SETFL, 0);

            /* Get current option */
            tcgetattr(fd, &optnew);

            /* initialize new option to raw input/output */
    //              memset(&optnew, 0, sizeof(optnew));
            cfmakeraw(&optnew);
            optnew.c_cc[VMIN ] = 0;
            optnew.c_cc[VTIME] = 2*10;

            /* set baudrate */
            switch (baudrate) {
                    case   1200: speed =   B1200;  break;
                    case   1800: speed =   B1800;  break;
                    case   4800: speed =   B4800;  break;
                    case   9600: speed =   B9600;  break;
                    case  19200: speed =  B19200;  break;
                    case  38400: speed =  B38400;  break;
                    case  57600: speed =  B57600;  break;
                    case 115200: speed = B115200;  break;
                    default:    speed = B19200; break;
            }
            cfsetispeed(&optnew, speed);
            cfsetospeed(&optnew, speed);

            /* Set data bits */
            optnew.c_cflag &= ~CSIZE;
            optnew.c_cflag &= ~CRTSCTS;
            optnew.c_iflag &= ~(ICRNL|IXON);
            optnew.c_cflag |= CLOCAL | CREAD;
            optnew.c_oflag &= ~OPOST;

            switch (databits) {
                    case 5: optnew.c_cflag |= CS5; break;
                    case 6: optnew.c_cflag |= CS6; break;
                    case 7: optnew.c_cflag |= CS7; break;
                    default :
                            optnew.c_cflag |= CS8; break;
            }

            /* Set parity checking */
            optnew.c_cflag |= PARENB;
            switch (parity) {
                    case 'e':
                    case 'E': optnew.c_cflag &= ~PARODD; break;
                    case 'o':
                    case 'O': optnew.c_cflag &=  PARODD; break;
                    default :
                            optnew.c_cflag &= ~PARENB; break;
            }

            /* Set stop bit(s) */
            if (stopbits == 2)
                    optnew.c_cflag &=  CSTOPB;
            else
                    optnew.c_cflag &= ~CSTOPB;

            optnew.c_lflag &= ~( ICANON | ECHO | ECHOE | ISIG );

            /* Apply new option */
            tcsetattr(fd, TCSANOW, &optnew);
    }
    return fd;
}

int lightOn()
{
    uint8_t send[] = {0x2A, 0x4B, 0x0D};
    uint8_t right[] = {0x2A, 0x4B, 0x00, 0x0D};

    int retry = 2;
    while(retry--){
        uint8_t recv[sizeof(right)];
        memset(recv, 0, sizeof(right));

        printf("send %s\n", toHex((uint8_t *)send, sizeof(send)).c_str());

        const int recvCount = sendRecv(send, sizeof(send), recv, sizeof(recv));

        if(recvCount != sizeof(recv)){
            if(recvCount){
                printf("recv %s\n", toHex((uint8_t *)recv, sizeof(recv)).c_str());
            }
            continue;
        }

        if(0 != memcmp(right, recv, sizeof(right))){
            printf("recv %s\n", toHex((uint8_t *)recv, sizeof(recv)).c_str());
            continue;
        }

        //success
        printf("recv %s\n", toHex((uint8_t *)recv, sizeof(recv)).c_str());
        retry = 0;
        break;
    }

    return retry;
}

int sendRecv(uint8_t *sBuf, uint16_t sSize, uint8_t *rBuf, uint16_t rSize)
{
    printf("enter %s\n", __func__);

//    m_mutex.lock();
    int ret = Write(sBuf, sSize);
    if (ret != 0){
        printf("%s Write error, Buf:%s\n", __func__, sBuf);
        goto _RET;
    }
    ret = Read(rBuf, rSize);
    if (ret != rSize){
        printf("%s read:%s ret:%d\n", __func__, rBuf, ret);
        goto _RET;
    }

_RET:
//    m_mutex.unlock();
    return ret;
}

int Write(const void* buf, size_t len)
{
    printf("enter %s\n", __func__);

    int ret = 0;
    int n = ::write(m_fd, buf, len);
    if(n != len){
        ret = -2;
    }
//    printf("send to uart result:%i\n", ret);
    return ret;
}

/*
 * return 接受到的字节数
 */
int Read(void* buf, size_t maxLen)
{
    printf("enter %s\n", __func__);

    int offset = 0;
    while(offset < maxLen){
        fd_set rd;
        FD_ZERO(&rd);
        FD_SET(m_fd, &rd);
        timeval timeout;
        timeout.tv_sec = 1;
        int ready = select(m_fd+1, &rd, NULL, NULL, &timeout);
        if (ready == 0){    //timeout
//            offset = SER_TO;
            printf("timeout\n");
            break;
        }else if (ready == -1 && (errno != EINTR) ){ //error
            offset = -2;
            printf("error\n");
            break;
        }else if(ready == 1){
            if (FD_ISSET(m_fd, &rd)){
                int n = ::read(m_fd, buf + offset, maxLen - offset);
                if(n > 0){
                    offset += n;
                }
            }
        }
    }
    return offset;
}

std::string toHex(uint8_t *buf, uint16_t size)
{
    std::stringstream hexSS;
    for (int i = 0; i < size; i++){
        hexSS << std::setw(2) << std::setfill('0') << std::hex << (int)buf[i] << " ";
    }
    std::string hexStr = hexSS.str();
    return hexStr;
}
3、遇到open函数出错

在::open() 出错时,已经通过perror函数打印出出错信息,可以根据信息修改

1)比如报错信息提示权限不对,修改权限

chmod 666 /dev/ttyS0

2)检查串口波特率

~/share/bin/PC$ stty -F /dev/ttyS0
speed 9600 baud; line = 0;
min = 0; time = 20;
-brkint -icrnl -imaxbel
-opost
-isig -icanon -iexten -echo -echoe

?

文章来源:https://blog.csdn.net/ylxwk/article/details/135559766
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。