/*  本程序符合GPL条约
 *  Beneboy 2003-5-16
*/
#include <stdio.h>              // printf
#include <fcntl.h>              // open
#include <string.h>             // bzero
#include <stdlib.h>             // exit
#include <sys/times.h>          // times
#include <sys/types.h>          // pid_t
#include <termios.h>  //termios, tcgetattr(), tcsetattr()
#include <unistd.h>
#include <sys/ioctl.h>          // ioctl
#include "MyCom.h"

#define TTY_DEV "/dev/ttyS" //端口路径
//接收超时
#define TIMEOUT_SEC(buflen,baud) (buflen*20/baud+2)
#define TIMEOUT_USEC 0

/*******************************************
 * 获得端口名称
********************************************/
char *get_ptty(pportinfo_t pportinfo)
{
 char *ptty;

switch(pportinfo->tty){
  case '0':{
   ptty = TTY_DEV"0";
  }break;
  case '1':{
   ptty = TTY_DEV"1";
  }break;
  case '2':{
   ptty = TTY_DEV"2";
  }break;
 }
 return(ptty);
}

/*******************************************
 * 波特率转化转换函数
********************************************/
int convbaud(unsigned long int baudrate)
{
 switch(baudrate){
  case 2400:
   return B2400;
  case 4800:
   return B4800;
  case 9600:
   return B9600;
  case 19200:
   return B19200;
  case 38400:
   return B38400;
  case 57600:
   return B57600;
  case 115200:
   return B115200;
  default:
   return B9600;
 }
}

/*******************************************
 * Setup comm attr
 * fdcom: 串口文件描述符, pportinfo: 待设置的端口信息s
 *
********************************************/
int PortSet(int fdcom, const pportinfo_t pportinfo)
{
 struct termios termios_old, termios_new;
 int  baudrate, tmp;
 char databit, stopbit, parity, fctl;

bzero(&termios_old, sizeof(termios_old));
 bzero(&termios_new, sizeof(termios_new));
 cfmakeraw(&termios_new);
 tcgetattr(fdcom, &termios_old);   //get the serial port attributions

/*------------设置端口属性----------------*/

//baudrates
 baudrate = convbaud(pportinfo -> baudrate);
 cfsetispeed(&termios_new, baudrate);  //填入串口输入端波特率
 cfsetospeed(&termios_new, baudrate);  //填入串口输出端波特率
 termios_new.c_cflag |= CLOCAL;   //控制模式, 保证程序不会成为端口的占有者
 termios_new.c_cflag |= CREAD;   //控制模式, 使能端口读取输入的数据

// 控制模式, flow control
 fctl = pportinfo-> fctl;
 switch(fctl){
  case '0':{
   termios_new.c_cflag &= ~CRTSCTS;  //no flow control
  }break;
  case '1':{
   termios_new.c_cflag |= CRTSCTS;   //hardware flow control
  }break;
  case '2':{
   termios_new.c_iflag |= IXON | IXOFF |IXANY; //software flow control
  }break;
 }

//控制模式, data bits
 termios_new.c_cflag &= ~CSIZE;  //控制模式, 屏蔽字符大小位
 databit = pportinfo -> databit;
 switch(databit){
  case '5':
   termios_new.c_cflag |= CS5;
  case '6':
   termios_new.c_cflag |= CS6;
  case '7':
   termios_new.c_cflag |= CS7;
  default:
   termios_new.c_cflag |= CS8;
 }

//控制模式 parity check
 parity = pportinfo -> parity;
 switch(parity){
  case '0':{
   termios_new.c_cflag &= ~PARENB;  //no parity check
  }break;
  case '1':{
   termios_new.c_cflag |= PARENB;  //odd check
   termios_new.c_cflag &= ~PARODD;
  }break;
  case '2':{
   termios_new.c_cflag |= PARENB;  //even check
   termios_new.c_cflag |= PARODD;
  }break;
 }

//控制模式, stop bits
 stopbit = pportinfo -> stopbit;
 if(stopbit == '2'){
  termios_new.c_cflag |= CSTOPB; //2 stop bits
 }
 else{
  termios_new.c_cflag &= ~CSTOPB; //1 stop bits
 }

//other attributions default
 termios_new.c_oflag &= ~OPOST;   //输出模式, 原始数据输出

termios_new.c_cc[VMIN]  = 1;   //控制字符, 所要读取字符的最小数量
 termios_new.c_cc[VTIME] = 1;   //控制字符, 读取第一个字符的等待时间,  unit: (1/10)second

tcflush(fdcom, TCIFLUSH);   //溢出的数据可以接收,但不读
 tmp = tcsetattr(fdcom, TCSANOW, &termios_new); //设置新属性, TCSANOW: 所由改变立即生效
 tcgetattr(fdcom, &termios_old);
 return(tmp);
}

/*******************************************
 * Open serial port
 * tty: 端口号 ttyS0, ttyS1, ....
 * 返回值为串口文件描述符
********************************************/
int PortOpen(pportinfo_t pportinfo)
{
 int fdcom; //串口文件描述符
 char *ptty;

ptty = get_ptty(pportinfo);
 //fdcom = open(ptty, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);
 fdcom = open(ptty, O_RDWR | O_NOCTTY | O_NONBLOCK);

return (fdcom);
}

/*******************************************
 * Close serial port
********************************************/
void PortClose(int fdcom)
{
 close(fdcom);
}

/********************************************
 * send data
 * fdcom: 串口描述符, data: 待发送数据, datalen: 数据长度
 * 返回实际发送长度
*********************************************/
int PortSend(int fdcom, char *data, int datalen)
{
 int len = 0;

len = write(fdcom, data, datalen); //实际写入的长度
 if(len == datalen){
  return (len);
 }
 else{
  tcflush(fdcom, TCOFLUSH);
  return -1;
 }
}

/*******************************************
 * receive data
 * 返回实际读入的字节数
 *
********************************************/
int PortRecv(int fdcom, char *data, int datalen, int baudrate)
{
 int readlen, fs_sel;
 fd_set fs_read;
 struct timeval tv_timeout;

FD_ZERO(&fs_read);
 FD_SET(fdcom, &fs_read);
 tv_timeout.tv_sec = TIMEOUT_SEC(datalen, baudrate);
 tv_timeout.tv_usec = TIMEOUT_USEC;

fs_sel = select(fdcom+1, &fs_read, NULL, NULL, &tv_timeout);
 if(fs_sel){
  readlen = read(fdcom, data, datalen);
  return(readlen);
 }
 else{
  return(-1);
 }

return (readlen);
}

//*************************Test*********************************
int main(int argc, char *argv[])
{
 int fdcom, i, SendLen, RecvLen;
 struct termios termios_cur;
 char RecvBuf[256];
        char writeBuf[256];
 portinfo_t portinfo ={
  '0',                          // print prompt after receiving
   9600,                       // baudrate: 9600
   '8',                          // databit: 8
   '0',                          // debug: off
   '0',                          // echo: off
   '2',                          // flow control: software
   '0',                          // default tty: COM1
   '0',                          // parity: none
   '1',                          // stopbit: 1
    0                           // reserved
 };

if(argc != 2){
  printf("Usage: <type 0 -- send 1 -- receive>\n");
  printf("   eg:");
  printf("        MyPort 0");
  exit(-1);
 }

fdcom = PortOpen(&portinfo);
 if(fdcom<0){
  printf("Error: open serial port error.\n");
  exit(1);
 }

PortSet(fdcom, &portinfo);

while(1)
 if(atoi(argv[1]) == 0)
        {
  //send data
  //for(i=0; i<1000; i++)
                {
                        //fgets(writeBuf,256,stdin);
                        scanf("%s",writeBuf);
   SendLen = PortSend(fdcom, writeBuf, strlen(writeBuf));
   if(SendLen>0)
                        {
    //printf("send data %s", writeBuf);
   }
   else
                        {
    printf("Error: send failed.\n");
   }

if(strncmp(writeBuf,"exit",4)==0)
                           break;
   sleep(1);
  }
  //PortClose(fdcom);
 }
 else
       {
  //for(;;)
                {
   RecvLen = PortRecv(fdcom, RecvBuf, 256, portinfo.baudrate);
   if(RecvLen>0)
                        {
    /*for(i=0; i<RecvLen; i++)
                                {
     printf("Receive data No %d is %x.\n", i, RecvBuf[i]);
    }//*/
                                RecvBuf[RecvLen] = '\0';
    printf("read data %s\n",RecvBuf);

if(strncmp(RecvBuf,"exit",4)==0)
                                    break;
   }
   else
                        {
    //printf("Error: receive error.\n");
   }
   sleep(1);
  }
 }
        PortClose(fdcom);
 return 0;
}

linux下串口控制的更多相关文章

  1. Linux下串口编程入门

    简介: Linux操作系统从一开始就对串行口提供了很好的支持,本文就Linux下的串行口通讯编程进行简单的介绍. 串口简介  串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用.常用 ...

  2. linux下串口通信与管理

    linux下的串口与windows有一些区别,下面将介绍一下linux下串口通信管理 查看是否支持USB串口: #lsmod | grep usbserial 如果没有信息:sudo apt-get ...

  3. Linux下串口編程遇到的接收数据错误及原因(0x0d,0x11接收错误)

    摘要:Linux下串口编程遇到的接收数据错误及原因 来源:https://dotblogs.com.tw/k/2012/07/24/73572 近日在调试串口的时候发现,另一设备向我ARM板的串口发送 ...

  4. Linux下串口编制【转】

    串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用.常用的串口是RS-232-C接口(又称EIA RS-232-C)它是在1970年由美国电子工业协会(EIA)联合贝尔系统.调制解调 ...

  5. Linux下串口编程【转】

    本文转载自:http://blog.csdn.net/w282529350/article/details/7378388 /************声明:本人只是见到这篇文章对我帮助很大才转载的,但 ...

  6. linux下串口的阻塞和非阻塞操作

    有两个可以进行控制串口阻塞性(同时控制read和write):一个是在打开串口的时候,open函数是否带O_NDELAY:第二个是可以在打开串口之后通过fcntl()函数进行控制. 阻塞的定义: 对于 ...

  7. Linux下串口与工业协议的开发

    1.串口通信原理 串口通信定义 串口通信:数据的串行传送方式.串口通信可分为同步通信与异步通信. 同步通信:按照软件识别同步字符来实现数据的发送和接收. 将许多字符组成一个信息组进行发送 要求发送时钟 ...

  8. Linux下串口ttyS2,ttyS3不能用的问题解决办法

    PC104,Xlinux下,突然发现串口3,4不能用... 以为是硬件的问题,换成wince后,3,4工作正常,排除电路问题 在linux下查看dmesg: serial8250: ttyS0 at ...

  9. Linux 下实现控制屏幕显示信息和光标的状态

    //display.h /************************************************************* FileName : display.h File ...

随机推荐

  1. Selenium2学习-037-WebUI自动化实战实例-IE浏览器显示比例问题:org.openqa.selenium.remote.SessionNotFoundException: Unexpected error launching Internet Explorer. Browser zoom level was set to 94%. It should be set to 100%

    好久没有写博文了,今天在给部门新人演示 Selenium WebDriver 启动其支持的各种浏览器时,启动 IE 时总是无法打开对应的百度网址,页面如下所示:

  2. js的执行顺序

    js是顺序执行的,但是在一个<script></script>标签中,后面的函数会预加载.如: <script type="text/javascript&qu ...

  3. Finally的执行时机

    有人问下面代码是return先执行,还是finally先执行. int i = 1;try{    return i;}finally{  i = 0;} 很多人都回答是finally先执行,因为他们 ...

  4. zabbix监控MySQL

    通过使用mysql_performance_monitor软件包实现zabbix对mysql的监控. 1.安装依赖软件.yum install perl-File-Which perl-libwww- ...

  5. 对JSP和Servlet性能优化,提升执行效率

    你的J2EE应用是不是运行的很慢?它们能不能承受住不断上升的访问量?本文讲述了开发高性能.高弹性的JSP页面和Servlet的性能优化技术.其意思是建立尽可能快的并能适应数量增长的用户及其请求.在本文 ...

  6. 转 awk中RS,ORS,FS,OFS区别与联系

     今天用到awk ofs 看到一篇不错文章 awk中RS,ORS,FS,OFS区别与联系 张映 发表于 2010-12-02 分类目录: shell 标签:awk, FS, OFS, ORS, RS, ...

  7. Power-BI费用分析

    费用分析主要从财务三大费用入手,剖析费用的结构.用途.占用等情况,从三大费用到明细费用.部门.职员的层层钻取,从而有效地进行费用管理和控制.Power-BI前端展示:图1<ignore_js_o ...

  8. 第三篇 SQL Server安全主体和安全对象

    本篇文章是SQL Server安全系列的第三篇,详细内容请参考原文. 一般来说,你通过给主体分配对象的权限来实现SQL Server上的用户与对象的安全.在这一系列,你会学习在SQL Server实例 ...

  9. 最流行的PHP 代码规范

    “PHP是最好的编程语言” ;-) 那么PHPer习惯使用什么样的代码规范呢?sideeffect.kr通过分析GitHub上托管的开源代码,得出了一些有趣的结果,让我们一起来看看吧. 缩进 空格(7 ...

  10. Windows下MongoDB安装与PHP扩展

    MongoDB是什么就不再累述了,下面只写MongoDB安装与PHP扩展的方法. 一,安装准备 MongoDB 如果网速慢,可以到MongoDB中文社区的百度网盘下载,密码3gun.(根据你的操作系统 ...