jetson nano 实现串口的字节输出

实现jetosn nano的字节输出,但是存在一定的问题

主要为在制作数据包的过程中,我遇到了当输出字节为0x0a的情况下串口会连续输出0x0d 0x0a

这时候需要在串口部分进行一定的配置防止自动换行的输出

   /*防止自动换行*/
    opt.c_oflag &= ~OPOST;     // 禁用输出处理标志,防止自动转换换行符

感谢博主Jetson Nano 入坑之路 ---- (10)C/C++语言读写UART或USB串口数据_jetson nano用什么语言编程-优快云博客

//hpp文件

#ifndef USART_SERIAL_HPP
#define USART_SERIAL_HPP

// 函数声明部分
int open_port(int com_port);
int set_uart_config(int fd, int baud_rate, int data_bits, char parity, int stop_bits);
// unsigned char return_flag = 0;  //反转标志位
// int cmd=0;                      //控制命令位
void control_led(int UART_fd,int cmd);

#endif
//cpp 文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <iconv.h>
#include <string>
#include <iostream>
 
#include <unistd.h>  // usleep 函数需要包含这个头文件
#include "usart_serial.hpp"



// // 使用实例
// int main()
// {   

//     while(1){



    
//         // begin::第一步,串口初始化
//         int UART_fd = open_port(0);
//         if (set_uart_config(UART_fd, 115200, 8, 'N', 1) < 0)
//         {
//             perror("set_com_config");
//             exit(1);
//         }
//         // end::串口初始化
        
//         // begin::第二步,读下位机上发的一行数据
//         char str[128];
//         char buff[1];
//         int len = 0;

//         if(return_flag==0)
//         {
//             cmd = 10&0xff;
//             return_flag=1;
//         }
//         else{
//             cmd = 11&0xff;
//             return_flag=0;
//         }
//         unsigned char data_to_send[] = {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,cmd,0x0D,0x0A};  // 8进制字节
//         int send_len = sizeof(data_to_send) / sizeof(data_to_send[0]);
//         usleep(1000000);  // 延迟微秒(1000000微秒=1秒)


//         write(UART_fd, data_to_send, send_len);  // 发送数据


//     }

//     return 0;
// }
 
/*
* 打开串口
*/
int open_port(int com_port)
{
    int fd;
    /* 使用普通串口 */
    // TODO::在此处添加串口列表
    const char* dev[] = { "/dev/ttyTHS1", "/dev/ttyUSB0" };
 
    //O_NDELAY 同 O_NONBLOCK。
    fd = open(dev[com_port], O_RDWR | O_NOCTTY);
    if (fd < 0)
    {
        perror("open serial port");
        return(-1);
    }
 
    //恢复串口为阻塞状态 
    //非阻塞:fcntl(fd,F_SETFL,FNDELAY)  
    //阻塞:fcntl(fd,F_SETFL,0) 
    if (fcntl(fd, F_SETFL, 0) < 0)
    {
        perror("fcntl F_SETFL\n");
    }
    /*测试是否为终端设备*/
    if (isatty(STDIN_FILENO) == 0)
    {
        perror("standard input is not a terminal device");
    }
 
    return fd;
}
 
/*
* 串口设置
*/
int set_uart_config(int fd, int baud_rate, int data_bits, char parity, int stop_bits)
{
    struct termios opt;
    int speed;
    if (tcgetattr(fd, &opt) != 0)
    {
        perror("tcgetattr");
        return -1;
    }
 
    /*设置波特率*/
    switch (baud_rate)
    {
    case 2400:  speed = B2400;  break;
    case 4800:  speed = B4800;  break;
    case 9600:  speed = B9600;  break;
    case 19200: speed = B19200; break;
    case 38400: speed = B38400; break;
    default:    speed = B115200; break;
    }
    cfsetispeed(&opt, speed);
    cfsetospeed(&opt, speed);
    tcsetattr(fd, TCSANOW, &opt);
 
    opt.c_cflag &= ~CSIZE;
 
    /*设置数据位*/
    switch (data_bits)
    {
    case 7: {opt.c_cflag |= CS7; }break;//7个数据位  
    default: {opt.c_cflag |= CS8; }break;//8个数据位 
    }
 
    /*设置奇偶校验位*/
    switch (parity) //N
    {
    case 'n':case 'N':
    {
        opt.c_cflag &= ~PARENB;//校验位使能     
        opt.c_iflag &= ~INPCK; //奇偶校验使能  
    }break;
    case 'o':case 'O':
    {
        opt.c_cflag |= (PARODD | PARENB);//PARODD使用奇校验而不使用偶校验 
        opt.c_iflag |= INPCK;
    }break;
    case 'e':case 'E':
    {
        opt.c_cflag |= PARENB;
        opt.c_cflag &= ~PARODD;
        opt.c_iflag |= INPCK;
    }break;
    case 's':case 'S': /*as no parity*/
    {
        opt.c_cflag &= ~PARENB;
        opt.c_cflag &= ~CSTOPB;
    }break;
    default:
    {
        opt.c_cflag &= ~PARENB;//校验位使能     
        opt.c_iflag &= ~INPCK; //奇偶校验使能          	
    }break;
    }
 
    /*设置停止位*/
    switch (stop_bits)
    {
    case 1: {opt.c_cflag &= ~CSTOPB; } break;
    case 2: {opt.c_cflag |= CSTOPB; }   break;
    default: {opt.c_cflag &= ~CSTOPB; } break;
    }
 
    /*处理未接收字符*/
    tcflush(fd, TCIFLUSH);
 
    /*设置等待时间和最小接收字符*/
    opt.c_cc[VTIME] = 1000;
    opt.c_cc[VMIN] = 0;
 
    /*关闭串口回显*/
    opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | NOFLSH);
 
    /*禁止将输入中的回车翻译为新行 (除非设置了 IGNCR)*/
    opt.c_iflag &= ~ICRNL;
    /*禁止将所有接收的字符裁减为7比特*/
    opt.c_iflag &= ~ISTRIP;
    /*防止自动换行*/
    opt.c_oflag &= ~OPOST;     // 禁用输出处理标志,防止自动转换换行符
    /*激活新配置*/
    if ((tcsetattr(fd, TCSANOW, &opt)) != 0)
    {
        perror("tcsetattr");
        return -1;
    }
 
    return 0;
}

void control_led(int UART_fd,int cmd)
{   
    cmd = cmd&0xff; //转化为8进制字节
    unsigned char data_to_send[] = {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,cmd,0x0D,0x0A};  // 8进制字节
    int send_len = sizeof(data_to_send) / sizeof(data_to_send[0]);
    // usleep(1000000);  // 延迟微秒(1000000微秒=1秒)
    write(UART_fd, data_to_send, send_len);  // 发送数据

}
### 使用 C++ 在 Jetson Nano 上进行串口通信 #### 安装必要的库文件 为了能够在 Jetson Nano 上利用 C++ 实现串口通信,首先需要安装合适的库来支持这一功能。对于 Jetson Nano 而言,可以考虑使用由 NVIDIA 提供并维护的 `Jetson.GPIO` 库的 C++ 版本[^1]。尽管该库主要针对 GPIO 操作设计,但在其基础上也可能包含了对串口的支持或是能够作为构建自定义解决方案的基础。 然而,更直接的方式可能是寻找专门用于处理 Linux 下串口编程的第三方库或依赖于标准 POSIX API 来实现所需的功能。由于没有特定提及适用于 Jetson Nano 的专用 C++ 串口库,因此推荐采用基于 POSIX 的方法来进行开发。 #### 初始化串口设备 当准备就绪后,可以通过打开指定路径下的 TTY 设备节点(如 `/dev/ttyTHS1` 或者 USB 类型的 `/dev/ttyUSB0`),设置波特率、校验位等参数完成初始化工作: ```cpp #include <fcntl.h> /* File Control Definitions */ #include <termios.h> /* POSIX Terminal Control Definitions */ #include <unistd.h> /* UNIX Standard Definitions */ // 打开串口端口 int open_serial_port(const char *portname){ int fd = open(portname, O_RDWR | O_NOCTTY); if (fd == -1) { perror("Failed to open serial port"); return -1; } struct termios tty; memset(&tty, 0, sizeof(tty)); if(tcgetattr(fd, &tty) != 0){ perror("Error from tcgetattr"); close(fd); return -1; } cfsetospeed(&tty, B9600); // 设置输出速度为 9600 波特率 cfsetispeed(&tty, B9600); // 设置输入速度为 9600 波特率 tty.c_cflag |= (CLOCAL | CREAD); // 启用接收器 tty.c_cflag &= ~PARENB; // 关闭奇偶校验 tty.c_cflag &= ~CSTOPB; // 单停止位 tty.c_cflag &= ~CSIZE; // 清除字符大小掩码 tty.c_cflag |= CS8; // 选择 8 位字符长度 tty.c_lflag &= ~(ICANON | ECHO | ECHONL | ISIG); // 原始模式 tty.c_oflag &= ~OPOST; if(tcsetattr(fd, TCSANOW, &tty) != 0){ perror("tcsetattr failed"); close(fd); return -1; } return fd; } ``` 此代码片段展示了如何通过调用系统函数配置串口属性,并返回已配置好的文件描述符以便后续操作。 #### 数据发送与接收 一旦成功打开了目标串口并且完成了相应的设定之后,就可以开始执行实际的数据传输任务了。下面给出了一种简单的写入单个字节串口以及从串口中读取数据的方法示例: ```cpp void write_to_serial(int fd, unsigned char byte){ ssize_t n_written = write(fd, &byte, 1); if(n_written != 1){ perror("Write error on serial port"); }else{ printf("Sent %d as ASCII code\n", byte); } } unsigned char read_from_serial(int fd){ unsigned char buffer; ssize_t bytes_read = read(fd, &buffer, 1); if(bytes_read == -1){ perror("Read error on serial port"); return '\0'; } else if(bytes_read == 0){ fprintf(stderr,"End of file encountered while reading.\n"); return '\0'; } else { printf("Received character '%c' with value %u\n", buffer, buffer); return buffer; } } ``` 上述两个辅助函数分别实现了向串口发送一个字节和尝试从中获取一字节信息的能力。值得注意的是,在真实的应用场景下可能还需要加入更多的错误检测逻辑以及其他高级特性比如超时控制等等。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诶我就不告诉你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值