zoukankan      html  css  js  c++  java
  • linux串口编程(c)

    //linux c: 串口设置
    //串口操作无非以下几个:
    //1 打开                       
    //2 设置串口属性
    //3 read write


    //struct termios能够表明一切串口属性,这里不详细说明.
    //详见 【Linux公开课】串口属性设置  http://mp.weixin.qq.com/s?src=3&timestamp=1467340907&ver=1&signature=2hx5roS7br3*GBJVmZQ0Om2X3KMAONfWdT1SSPB2fMDoc68n3k6nqofouSMF3UWy8HMv58IMyIT4XiugpDSQVEPSubo8oSDt*BcWwUVgdqvSUypVfgz8arph5*9QxamrlcafmoPA9fk42FwIjITW6A==
    //以及 Linux应用程序开发 http://hilinux.com/man/linuxdev/ch09.html, 这篇文章对串口结构体做了比较详细的说明

    struct termios {
        tcflag_t c_iflag; /* 输入参数 */
        tcflag_t c_oflag; /* 输出参数 */
        tcflag_t c_cflag; /* 控制参数*/
        tcflag_t c_ispeed; /* 输入波特率 */
        tcflag_t c_ospeed; /* 输出波特率 */
        cc_t c_line; /* 线控制 */
        cc_t c_cc[NCCS]; /* 控制字符*/
    };
                           
    //xereno的串口代码是太繁乱,只做对比确认用.
    //下面摘抄一段网络代码进行分析:        
    //串口操作示例
        #include <stdio.h>
        #include <stdlib.h>
        #include <unistd.h>
        #include <fcntl.h>
        #include <asm/termios.h>   // 在linux x86下面用#include <termios.h>

        #include "serial.h"

        #define DEV_NAME  "/dev/ttyS1" //同自己的驱动写的名字
        
        int set_port_attr (int fd,int  baudrate, int  databit, const char *stopbit, char parity, int vtime,int vmin );
        static void set_baudrate (struct termios *opt, unsigned int baudrate);
        static void set_data_bit (struct termios *opt, unsigned int databit);
        static void set_stopbit (struct termios *opt, const char *stopbit);
        static void set_parity (struct termios *opt, char parity);
        
        int main (int argc, char *argv[])
        {
            int fd;
            int len, i,ret;
            char buf[] = "hello ZLG!";

            fd = open(DEV_NAME, O_RDWR | O_NOCTTY); //如果是在linux x86下面做实验, 这个设备是有问题的, 可不要这一步, 用fd=0直接定位到当前的终端来进行实验.
            if(fd < 0) {
            perror(DEV_NAME);
            return -1;
            }

            ret = set_port_attr (fd, B115200, 8, "1", 'N',150,255 );    /* 115200 8n1                                 */
            if(ret < 0) {
                   printf("set uart arrt faile ");
                   exit(-1);
            }

            len = write(fd, buf, sizeof(buf));                            /* 向串口发送字符串                            */
            if (len < 0) {
                   printf("write data error ");
                   return -1;
            }
            
            len = read(fd, buf, sizeof(buf));                            /* 在串口读取字符串                            */
            if (len < 0) {
                printf("read error ");
                return -1;
            }

            printf("%s ", buf);                                      /* 打印在串口读取的字符串       */

            return(0);
        }

    //自定义终端属性设置函数具体定义如下
    //设置终端属性的时候注意,有的项目是通过与&,而有的项目是通过或|. 不要混淆误解.
        int  set_port_attr (int fd,int  baudrate, int  databit, const char *stopbit, char parity, int vtime,int vmin )
        {
            struct termios opt;
            tcgetattr(fd, &opt);       //获取初始设置
            
            set_baudrate(&opt, baudrate);
            set_data_bit(&opt, databit);
            set_parity(&opt, parity);
            set_stopbit(&opt, stopbit);
            
            opt.c_cflag &= ~CRTSCTS;// 不使用硬件流控制
            opt.c_cflag |= CLOCAL | CREAD; //CLOCAL--忽略 modem 控制线,本地连线, 不具数据机控制功能, CREAD--使能接收标志

            /*
            IXON--启用输出的 XON/XOFF 流控制
            IXOFF--启用输入的 XON/XOFF 流控制
            IXANY--允许任何字符来重新开始输出
            IGNCR--忽略输入中的回车
            */
            opt.c_iflag &= ~(IXON | IXOFF | IXANY);
            opt.c_oflag &= ~OPOST; //启用输出处理
            /*
            ICANON--启用标准模式 (canonical mode)。允许使用特殊字符 EOF, EOL,
                    EOL2, ERASE, KILL, LNEXT, REPRINT, STATUS, 和 WERASE,以及按行的缓冲。
            ECHO--回显输入字符
            ECHOE--如果同时设置了 ICANON,字符 ERASE 擦除前一个输入字符,WERASE 擦除前一个词
            ISIG--当接受到字符 INTR, QUIT, SUSP, 或 DSUSP 时,产生相应的信号
            */
            opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
            opt.c_cc[VMIN] = vmin; //设置非规范模式下的超时时长和最小字符数:
            opt.c_cc[VTIME] = vtime; //VTIME与VMIN配合使用,是指限定的传输或等待的最长时间
            
            tcflush (fd, TCIFLUSH);                    /* TCIFLUSH-- update the options and do it NOW */
            return (tcsetattr (fd, TCSANOW, &opt)); /* TCSANOW--改变立即发生 */
        }
        
        //自定义set_baudrate()函数
        //使用set_baudrate()函数设置串口输入/输出波特率为115200的代码为:set_baudrate(&opt, B115200));
        //通常来说,串口的输入和输出波特率都设置为同一个值,如果要分开设置,就要分别调用cfsetispeed , cfsetospeed
            static void set_baudrate (struct termios *opt, unsigned int baudrate)
            {
                 cfsetispeed(opt, baudrate);
                 cfsetospeed(opt, baudrate);
            }
            
        //自定义set_stopbit函数
        //在set_stopbit()函数中,stopbit参数可以取值为:“1”(1位停止位)、“1.5”(1.5位停止位)和“2”(2位停止位)。
            static void set_stopbit (struct termios *opt, const char *stopbit)
            {
                if (0 == strcmp (stopbit, "1")) {
                    opt->c_cflag &= ~CSTOPB;                                                           /* 1位停止位t             */
                } else if (0 == strcmp (stopbit, "1.5")) {
                    opt->c_cflag &= ~CSTOPB;                                                           /* 1.5位停止位            */
                }else if (0 == strcmp (stopbit, "2")) {
                    opt->c_cflag |= CSTOPB;                                                            /* 2 位停止位             */
                }else {
                    opt->c_cflag &= ~CSTOPB;                                                           /* 1 位停止位             */
                }
            }
        
        //set_data_bit函数
        //CSIZE--字符长度掩码。取值为 CS5, CS6, CS7, 或 CS8
            static void set_data_bit (struct termios *opt, unsigned int databit)
            {
                opt->c_cflag &= ~CSIZE;
                switch (databit) {
                case 8:
                    opt->c_cflag |= CS8;
                    break;
                case 7:
                    opt->c_cflag |= CS7;
                    break;
                case 6:
                    opt->c_cflag |= CS6;
                    break;
                case 5:
                    opt->c_cflag |= CS5;
                    break;
                default:
                    opt->c_cflag |= CS8;
            break;
                }
            }
            
        //set_parity函数
        //在set_parity函数中,parity参数可以取值为:‘N’和‘n’(无奇偶校验)、‘E’和‘e’(表示偶校验)、‘O’和‘o’(表示奇校验)。
            static void set_parity (struct termios *opt, char parity)
            {
                switch (parity) {
                case 'N':                                                                                   /* 无校验          */
                case 'n':
                    opt->c_cflag &= ~PARENB;
                    break;
                case 'E':                                                                                   /* 偶校验          */
                case ‘e‘:
                    opt->c_cflag |= PARENB;
                    opt->c_cflag &= ~PARODD;
                    break;
                case 'O':                                                                                   /* 奇校验           */
                case ‘o‘:
                    opt->c_cflag |= PARENB;
                    opt->c_cflag |= ~PARODD;
                    break;
                default:                                                                                    /* 其它选择为无校验 */
                    opt->c_cflag &= ~PARENB;
                    break;
                }
            }

    mcu svn:
    https://123.57.81.221/svn/xida/trunk/mcu/stm32       

  • 相关阅读:
    GridView多行多列合并单元格(指定列合并)
    项目管理知识体系指南PMBOK指南
    作业调度框架 Quartz.NET 2.0 beta 发布
    外语学习有助于大脑发育
    抢书之JS版
    mac 安装python和Django开发环境
    戏谈一道面试题
    —安装时填写注册表
    深入浅出SQL Server Replication第一篇:走近Replication(上)
    IIS寄宿方式的Web地址、BaseAddress和EndPoint Address的关系
  • 原文地址:https://www.cnblogs.com/mylinux/p/5632359.html
Copyright © 2011-2022 走看看