linux下c的串口收发
linux下c的串口收发录
转自: https://blog.csdn.net/weixin_41471318/article/details/116230465
文章目录
- linux下c的串口收发录
- 转自: https://blog.csdn.net/weixin_41471318/article/details/116230465
- 前言
- 一、直接打开串口
- 二、使用步骤
- 1.引入库
- 2.源码
- 三、使用步骤
- 1.termios详解及其赋值
- 总结
前言
因为在另外一篇文章说到了单片机的收发,所以想着在linux下也写一篇
而他们不同的是单片机是裸机,而Linux是一个系统,至于linux下皆文件,知道就行了,这里以ubuntu讲解,linux你大可分为驱动–内核–应用,而对于初始化串口都是内核跟驱动的事情,他们写好后会生成一个设备号,至于设备号在啥地方,驱动工程师会告诉你,一般来说串口的在 ”/dev/ttyx“,我们输入 ls /dev/tty 后按下Tab,他会自动补齐,然后会看到很多设备,可以理解成设备操作符
ls /dev/tty (+Tab)
提示:以下是本篇文章正文内容,下面案例可供参考
一、直接打开串口
fd= open("/dev/ttyUSB0",O_RDWR );//不成为控制终端程序,不受其他程序输出输出影响
这种也可以,后续也可以进行读写。就是read write,但是这样会使得波特率只能是9600,所以很多时候对于一些外设不是很友好,所以要对其进行设置
//试用的头文件有以下
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <error.h>
#include <termios.h>///串口使用到了这个
#include <malloc.h>
#include <sys/types.h>
#include <sys/stat.h>
二、使用步骤
1.引入库
代码如下(示例):
typedef struct termios termios_t;//串口类型结构体
typedef struct serial_data{char databuf[100];//发送/接受数据int serfd;//串口文件描述符
}ser_Data;void *sersend(void *arg);
void *serrecv(void *arg);
其termios 结构体是这个,后面会对这几个结构体进行解释
//而比较重要的是termios这个结构体struct termios{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]; /* 控制字符特性*/speed_tc_isspeed; //输入波特率speed_tc_ospedd; //输出波特率};
对此结构体进行设置
bzero(ter_s,sizeof(*ter_s)); ter_s->c_cflag |= CLOCAL | CREAD; //激活本地连接与接受使能 ter_s->c_cflag &= ~CSIZE;//失能数据位屏蔽ter_s->c_cflag |= CS8;//8位数据位 ter_s->c_cflag &= ~CSTOPB;//1位停止位 ter_s->c_cflag &= ~PARENB;//无校验位 ter_s->c_cc[VTIME] = 0;ter_s->c_cc[VMIN] = 0;
改变波特率,如果没有,那就是默认的115200
cfsetispeed(ter_s,B115200);//设置输入波特率cfsetospeed(ter_s,B115200);//设置输出波特率 tcflush(serport1fd,TCIFLUSH);//刷清未处理的输入和/或输出 if(tcsetattr(serport1fd,TCSANOW,ter_s) != 0){printf("com set error!\r\n");}
2.源码
代码如下(示例):
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <error.h>
#include <termios.h>
#include <malloc.h>
#include <sys/types.h>
#include <sys/stat.h>
typedef struct termios termios_t;typedef struct serial_data{char databuf[100];//发送/接受数据int serfd;//串口文件描述符}ser_Data;void *sersend(void *arg);
void *serrecv(void *arg);int main(int argc,char *argv[])
{pthread_t pid1,pid2;pthread_attr_t *pthread_arr1,*pthread_arr2;pthread_arr1 = NULL;pthread_arr2 = NULL;int serport1fd;/* 进行串口参数设置 */termios_t *ter_s = malloc(sizeof(*ter_s));serport1fd = open(argv[1],O_RDWR | O_NOCTTY | O_NDELAY);//不成为控制终端程序,不受其他程序输出输出影响if(serport1fd < 0){printf("%s open faild\r\n",argv[1]);return -1;}bzero(ter_s,sizeof(*ter_s));ter_s->c_cflag |= CLOCAL | CREAD; //激活本地连接与接受使能ter_s->c_cflag &= ~CSIZE;//失能数据位屏蔽ter_s->c_cflag |= CS8;//8位数据位ter_s->c_cflag &= ~CSTOPB;//1位停止位ter_s->c_cflag &= ~PARENB;//无校验位ter_s->c_cc[VTIME] = 0;ter_s->c_cc[VMIN] = 0;/*1 VMIN> 0 && VTIME> 0VMIN为最少读取的字符数,当读取到一个字符后,会启动一个定时器,在定时器超时事前,如果已经读取到了VMIN个字符,则read返回VMIN个字符。如果在接收到VMIN个字符之前,定时器已经超时,则read返回已读取到的字符,注意这个定时器会在每次读取到一个字符后重新启用,即重新开始计时,而且是读取到第一个字节后才启用,也就是说超时的情况下,至少读取到一个字节数据。2 VMIN > 0 && VTIME== 0在只有读取到VMIN个字符时,read才返回,可能造成read被永久阻塞。3 VMIN == 0 && VTIME> 0和第一种情况稍有不同,在接收到一个字节时或者定时器超时时,read返回。如果是超时这种情况,read返回值是0。4 VMIN == 0 && VTIME== 0这种情况下read总是立即就返回,即不会被阻塞。----by 解释粘贴自博客园*/cfsetispeed(ter_s,B115200);//设置输入波特率cfsetospeed(ter_s,B115200);//设置输出波特率tcflush(serport1fd,TCIFLUSH);//刷清未处理的输入和/或输出if(tcsetattr(serport1fd,TCSANOW,ter_s) != 0){printf("com set error!\r\n");}char buffer[] = {"hello my world!\r\n"};char recvbuf[100] = {};ser_Data snd_data;ser_Data rec_data;snd_data.serfd = serport1fd;rec_data.serfd = serport1fd;memcpy(snd_data.databuf,buffer,strlen(buffer));//拷贝发送数据pthread_create(&pid1,pthread_arr1,sersend,(void *)&snd_data);pthread_create(&pid2,pthread_arr2,serrecv,(void *)&rec_data);ssize_t sizec;while(1){usleep(100000);}pthread_join(pid1,NULL);pthread_join(pid2,NULL);free(ter_s);return 0;
}void *sersend(void *arg)//串口发送线程函数
{ser_Data *snd = (ser_Data *)arg ;int ret;while(0){ret = write(snd->serfd,snd->databuf,strlen(snd->databuf));if(ret > 0){printf("send success, data is %s\r\n",snd->databuf);}else{printf("send error!\r\n");}usleep(300000);/*if(发生中断)break;//退出*/}
}void *serrecv(void *arg)//串口发送线程函数
{ser_Data *rec= (ser_Data *)arg ;int ret;while(1){ret = read(rec->serfd,rec->databuf,1024);if(ret > 0){printf("recv success,recv size is %d \r\n",ret );if(rec->databuf[0]==1){printf("\n many color");}else{printf("\n black color");}printf("\n num :%d",rec->databuf[1]);if(rec->databuf[3]==1){printf("\n one by one open");}else{printf("\n one by one close");}if(rec->databuf[4]==1){printf("\n single single");}else{printf("\n double single");}if(rec->databuf[5]==1){printf("\n auto");}else if(rec->databuf[5]==2){printf("\n text");}else if(rec->databuf[5]==3){printf("\n text pict");}else if(rec->databuf[5]==4){printf("\n pict");}printf("\n mingandu :%d",rec->databuf[6]);if(rec->databuf[6]==1){printf("\n a4");}else{printf("\n a3");}if(rec->databuf[7]==1){printf("\n jinzhiqi");}else{printf("\n gaotai");}}else{/*什么也不做*/}usleep(1000);/*if(发生中断)break;//退出*/}
}
该处使用的url网络请求的数据。
三、使用步骤
1.termios详解及其赋值
//而比较重要的是termios这个结构体struct termios{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]; /* 控制字符特性*/};
c_iflag参数表
键值 | Value |
---|---|
IGNBRK | 忽略BREAK键输入 |
BRKINT | 如果设置了IGNBRK,BREAK键输入将被忽略 |
IGNPAR | 忽略奇偶校验错误 |
PARMRK | 标识奇偶校验错误 |
INPCK | 允许输入奇偶校验 |
ISTRIP | 去除字符的第8个比特 |
INLCR | 将输入的NL(换行)转换成CR(回车) |
IGNCR | 忽略输入的回车 |
ICRNL | 将输入的回车转化成换行(如果IGNCR未设置的情况下) |
IUCLC | 将输入的大写字符转换成小写字符(非POSIX) |
IXON | 允许输出时对XON/XOFF流进行控制 |
IXANY | 输入任何字符将重启停止的输出 |
IXOFF | 允许输入时对XON/XOFF流进行控制 |
IMAXBEL | 当输入队列满的时候开始响铃 |
c_oflag参数表
键值 | Value |
---|---|
OPOST | 处理后输出 |
OLCUC | 将输入的小写字符转换成大写字符(非POSIX) |
ONLCR | 将输入的NL(换行)转换成CR(回车)及NL(换行) |
OCRNL | 将输入的CR(回车)转换成NL(换行) |
ONOCR | 第一行不输出回车符 |
ONLRET | 不输出回车符 |
OFILL | 发送填充字符以延迟终端输出 |
OFDEL | 以ASCII码的DEL作为填充字符,如果未设置该参数,填充字符为NUL |
NLDLY | 换行输出延时,可以取NL0(不延迟)或NL1(延迟0.1s) |
CRDLY | 回车延迟,取值范围为:CR0、CR1、CR2和 CR3 |
TABDLY | 水平制表符输出延迟,取值范围为:TAB0、TAB1、TAB2和TAB3 |
BSDLY | 空格输出延迟,可以取BS0或BS1 |
VTDLY | 垂直制表符输出延迟,可以取VT0或VT1 |
FFDLY | 换页延迟,可以取FF0或FF1 |
c_cflag:
键值 | Value |
---|---|
CBAUD | 波特率(4+1位)(非POSIX) |
CBAUDEX | 附加波特率(1位)(非POSIX) |
CSIZE | 字符长度,取值范围为CS5、CS6、CS7或CS8 |
CSTOPB | 设置两个停止位 |
CREAD | 使用接收器 |
PARENB | 使用奇偶校验 |
PARODD | 对输入使用奇偶校验,对输出使用偶校验 |
HUPCL | 关闭设备时挂起 |
CLOCAL | 忽略调制解调器线路状态 |
CRTSCTS | 使用RTS/CTS流控制 |
c_lflag:
键 值 | 说 明 |
---|---|
ISIG | 当输入INTR、QUIT、SUSP或DSUSP时,产生相应的信号 |
ICANON | 使用标准输入模式 |
XCASE | 在ICANON和XCASE同时设置的情况下,终端只使用大写。如果只设置了XCASE,则输入字符将被转换为小写字符,除非字符使用了转义字符(非POSIX,且Linux不支持该参数) |
ECHO | 显示输入字符 |
ECHOE | 如果ICANON同时设置,ERASE将删除输入的字符,WERASE将删除输入的单词 |
ECHOK | 如果ICANON同时设置,KILL将删除当前行 |
ECHONL | 如果ICANON同时设置,即使ECHO没有设置依然显示换行符 |
ECHOPRT | 如果ECHO和ICANON同时设置,将删除打印出的字符(非POSIX) |
TOSTOP | 向后台输出发送SIGTTOU信号 |
总结
提示:这里对文章进行总结:
先搞懂那几个结构体,就好办事了
链接: link
linux下c的串口收发相关推荐
- linux c 串口 调用命令,Linux系统C语言串口收发
Linux系统C语言串口收发 Linux系统对串口提供了很好的支持,使我们很容易就能用C语言编写出串口收发程序. 先简单说明一下编写串口收发程序前的准备工作.首先串口收发需要有硬件上的串口,在Linu ...
- Linux uart寄存器读写,Linux下读写UART串口的代码
Linux下读写UART串口的代码,从IBM Developer network上拿来的东西,操作比較的复杂,就直接跳过了,好在代码能用,记录一下- 两个实用的函数- /** *@brief 设置串口 ...
- linux下Qt编写串口调试助手,如何在linux下用QT写一个简单的串口调试助手
如何在linux下用QT写一个简单的串口调试助手 QT5串口类 在QT5以前,编写串口一般使用的是qextserialport类,但在QT5之后有了QT自带的串口类SerialPort(串口基础类)和 ...
- Linux下自定义虚拟串口驱动
前些天给新的板子修改BUG的时候,发现这块板子的串口是接在板载MCU上,我们的主SOC(海思HI3520D)上已经没有多余的串口.于是问题来了- 我们很多的上层应用都是通过串口和传感器通讯的,而且程序 ...
- Linux下C语言串口应用编程,Linux下串口C语言编程
Linux下串口C语言编程 (5页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 串口操作代码#include #include #inclu ...
- Linux下C语言串口应用编程
在编写Linux串口的C程序之前,需要包含以下头文件: #include <termios.h> 在Linux系统中,一切皆文件,所以串口设备也是一类文件,学习过Linux驱动程序的学员都 ...
- Linux下的虚拟串口驱动(一)
欢迎转载,转载请注明出处. 前言 最近准备在Linux下,实现虚拟串口驱动:但因为毕业后,一直从事的是裸机驱动开发,所以Linux下的设备驱动,就慢慢忘记了:为了实现这一功能,在网上也查找了很多资料, ...
- linux下QT开发串口通信助手
串口通信的应用十分广泛,所以在QT下编写一个串口通信程序就显得尤为重要.下面将一步一步叙述开发过程: 1.下载第三方QT串口类,免积分 http://download.csdn.net/detail/ ...
- linux串口助手开发,linux下QT开发串口通信助手
串口通信的应用十分广泛,所以在QT下编写一个串口通信程序就显得尤为重要.下面将一步一步叙述开发过程: 1.下载第三方QT串口类,免积分 http://download.csdn.net/detail/ ...
最新文章
- 魅族员工跳槽OPPO后感慨,公司高层各种反思,不会骂员工废材
- 机器学习--Hoeffding Inequality--界定概率边界
- Android UmengShareSDK第三方登录
- java设计模式之UML①
- YOLOv4改进版重磅问世!Yolov4原班人马重磅推出Scaled-YOLOv4!业界最佳
- Merry Christmas and Happy New Year~
- ant root环境配置_Java ant环境变量配置
- 关于stack 和heap
- 智慧社区智能化管理系统搭建
- Js传参中文乱码解决方法
- c# DevExpress Gridview 设置表格背景颜色
- bat的使用技巧汇总
- Linux虚拟机设置全屏
- ODI 11g安装记录
- 4AT已经衰老 6AT正值壮年
- 数字通信调制方式的误码率matlab仿真,包括OOK,PRK,FSK以及QAM
- 计算机网盘变成红色是怎么回事,电脑小知识:硬盘变红了会带来哪些危害?
- 支持生僻字且自动识别utf-8编码的php汉字转拼音类,支持生僻字且自动识别utf-8编码的php汉字转拼音类...
- win10系统磁盘进行再分区的方法
- MySQL查询优化小结