linux下,PC机串口通信开发

本文详细介绍了如何在Linux系统中查看电脑串口信息,如ttyS0和ttyS1,修改串口波特率,以及通过C++编程发送数据到串口。还展示了如何处理open函数错误,如权限问题和波特率检查方法。
摘要由CSDN通过智能技术生成
 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、修改串口波特率
stty -F /dev/ttyUSB0 9600

 3、给串口发送数据
echo -ne '\x2A\x53\x0D' | sudo tee /dev/ttyUSB0
  • echo -ne: -n 参数表示不输出结尾的换行符,-e 参数允许解释转义字符。
  • '\x2A\x53\x0D': 是一个包含十六进制数据的字符串,其中 \x 表示后面紧跟的是十六进制值。
  • sudo tee /dev/ttyUSB0: 将数据发送到 /dev/ttyUSB0 串口设备。你可能需要使用 sudo 权限。 
 4、添加串口调试代码

简单实现控制灯开的函数

#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;
}
5、遇到open函数出错

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

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

chmod 666 /dev/ttyS0

或者以root权限运行可执行文件

// 假如可执行文件是a.out
sudo ./a.out

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

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值