有关linux串口通信
来源:互联网 发布:mac如何卸载app 编辑:程序博客网 时间:2024/06/14 12:45
有关linux串口通信
Talk is cheap,show me the code.
COM_Linux.h#ifndef __COM_LINUX_H__#define __COM_LINUX_H__#define MAX_BUF 512 //串口数据缓冲最大字节数#define MIN(A,B) (A<B?A:B)int COM_open(char*);int COM_set(int,int,int,int,char,char);int COM_BufQueSize(int,int*);int COM_recv(int,char*,int);int COM_transmit(int,char*,int);#endif
#include <stdio.h> /*开头两个头文件就不多说了*/#include <stdlib.h>#include <string.h> /*字符串操作会用到*/#include <unistd.h> /*Unix标准函数定义 unix std*/#include <fcntl.h> /*文件控制定义 file control*/#include <termios.h> /*POSIX 终端控制定义*/#include <errno.h> /*错误号定义*/#include <sys/ioctl.h>#include "COM_Linux.h"/****************************************************** * 名称: COM_open * 功能: 打开串口并返回串口设备文件描述 * 传参: fd:文件描述符 port:串口号(ttyS0,ttyUSB0...) * 返回: 正确 fd 错误 -1*******************************************************/int COM_open(char* port) { int fd=-1; fd=open(port,O_RDWR|O_NOCTTY|O_NDELAY); /*open函数代表打开串口设备 * 一般推荐的标志位参数如上述,通过|运算组合 *O_RDWR 以可读写方式打开文件 *O_NOCTTY 表明本程序非串口上的控制终端,不受组合键信号影响 *O_DELAY 表示忽略DCD信号线状态(另一端是否已经链接) *否则open函数会阻塞等待DCD信号,导致程序丢失相应*/ if(-1 == fd){ perror("Unable to Open Uart\n"); return -1; }else{ printf("fd->open=%d\n",fd); } //恢复串口为阻塞状态 if(fcntl(fd,F_SETFL,0)<0){ printf("set flag error!\n"); return -1; }else{ printf("fcntl=%d\n",fcntl(fd,F_SETFL,0)); } return fd;}/******************************************** * 名称: COM_close * 功能: 关闭串口 * 入口参数: fd * 出口参数: 成功 0 错误 -1 * ******************************************/int COM_close(fd){ if(fd<0) return -1; if(close(fd)==-1) return -1; printf("Close Uart\n"); return 0;}/************************************************************ * 名称: COM_set * 功能: 置串口各项参数 * 入口参数: fd * baud 串口速度,即波特率 4800 9600 115200 * data_bit 数据位 一个字节的数据位个数 7、8 * stop_bit 停止位 停止位个数 1、2 * parity 校验类型 N:无校验 O:奇校验ODD E: 偶校验EVEN * flow_ctrl 数据流控制 N:无 S:软件流 H:硬件流 * 出口参数: 正确0,错误-1 * ********************************************************/int COM_set(int fd,int baud,int data_bit,int stop_bit,char parity,char flow_ctrl){ struct termios options; //tcgetattr(fd,&options)得到fd指向对象的相关参数 //保存在termios定义的结构体内 //且可测试配置是否正确,调用成功返回0,失败返回-1 if(tcgetattr(fd,&options)!=0){ perror("Set com error\n"); return -1; } switch(baud){ case 4800: /*c_cflag成员用于描述串口硬件控制 用于波特率 校验 数据位 停止 控制流等 * 所有的都是位操作,通过位运算的与或非关系来设置或清楚相关标志 */ options.c_cflag=B4800; break; case 9600: options.c_cflag=B9600; break; case 115200: options.c_cflag=B115200; break; default: options.c_cflag=B9600; break; } switch(data_bit){ case 7: options.c_cflag&=~CSIZE; options.c_cflag|=CS7; break; case 8: options.c_cflag&=~CSIZE; options.c_cflag|=CS8; break; default: options.c_cflag&=~CSIZE; options.c_cflag|=CS8; break; } switch(stop_bit){ case 1: options.c_cflag&=~CSTOPB; break; case 2: options.c_cflag|=CSTOPB; break; default: options.c_cflag&=~CSTOPB; break; } switch(parity){ case 'N': options.c_cflag&=~PARENB; //无奇偶校验 //c_iflag 控制串口数据输入 如剥离输入字符为8位 奇偶校验生效等 options.c_iflag&=~(INPCK|ISTRIP); //禁用输入奇偶校验 options.c_iflag|=IGNPAR; //忽略奇偶校验错误 break; case 'O': options.c_cflag|=(PARENB|PARODD); //启用校验并设置为奇校验 options.c_iflag|=(INPCK|ISTRIP); //启用奇偶检查并从接受字符串中脱去奇偶位 options.c_iflag&=~IGNPAR; //不忽略奇偶校验错误 break; case 'E': options.c_cflag|=PARENB; //启用奇偶校验 options.c_cflag&=~PARODD; //设置为偶校验 options.c_iflag|=(INPCK|ISTRIP); //启用检查并从中脱去奇偶校验位 options.c_iflag&=~IGNPAR; //不忽略校验错误 break; default: options.c_cflag&=~PARENB; options.c_iflag&=~(INPCK|ISTRIP); options.c_iflag|=IGNPAR; break; } switch(flow_ctrl){ case 'N': options.c_cflag&=~CRTSCTS; //停用硬件流控制 options.c_iflag&=~(IXON|IXOFF|IXANY);//停用软件控制流 options.c_cflag|=CLOCAL; //不使用流控制 break; case 'S': options.c_cflag&=~CRTSCTS; //停用硬件流控制 options.c_iflag|=(IXON|IXOFF|IXANY);//使用软件流控制 options.c_cflag&=~CLOCAL; //使用流控制 break; case 'H': options.c_cflag|=CRTSCTS; options.c_iflag&=~(IXON|IXOFF|IXANY);//使用硬件流控制 options.c_cflag&=~CLOCAL; //使用流控制 break; default: options.c_cflag&=~CRTSCTS; options.c_iflag&=~(IXON|IXOFF|IXANY); options.c_cflag|=CLOCAL; break; } options.c_cflag|=CREAD; //启用接收器,能够从串口中读取数据 options.c_iflag|=IGNBRK; //忽略输入行终止条件 //c_lflag设置串口驱动与用户间界面 options.c_lflag=0;//非加工输入,即显示原始数据 options.c_oflag=0;//非加工输出 //options.c_lflag &= ~(ICANON|ECHO|ECHOE|ISIG); //options.c_oflag &= ~OPOST; /*c_cc成员数组,索引宏常量 * 还可以设置超时参数,通过VMIN和VTIME引用 * 但只在非加工方式才有实际意义 * 分别控制等待字节数和等待时长,单位0.1s*/ //如果串口输入队列没有数据,将在read调用处阻塞 options.c_cc[VMIN] = 1; options.c_cc[VTIME] = 0; if(tcsetattr(fd,TCSANOW,&options)==-1){ printf("set error\n"); return -1; } tcflush(fd,TCIFLUSH); //刷新收到的数据,但是不读 tcflush(fd,TCOFLUSH); //刷新写入的数据,但不传送 return 0;}/***************************************************** * 名称: COM_BufQueSize * 功能: 得到串口输入队列中的字节数 * 传参: fd * buf_size 字节数会保存在该指针指向内存 * 返回: 正确 0 错误 -1 ****************************************************/ int COM_BufQueSize(int fd,int* buf_size) { int byte_count=0; if(fd == -1) return -1; //使用ioctl系统调用来实现配置串口 //任何IO操作都可以交给它 //此处的FIONREAD为返回输入队列中的字节数 if(ioctl(fd,FIONREAD,&byte_count)!=-1){ *buf_size=byte_count; return 0; } return -1; }/***************************************************** * 名称: COM_recv * 功能: 接受串口数据 * 传参: fd * recv_buf 读出串口数据存入recv_buf字符串 * data_len 一帧读取数据的长度 * 返回: 正确 所读字节数 错误 -1 * *****************************************************/int COM_recv(int fd,char* recv_buf,int data_len){ int rCount=0; //实际读到的字节数 int recvBytes=0; //实际接受字节数,可能大于最大缓冲 int QueSize=0; //输入队列字节数 if(fd<0){ perror("file description is valid\n"); return -1; } if(recv_buf==NULL){ perror("read buf is NULL\n"); return -1; } if(data_len>MAX_BUF) //大于最大缓冲区的分开处理 recvBytes=MAX_BUF; else recvBytes=data_len; memset(recv_buf,'\0',recvBytes); //清空字符串 if(COM_BufQueSize(fd,&QueSize)!=-1){ //获取输入队列字节数 printf("Uart Queue have %d bytes\n",QueSize); recvBytes=MIN(recvBytes,QueSize); //取其中的较小值作为接受字节数 } if(!recvBytes) return -1; rCount=read(fd,recv_buf,recvBytes); if(rCount<0){ perror("read error\n"); return -1; } return rCount;}/************************************************* * 名称: COM_transmit * 功能: 发送数据 * 传参: fd * mit_buf 将指向缓冲区数据写入串口 * data_len 写入的字节数长度 * 返回: 成功返回 实际写入字节数 失败 -1 * **********************************************/int COM_transmit(int fd,char* mit_buf,int data_len){ int wCount=0; //实际写入字节数长度 int mitBytes=data_len; if(fd<0){ perror("file description is valid\n"); return -1; } if((mitBytes>MAX_BUF)||!mitBytes) return -1; wCount=write(fd,mit_buf,mitBytes); if(wCount<0){ perror("write error\n"); return -1; } while(tcdrain(fd)==-1); //保证输出队列中所有数据被传送 return wCount;}
main.c#include "COM_Linux.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#define CMD_MAX_LEN 255int main(int argc,char *argv[]){ char Read_Buf[MAX_BUF+1]; //存储读取数据 char Write_Buf[MAX_BUF+1]; //存储发送数据 char CMD[CMD_MAX_LEN+1]; //命令控制字符串 int rCount=0; int wCount=0; int fd,com_port; if(argc<3){ printf("please fill the parameter\n"); return -1; } if((fd=COM_open(argv[1]))==-1) return -1; //if((fd=COM_open("/dev/ttyS1"))==-1) return -1; com_port=atoi(argv[2]); //将字符串转换为int整数 if(COM_set(fd,com_port,8,1,'N','N')==-1){ COM_close(fd); return -1; } while(1){ memset(CMD,'\0',CMD_MAX_LEN+1); //清空 printf("Enter Command: \n"); if(!fgets(CMD,CMD_MAX_LEN+1,stdin)){ //从stdin流,键盘获取输入 perror("fget error\n"); return -1; } /*fgets函数当遇到换行符和缓冲区已满,即会停止返回 *所以在不填满缓冲区的正常情况下 fgets获取的数据包括输入字符串加上回车换行符并在最后加上'\0' 如输入hello后回车,得到的strlen长度应为hello的5个字符长度 加一个\n回车以及最后的\0结束符,共7个 但strlen函数不包括结束符号,所以只有共6个 此处的CMD字符串应当将'\n'替换成'\0',便于后续比较str compare '\n'位于strlen长度最后一位,数组索引需减1*/ //printf("111%c222%c333",CMD[strlen(CMD)],CMD[strlen(CMD)-1]); CMD[strlen(CMD)-1]='\0'; if(strncmp(CMD,"quit",sizeof("quit"))==0) break; //退出命令 if(strncmp(CMD,"read",sizeof("read"))==0){ memset(Read_Buf,'\0',MAX_BUF+1); rCount=COM_recv(fd,Read_Buf,MAX_BUF); if(rCount>0){ printf("ReadBuffer: %s\n",Read_Buf); //向屏幕打印获取数据 printf("Read com char num: %d\n",rCount); } } if(strncmp(CMD,"write",sizeof("write"))==0){ memset(Write_Buf,'\0',MAX_BUF+1); strcpy(Write_Buf,"Hello"); printf("Write_Buf:%s\n",Write_Buf); wCount=COM_transmit(fd,Write_Buf,strlen((char*)Write_Buf)); sleep(1); memset(Read_Buf,'\0',MAX_BUF+1); } } COM_close(fd); return 0;}
阅读全文
0 0
- 有关linux串口通信
- linux串口通信编程
- Linux下串口通信
- linux串口通信程序
- Linux串口通信程序
- linux串口通信
- Linux 串口通信
- Linux:串口通信
- Linux:串口通信
- linux 下串口通信
- Linux串口通信例子
- Linux:串口通信
- Linux Java 串口通信
- linux串口通信
- linux串口通信
- linux下串口通信
- Linux--串口通信详解
- linux 串口通信详解
- Gym
- css3 media媒体查询器用法总结
- 设计模式-单例模式
- centos下安装python3
- 算法与数据结构-堆的基本操作C语言实现
- 有关linux串口通信
- 支持向量机svm由浅到深
- javaScript屏蔽鼠标右键,F12及其它审查元素功能
- kmp
- C语言中的左移注意
- Java作业-双色球彩票
- 【Bootstrap框架】——JS插件(JS plug-in)
- Spring Boot+log4j2+yml配置(2)MongoDB引入
- 单链表面试题——基础篇