树莓派5访问pin口控制uart-ttl转485

xingyun86 2月前 229

树莓派5访问pin口控制uart-ttl转485

ttl转485

// pi5rw.cpp : Defines the entry point for the application.
//
#include "pi5rw.h"
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#define termios asmtermios
#include <asm/termbits.h>
#undef  termios
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/serial.h>
#include <thread>
#include <vector>
int serialSetBaud2(int fd, int baud)
{
    struct termios2 tio = { 0 };
    if (ioctl(fd, TCGETS2, &tio) < 0)
    {
        perror("TCGETS2");
        return (-1);
    }
    tio.c_cflag &= ~CRTSCTS;  //禁用硬件流控
    tio.c_cflag &= ~CBAUD;
    tio.c_cflag |= BOTHER;
    tio.c_ispeed = baud;
    tio.c_ospeed = baud;
    ioctl(fd, TCSETS2, &tio);
    if (ioctl(fd, TCGETS2, &tio) < 0)
    {
        perror("TCGETS2");
        return (-2);
    }
    return 0;
}
int serialOpen(const char* device, const int baud)
{
    struct termios options;
    speed_t myBaud;
    int     status, fd;
    switch (baud)
    {
    case      50:	myBaud = B50; break;
    case      75:	myBaud = B75; break;
    case     110:	myBaud = B110; break;
    case     134:	myBaud = B134; break;
    case     150:	myBaud = B150; break;
    case     200:	myBaud = B200; break;
    case     300:	myBaud = B300; break;
    case     600:	myBaud = B600; break;
    case    1200:	myBaud = B1200; break;
    case    1800:	myBaud = B1800; break;
    case    2400:	myBaud = B2400; break;
    case    4800:	myBaud = B4800; break;
    case    9600:	myBaud = B9600; break;
    case   19200:	myBaud = B19200; break;
    case   38400:	myBaud = B38400; break;
    case   57600:	myBaud = B57600; break;
    case  115200:	myBaud = B115200; break;
    case  230400:	myBaud = B230400; break;
    case  460800:	myBaud = B460800; break;
    case  500000:	myBaud = B500000; break;
    case  576000:	myBaud = B576000; break;
    case  921600:	myBaud = B921600; break;
    case 1000000:	myBaud = B1000000; break;
    case 1152000:	myBaud = B1152000; break;
    case 1500000:	myBaud = B1500000; break;
    case 2000000:	myBaud = B2000000; break;
    case 2500000:	myBaud = B2500000; break;
    case 3000000:	myBaud = B3000000; break;
    case 3500000:	myBaud = B3500000; break;
    case 4000000:	myBaud = B4000000; break;
    default:
        return -2;
    }
    if ((fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)
        return -1;
    fcntl(fd, F_SETFL, O_RDWR);
    // Get and modify current options:
    tcgetattr(fd, &options);
    cfmakeraw(&options);
    cfsetispeed(&options, myBaud);
    cfsetospeed(&options, myBaud);
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_oflag &= ~OPOST;
    options.c_cc[VMIN] = 0;
    options.c_cc[VTIME] = 100;	// Ten seconds (100 deciseconds)
    tcsetattr(fd, TCSANOW, &options);
    ioctl(fd, TIOCMGET, &status);
    status |= TIOCM_DTR;
    status |= TIOCM_RTS;
    ioctl(fd, TIOCMSET, &status);
    usleep(10000);	// 10mS
    return fd;
}
void serialSetAttr(int fd, uint8_t DataBits = '8', uint8_t Parity = 'N', uint8_t StopBits = '2')
{
    struct termios options = { 0 };
    tcgetattr(fd, &options);   // Read current options
    // 启动接收器,能够从串口中读取输入数据
    options.c_cflag |= CLOCAL;
    options.c_cflag |= CREAD;
    options.c_cflag &= ~CRTSCTS;  //禁用硬件流控
    options.c_cflag &= ~CSIZE;  // Mask out size
    options.c_cflag |= CS8;     // Or in 8-bits
    options.c_cflag &= ~(PARENB | INPCK);  // Disable Parity - even by default
    options.c_cflag |= CSTOPB;     // Stop bits
    // 设置数据位
    switch (DataBits)
    {
    case '5': options.c_cflag |= CS5; break;
    case '6': options.c_cflag |= CS6; break;
    case '7': options.c_cflag |= CS7; break;
    case '8': options.c_cflag |= CS8; break;
    default: options.c_cflag |= CS8; break;//默认数据位为8
    }
    // 设置校验方式
    switch (Parity)
    {
        // 无校验
    case 'n':
    case 'N':
        options.c_cflag &= ~PARENB;
        options.c_iflag &= ~INPCK;
        break;
        // 偶校验
    case 'e':
    case 'E':
        options.c_cflag |= PARENB;
        options.c_cflag &= ~PARODD;
        options.c_iflag |= INPCK;
        break;
        // 奇校验
    case 'o':
    case 'O':
        options.c_cflag |= PARENB;
        options.c_cflag |= PARODD;
        options.c_iflag |= INPCK;
        // 设置为空格
    case 's':
    case 'S':
        options.c_cflag &= ~PARENB;
        options.c_cflag &= ~CSTOPB;
        // 默认无校验
    default:
        options.c_cflag &= ~PARENB;
        options.c_iflag &= ~INPCK;
        break;
    }
    // 设置停止位
    switch (StopBits)
    {
    case '1': options.c_cflag &= ~CSTOPB; break;
    case '2': options.c_cflag |= CSTOPB; break;
    default: options.c_cflag &= ~CSTOPB; break;
    }
    tcflush(fd, TCIFLUSH);//handle unrecevie char
    tcsetattr(fd, TCSANOW, &options);   // Set new options
}
std::vector<uint8_t> ToFrame(const std::vector<uint8_t>& vInData)
{
    uint16_t crc = 0x0000;
    std::vector<uint8_t> frame(vInData.begin(), vInData.end());
    frame.at(1) = frame.size();
    for (auto i = 0; i < frame.size() - 2; i++)
    {
        crc += frame.at(i);
    }
    frame.at(frame.size() - 2) = ((uint8_t*)&crc)[0];
    frame.at(frame.size() - 1) = ((uint8_t*)&crc)[1];
    return frame;
}
void serialSend(int fd, const std::vector<uint8_t>& data/* = {}*/)
{
    int nLen = 0;
    auto vData = ToFrame(data);
    vData.insert(vData.begin(), 0x00);
    serialSetBaud2(fd, 19200);
    nLen = write(fd, vData.data(), vData.size());
    serialSetBaud2(fd, 250000);
}
int test()
{
    int fd = 0;
    // gpio 使用硬件串口
    if ((fd = serialOpen("/dev/ttyAMA0", 115200)) < 0)
    {
        printf("serialOpen error(%d)\n", errno);
        return (-1);
    }
    //设置为非阻塞模式
    //fcntl(fd, F_SETFL, O_NONBLOCK);
    serialSetAttr(fd);
    serialSetBaud2(fd, 250000);
    std::thread([&]()
        {
            while (true) {
                int result;
                if (ioctl(fd, FIONREAD, &result) == -1 || result == 0)
                {
                    usleep(1000 * 50);
                    continue;
                }
                unsigned char buffer[1024] = { 0 };
                int ret = read(fd, buffer, sizeof(buffer));
                if (ret > 0) {
                    printf("read:");
                    //依次将读取到的数据输出到日志
                    for (int i = 0; i < ret; ++i)
                        printf(" %02x", buffer[i]);
                    ////当收到数据时,再将收到的数据原样发送
                    //int n = write(fd, buffer, ret);
                    //if (n != ret)
                    //    printf("send fail!\n");
                    ////当收到0xFF时,跳出循环
                    //if (buffer[0] == 0xFF)
                    //    break;
                    continue;
                }
                else {
                    //没收到数据时,休眠50ms,防止过度消耗cpu
                    usleep(1000 * 50);
                }
            }
        }
    ).detach();
    while (true)
    {
        getchar();
        {
            serialSend(fd, { 0x80, 0x00, 0x06, 0xD0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
        }
    }
    close(fd);
    return 0;
}
int main(int argc, char ** argv)
{
	std::cout << "Hello CMake." << std::endl;
    test();
	return 0;
}

配置/boot/config.txt

[all]
usb_max_current_enable=1
dtoverlay=uart0,ctsrts
#dtoverlay=uart0-pi5,ctsrts


×
打赏作者
最新回复 (0)
查看全部
全部楼主
返回