linux下串口控制
/* 本程序符合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下串口控制的更多相关文章
- Linux下串口编程入门
简介: Linux操作系统从一开始就对串行口提供了很好的支持,本文就Linux下的串行口通讯编程进行简单的介绍. 串口简介 串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用.常用 ...
- linux下串口通信与管理
linux下的串口与windows有一些区别,下面将介绍一下linux下串口通信管理 查看是否支持USB串口: #lsmod | grep usbserial 如果没有信息:sudo apt-get ...
- Linux下串口編程遇到的接收数据错误及原因(0x0d,0x11接收错误)
摘要:Linux下串口编程遇到的接收数据错误及原因 来源:https://dotblogs.com.tw/k/2012/07/24/73572 近日在调试串口的时候发现,另一设备向我ARM板的串口发送 ...
- Linux下串口编制【转】
串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用.常用的串口是RS-232-C接口(又称EIA RS-232-C)它是在1970年由美国电子工业协会(EIA)联合贝尔系统.调制解调 ...
- Linux下串口编程【转】
本文转载自:http://blog.csdn.net/w282529350/article/details/7378388 /************声明:本人只是见到这篇文章对我帮助很大才转载的,但 ...
- linux下串口的阻塞和非阻塞操作
有两个可以进行控制串口阻塞性(同时控制read和write):一个是在打开串口的时候,open函数是否带O_NDELAY:第二个是可以在打开串口之后通过fcntl()函数进行控制. 阻塞的定义: 对于 ...
- Linux下串口与工业协议的开发
1.串口通信原理 串口通信定义 串口通信:数据的串行传送方式.串口通信可分为同步通信与异步通信. 同步通信:按照软件识别同步字符来实现数据的发送和接收. 将许多字符组成一个信息组进行发送 要求发送时钟 ...
- Linux下串口ttyS2,ttyS3不能用的问题解决办法
PC104,Xlinux下,突然发现串口3,4不能用... 以为是硬件的问题,换成wince后,3,4工作正常,排除电路问题 在linux下查看dmesg: serial8250: ttyS0 at ...
- Linux 下实现控制屏幕显示信息和光标的状态
//display.h /************************************************************* FileName : display.h File ...
随机推荐
- 用css实现云状提示框
经常会用到云状提示框,如图: 基本框架是这样,以三角在左侧为例: <div class="container"> <div class="content ...
- zero1--hibernate注解02
- iOS Architecture和Valid architectures
目前ios的指令集有以下几种: 1,armv6,支持的机器iPhone,iPhone2,iPhone3G及对应的iTouch 2,armv7,支持的机器iPhone4,iPhone4S 3,armv7 ...
- dataguard集群搭建
dataguard集群搭建 1. 创建虚拟机 创建一台虚拟机配置如下: 系统Red Hat Enterprise 6(64位).16vCPU.8G内存.两块VM Network类型网卡.三块硬盘分别为 ...
- 分享一下怎么开发一款图片视频类App,秒拍和prisma
第一步,分解短视频App的功能 我们在秒拍官网看到如此描述: [视频拍摄及导入]支持直接拍摄及导入手机本地的视频 [照片电影]照片专属特效,轻松创作照片电影 [MV特效]10余款全新MV特效,让普通视 ...
- mysql -B 恢复与不加
-B 跟--database 意义一样 在默认不指定库时候 连续名称,只有第一个名称为库名,后面的都为表名 而使用 -B 或者 --database 之后 所有的名 都是库名 1 导出单个库时候加了- ...
- javascript设计模式学习之十六——状态模式
一.状态模式的定义 状态模式的关键是区分事务内部和外部的状态,事务内部状态改变往往会带来事务的行为改变. 状态模式中有意思的一点是,一般我们谈到封装,都是优先封装对象的行为,而非对象的状态.但在状态模 ...
- 如何让CRectTracker的m_rect不超出一定的范围,比如screen或者某个document的范围
最近在尝试做一个QQ截图那样的工具,其中一个功能就是要做一个选择框,自然用到了CRectTracker 但是有一个很关键的东西就是,拖拽CRectTracker的时候,不能让CRectTracker“ ...
- Java 杨辉三角的简单实现
package com.lf.trianglenumber; public class Test { public static void main(String[] args) { // 打印的行数 ...
- ARC Rules
To write and compile source code for ARC, you have to take care of a few things. Just by following t ...