linux下串口应用开发

2023-05-16

为什么80%的码农都做不了架构师?>>>   hot3.png

       据通信的基本方式可分为并行通信与串行通信两种。
· 并行通信是指利用多条数据传输线将一个资料的各位同时传送。它的特点是传输速度
快,适用于短距离通信,但要求传输速度较高的应用场合。
· 串行通信是指利用一条传输线将资料一位位地顺序传送。特点是通信线路简单,利用
简单的线缆就可实现通信,降低成本,适用于远距离通信,但传输速度慢的应用场合。
串口设置详解
本节主要讲解设置串口的主要方法。
如前所述,设置串口中最基本的包括波特率设置,校验位和停止位设置。串口的设置主
要是设置struct termios结构体的各成员值,如下所示:
#include
struct termio
{     
      unsigned short c_iflag; /* 输入模式标志 */
      unsigned short c_oflag; /* 输出模式标志 */
      unsigned short c_cflag; /* 控制模式标志*/
      unsigned short c_lflag; /*本地模式标志 */
      unsigned char c_line; /* line discipline */
      unsigned char c_cc[NCC]; /* control characters */
};
在这个结构中最为重要的是c_cflag,通过对它的赋值,用户可以设置波特率、字符大小、
数据位、停止位、奇偶校验位和硬件流控等。另外c_iflag 和c_cc 也是比较常用的标志。在
此主要对这3 个成员进行详细说明。
                 c_cflag支持的常量名称
CBAUD        波特率的位掩码
B0           0波特率(放弃DTR)
B1800        1800波特率
B2400        2400波特率
B4800        4800波特率
B9600        9600波特率
B19200       19200波特率
B38400       38400波特率
B57600       57600波特率
B115200      115200波特率
EXTA         外部时钟率
EXTB         外部时钟率
CSIZE        数据位的位掩码
CS5          5个数据位
CS6          6个数据位
CS7          7个数据位
CS8          8个数据位
CSTOPB       2个停止位(不设则是1个停止位)
CREAD        接收使能
PARENB       校验位使能
PARODD       使用奇校验而不使用偶校验
HUPCL        最后关闭时挂线(放弃DTR)
CLOCAL       本地连接(不改变端口所有者)
LOBLK        块作业控制输出
CNET_CTSRTS  硬件流控制使能

      c_iflag支持的常量名称
INPCK        奇偶校验使能
IGNPAR       忽略奇偶校验错误
PARMRK       奇偶校验错误掩码
ISTRIP       除去奇偶校验位
IXON         启动出口硬件流控
IXOFF        启动入口软件流控
IXANY        允许字符重新启动流控
IGNBRK       忽略中断情况
BRKINT       当发生中断时发送SIGINT信号
INLCR        将NL映射到CR
IGNCR        忽略CR
ICRNL        将CR映射到NL
IUCLC        将高位情况映射到低位情况
IMAXBEL      当输入太长时回复ECHO
      c_cc 支持的常量名称
VINTR     中断控制,对应键为CTRL+C
VQUIT     退出操作,对应键为CRTL+Z
VERASE    删除操作,对应键为Backspace(BS)
VKILL     删除行,对应键为CTRL+U
VEOF      位于文件结尾,对应键为CTRL+D
VEOL      位于行尾,对应键为Carriage return(CR)
VEOL2     位于第二行尾,对应键为Line feed(LF)
VMIN      指定了最少读取的字符数
VTIME     指定了读取每个字符的等待时间

串口控制函数
Tcgetattr         取属性(termios结构)
Tcsetattr         设置属性(termios结构)
cfgetispeed     得到输入速度
Cfgetospeed           得到输出速度
Cfsetispeed            设置输入速度
Cfsetospeed           设置输出速度
Tcdrain           等待所有输出都被传输
tcflow           挂起传输或接收
tcflush           刷清未决输入和/或输出
Tcsendbreak           送BREAK字符
tcgetpgrp              得到前台进程组ID
tcsetpgrp               设置前台进程组ID

      [color=#ff0000]完整的串口配置模板,实用!把常用的选项在函数里面列出,可大大方便用户的调试使用[/color]

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
    struct termios newtio,oldtio;
    /*保存测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息*/
    if ( tcgetattr( fd,&oldtio) != 0)
    {
        perror("SetupSerial 1");
         return -1;
     }
    bzero( &newtio, sizeof( newtio ) );
    /*步骤一,设置字符大小*/
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;
    /*设置停止位*/
    switch( nBits )
    {
        case 7:
            newtio.c_cflag |= CS7;
            break;
        case 8:
            newtio.c_cflag |= CS8;
            break;
    }
/*设置奇偶校验位*/
    switch( nEvent )
    {
        case 'O': //奇数
            newtio.c_cflag |= PARENB;
            newtio.c_cflag |= PARODD;
            newtio.c_iflag |= (INPCK | ISTRIP);
        break;
        case 'E': //偶数
            newtio.c_iflag |= (INPCK | ISTRIP);
            newtio.c_cflag |= PARENB;
            newtio.c_cflag &= ~PARODD;
        break;
            case 'N': //无奇偶校验位
            newtio.c_cflag &= ~PARENB;
        break;
    }
    /*设置波特率*/
    switch( nSpeed )
    {
        case 2400:
            cfsetispeed(&newtio, B2400);
            cfsetospeed(&newtio, B2400);
        break;
        case 4800:
            cfsetispeed(&newtio, B4800);
            cfsetospeed(&newtio, B4800);
        break;
        case 9600:
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
        break;
        case 115200:
            cfsetispeed(&newtio, B115200);
            cfsetospeed(&newtio, B115200);
        break;
        case 460800:
            cfsetispeed(&newtio, B460800);
            cfsetospeed(&newtio, B460800);
        break;
        default:
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
        break;
    }
    /*设置停止位*/
    if( nStop == 1 )
        newtio.c_cflag &= ~CSTOPB;
    else if ( nStop == 2 )
        newtio.c_cflag |= CSTOPB;
    /*设置等待时间和最小接收字符*/
    newtio.c_cc[VTIME] = 0;
    newtio.c_cc[VMIN] = 0;
    /*处理未接收字符*/
    tcflush(fd,TCIFLUSH);
    /*激活新配置*/
    if((tcsetattr(fd,TCSANOW,&newtio))!=0)
    {
        perror("com set error");
        return -1;
    }
    printf("set done!\n");
    return 0;
}
           
           
           
           
           

[b]串口使用详解[/b]
在配置完串口的相关属性后,就可对串口进行打开,读写操作了。其使用方式与文件操作一样,区别在于串口是一个终端设备。

[b]打开串口[/b]
fd = open( "/dev/ttyS0", O_RDWR|O_NOCTTY|O_NDELAY);

   Open函数中除普通参数外,另有两个参数O_NOCTTY和O_NDELAY。
   O_NOCTTY: 通知linix系统,这个程序不会成为这个端口的控制终端。
   O_NDELAY: 通知linux系统不关心DCD信号线所处的状态(端口的另一端是否激活或者停止)。
然后,恢复串口的状态为阻塞状态,用于等待串口数据的读入。用fcntl函数:
       fcntl(fd, F_SETFL, 0);

   接着,测试打开的文件描述府是否引用一个终端设备,以进一步确认串口是否正确打开。
       isatty(STDIN_FILENO);
串口的读写与普通文件一样,使用read,write函数。
       read(fd,buff,8);
       write(fd,buff,8);
实例


#i nclude stdio.h>
#i nclude string.h>
#i nclude sys/types.h>
#i nclude errno.h>
#i nclude sys/stat.h>
#i nclude fcntl.h>
#i nclude unistd.h>
#i nclude termios.h>
#i nclude stdlib.h>
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
    struct termios newtio,oldtio;
    if ( tcgetattr( fd,&oldtio) != 0) {
        perror("SetupSerial 1");
        return -1;
    }
    bzero( &newtio, sizeof( newtio ) );
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;
    switch( nBits )
    {
    case 7:
        newtio.c_cflag |= CS7;
        break;
    case 8:
        newtio.c_cflag |= CS8;
        break;
    }
    switch( nEvent )
    {
    case 'O':
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);
        break;
    case 'E':
        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        break;
    case 'N':
        newtio.c_cflag &= ~PARENB;
        break;
    }
switch( nSpeed )
    {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
        cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    default:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }
    if( nStop == 1 )
        newtio.c_cflag &= ~CSTOPB;
    else if ( nStop == 2 )
    newtio.c_cflag |= CSTOPB;
    newtio.c_cc[VTIME] = 0;
    newtio.c_cc[VMIN] = 0;
    tcflush(fd,TCIFLUSH);
    if((tcsetattr(fd,TCSANOW,&newtio))!=0)
    {
        perror("com set error");
        return -1;
    }
    printf("set done!\n");
    return 0;
}
int open_port(int fd,int comport)
{
    char *dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"};
    long vdisable;
    if (comport==1)
    {    fd = open( "/dev/ttyS0", O_RDWR|O_NOCTTY|O_NDELAY);
        if (-1 == fd){
            perror("Can't Open Serial Port");
            return(-1);
        }
        else
            printf("open ttyS0 .....\n");
    }
    else if(comport==2)
    {    fd = open( "/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY);
        if (-1 == fd){
            perror("Can't Open Serial Port");
            return(-1);
        }
        else
            printf("open ttyS1 .....\n");
    }
    else if (comport==3)
    {
        fd = open( "/dev/ttyS2", O_RDWR|O_NOCTTY|O_NDELAY);
        if (-1 == fd){
            perror("Can't Open Serial Port");
            return(-1);
        }
        else
            printf("open ttyS2 .....\n");
    }
    if(fcntl(fd, F_SETFL, 0)0)
        printf("fcntl failed!\n");
    else
        printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
    if(isatty(STDIN_FILENO)==0)
        printf("standard input is not a terminal device\n");
    else
        printf("isatty success!\n");
    printf("fd-open=%d\n",fd);
    return fd;
}
int main(void)
{
    int fd;
    int nread,i;
    char buff[]="Hello\n";
    if((fd=open_port(fd,1))0){
        perror("open_port error");
        return;
    }
    if((i=set_opt(fd,115200,8,'N',1))0){
        perror("set_opt error");
        return;
    }
    printf("fd=%d\n",fd);
//    fd=3;
    nread=read(fd,buff,8);
    printf("nread=%d,%s\n",nread,buff);
    close(fd);
    return;
 
}

转载于:https://my.oschina.net/jtihj/blog/1969

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux下串口应用开发 的相关文章

随机推荐

  • 材料研究方法

    编程是非常有意思的 xff0c 可是作为材料人 xff0c 学好材料才是比较重要的事情 xff0c 下面记录一些知识点 光学透镜的成像原理 光的折射 光在均匀介质中沿直线传播 在不同介质中光的传播速度不同 当光从一种介质传播到另一种介质中去
  • [微信小程序系列] 动画案例之圆点沿着圆圈运动

    作者 xff1a 滴滴公共前端团队 Tawnia 滴滴作为第一批的小程序开发者 xff0c 我们也大量地用到了动画 xff0c 积累了一些经验 xff0c 由于市面上的小程序动画案例很少 xff0c 我们也分享一部分我们做过的案例 xff1
  • Vue Iview Tree插件的无限层

    Iview lt template gt lt Tree data 61 34 baseData 34 show checkbox multiple gt lt Tree gt lt template gt lt script gt exp
  • React Component vs React Element

    React Component vs React Element 有这样的一个问题 xff1a 方法定义 function add x y return x 43 y 方法调用 add 1 2 组件定义 class Icon extends
  • 手把手学STM32(一)

    手把手学STM32 一 构建工程 这篇文章详细的介绍编写第一个固件工程 xff08 F103ZET6版本的 xff09 文档里的操作部分我使用了黄色背景色标出 xff0c 如觉麻烦 xff0c 可直接参考黄色部分 资料下载链接 xff1a
  • Linux下查看在线用户及用户进程

    可采用命令 xff1a w who last users finger 需yum安装 法一 xff1a root 64 test1 who root tty1 2015 08 19 23 15 lxh pts 0 2015 08 20 00
  • 手动制作一个QQ群机器人

    为什么80 的码农都做不了架构师 xff1f gt gt gt 最近在群里面一个朋友在玩机器人 我觉得蛮有意思的所以查了下资料搞了一个机器人 这里只是借助软件实现机器人 后面会自己去手写一个机器人 1 进入图灵的官网 http www tu
  • X-Content-Type-Options: nosniff

    如果服务器发送响应头 34 X Content Type Options nosniff 34 xff0c 则 script 和 styleSheet 元素会拒绝包含错误的 MIME 类型的响应 这是一种安全功能 xff0c 有助于防止基于
  • 过期域名

    tonha sx cn wqk410 sx cn liyongfu2005 sx cn id 3682362 sx cn dtsgfljdsbyxzrgs sx cn id 1184965 sx cn jinlei001 sx cn lin
  • CSS之 background-color: rgba(255,0,0,opacity number)

    一 xff1a backgrounde color xff1a rgba xff08 xff09 设置背景色的时候 xff0c 可以调节背景色的透明度 xff0c 注意是背景哦 xff0c 所以不会存在遮罩问题 见图 test cover
  • PrestaShop 网站后台配置(三)

    转载请注明出处 xff1a http www cnblogs com zhong dev p 4942957 html 网店版本 v1 6 这一篇文章主要介绍 前台显示模块 的调整 1 xff1a top banner xff08 首页横幅
  • 正则表达式

    Date 2019 07 03 Author Sun 本节目的 xff1a xff08 1 xff09 掌握正则表达式和re模块使用 xff08 2 xff09 python操作正则表达式 xff0c 匹配贪婪和非贪婪模式使用 xff08
  • asp.net mvc 部署时出现错误 没有对“C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files”的写访问权限...

    在IIS中 发布程序一个ASP NET程序 xff0c 通过IE访问报如下错误 xff1a 当前标识 NT AUTHORITY NETWORK SERVICE 没有对 C WINDOWS Microsoft NET Framework v2
  • 事件的好处~实现对修改的封闭,对扩展的开放

    事件是这样的 xff0c 我觉得用事件来做这事比较好 xff0c 它很好的遵循了 开闭原则 xff0c 当然这并不是最重要的 xff0c 最重要的应该是它更符合程序开发的原则 场合 xff1a 一个订单处理问题 xff0c 一个订单的产生可
  • 中文显示不全?docker+ firefox

    2019独角兽企业重金招聘Python工程师标准 gt gt gt sudo apt get install ttf wqy microhei ttf wqy microhei ttf wqy zenhei kde l10n zhcn xf
  • FreeRTOS 移植,问题总结

    一直没亲手移植过FreeRTOS xff0c 心血来潮移植了下最新版的FreeRTOSv202104 00 过程不赘述 xff0c 可以参考 https www cnblogs com iot dev p 11681067 html xff
  • Linux常见的进程调度算法

    进程调度 xff1a 在操作系统中调度是指一种资源分配 调度算法是指 根据系统的资源分配策略所规定的资源分配算法 操作系统管理了系统的有限资源 xff0c 当有多个进程 或多个进程发出的请求 要使用这些资源时 xff0c 因为资源的有限性
  • 无人机行业应用分类有哪些?

    创客的集结号已吹响 随着无人机技术的发展 xff0c 细分市场领域的需求增长 xff0c 无人机的应用正展现出越来越丰富的可能性 航拍 植保 xff0c 替代电力工人巡线等等 xff0c 无人机的应用越来越广泛 xff0c 正推动着各个领域
  • ROS初级教程 cmake cmakelist.txt 的编写教程

    有很多 的时候我们使用别人的程序包 然后添加东西的时候缺少什么东西 xff0c 会使程序编译不过去 xff0c 甚至无法运行 xff0c 接下来介绍一下cmakelist txt 的每一行的作用 为了以后添加和修改方便 2 整体结构和订购
  • linux下串口应用开发

    为什么80 的码农都做不了架构师 xff1f gt gt gt 据通信的基本方式可分为并行通信与串行通信两种 并行通信是指利用多条数据传输线将一个资料的各位同时传送 它的特点是传输速度 快 xff0c 适用于短距离通信 xff0c 但要求传