linux与开发板串口通信
研究了一天的linux串口,结果改了树莓派的系统配置文件config.txt给改了导致系统崩溃。。。。其实我感觉网上的大多数方法都是不符合新版本树莓派的,网上的方法是通过修改系统配置文件后安装minicom进行串口的调试。为什么需要修改配置文件?因为树莓派升级后tx与rx引脚是复用的,需要用于串口的话就需要修改配置,让系统把io口让给串口。
这种方法比较麻烦,我采用的是利用两个usb转串口,互相连接好了,就可以直接通过linux下的串口通信函数来实现通信了。需要注意的是两个usb转串口相互连接时不仅仅要将RXD、TXD相互反接,还需要将GND连接在一起。
下面讲解下具体方法
(1)不同系统的串口名称是不一样的,如下图。

(2)设置
最基本的设置串口包括波特率设置,效验位和停止位设置.
很多系统都支持POSIX终端(串口)接口.程序可以利用这个接口来改变终端的参数,比如,波特率,字符大小等等.要使用这个端口的话,你必须将<termios.h>头文件包含到你的程序中.这个头文件中定义了终端控制结构体和POSIX控制函数.
与串口操作相关的最重要的两个POSIX函数可能就是tcgetattr(3)和tcsetattr(3).顾名思义,这两个函数分别用来取得设设置终端的属性.调用这两个函数的时候,你需要提供一个包含着所有串口选项的termios结构体,串口的设置主要是设置struct termios结构体的各成员值.

通过termio结构体的c_cflag成员可以控制波特率,数据的比特数,parity,停止位和硬件流控制,下面这张表列出了所有可以使用的常数


进行设置时千万不要直接用使用数字来初始化c_cflag(当然还有其他标志),最好的方法是使用位运算的与或非组合来设置或者清除这个标志.不同的操作系统版本会使用不同的位模式,使用常数定义和位运算组合来避免重复工作从而提高程序的可移植性.
1.1波特率设置
不同的操作系统会将波特率存储在不同的位置.旧的编程接口将波特率存储在上表所示的c_cflag成员中,而新的接口实装则提供了c_ispeed和c_ospeed成员来保存实际波特率的值.
程序中可是使用cfsetospeed(3)和cfsetispeed(3)函数在termios结构体中设置波特率而不用去管底层操作系统接口.下面的代码是个非常典型的设置波特率的例子.
struct termios options;
tcgetattr(fd,&option); //获取端口的当前状态
cfsetispeed(&options,B19200);//设置波特率为19200
options.c_cflags | =(CLOCK | CREAD);//将设置的参数传入
tcsetattr(fd,TCSANOW.&options);
函数tcgetattr( )会将当前串口配置回填到termio结构体option中.然后,程序设置了输入输出的波特率并且将本地模式(CLOCAL)和串行数据接收(CREAD)设置为有效,接着将新的配置作为参数传递给函数tcsetattr( ).常量TCSANOW标志所有改变必须立刻生效而不用等到数据传输结束.其他另一些常数可以保证等待数据结束或者刷新输入输出之后再生效.

1.2 设置字符大小,设置字符大小的时候,没有像设置波特率那么方便的函数.所以,程序中需要一些位掩码运算来把事情搞定.字符大小以比特为单位指定:
options.c_flag &= ~CSIZE; /* Mask the character size bits */
options.c_flag |= CS8; /* Select 8 data bits */
1.3 与上同理,通过位掩码来设置校验位与停止位
无奇偶校验( no parity)
options.c_cflag &= ~PARENB
options.c_cflag &= ~CSTOPB
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
偶校验(even parity)
options.c_cflag |= PARENB
options.c_cflag &= ~PARODD
options.c_cflag &= ~CSTOPB
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS7;
奇校验(odd parity)
options.c_cflag |= PARENB
options.c_cflag |= PARODD
options.c_cflag &= ~CSTOPB
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS7;
设置奇偶校验函数
/**
*@brief 设置串口数据位,停止位和效验位
*@param fd 类型 int 打开的串口文件句柄
*@param databits 类型 int 数据位 取值 为 7 或者8
*@param stopbits 类型 int 停止位 取值为 1 或者2
*@param parity 类型 int 效验类型 取值为N,E,O,,S
*/
int set_Parity(int fd,int databits,int stopbits,int parity)
{
struct termios options;
if ( tcgetattr( fd,&options) != ) {
perror("SetupSerial 1");
return(FALSE);
}
options.c_cflag &= ~CSIZE;
switch (databits) /*设置数据位数*/
{
case :
options.c_cflag |= CS7;
break;
case :
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n"); return (FALSE);
}
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */
options.c_cflag &= ~PARODD; /* 转换为偶效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'S':
case 's': /*as no parity*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;break;
default:
fprintf(stderr,"Unsupported parity\n");
return (FALSE);
}
/* 设置停止位*/
switch (stopbits)
{
case :
options.c_cflag &= ~CSTOPB;
break;
case :
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return (FALSE);
}
/* Set input parity option */
if (parity != 'n')
options.c_iflag |= INPCK;
tcflush(fd,TCIFLUSH);
options.c_cc[VTIME] = ; /* 设置超时15 seconds*/
options.c_cc[VMIN] = ; /* Update the options and do it NOW */
if (tcsetattr(fd,TCSANOW,&options) != )
{
perror("SetupSerial 3");
return (FALSE);
}
return (TRUE);
}
1.4 本地设置,本地模式成员变量c_lflag可以控制串口驱动怎样控制输入字符.通常,你可能需要通过c_lflag成员来设置经典输入和原始输入模式。
1.4.1 选择经典模式,经典输入是以面向行设计的.在经典输入模式中输入字符会被放入一个缓冲之中,这样可以以与用户交互的方式编辑缓冲的内容,直到收到CR(carriage return)或者LF(line feed)字符.选择使用经典输入模式的时候,你通常需要选择ICANON,ECHO和ECHOE选项: options.c_lflag |= (ICANON | ECHO | ECHOE);
1.4.2 选择原始输入,原始输入根本不会被处理.输入字符只是被原封不动的接收.一般情况中,如果要使用原始输入模式,程序中需要去掉ICANON,ECHO,ECHOE和ISIG选项:options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
(2)读写串口,unix将串口当做文件来处理,直接读取串口即可,write函数也会返回发送数据的字节数或者在发生错误的时候返回-1.通常,发送数据最常见的错误就是EIO,当调制解调器或者数据链路将Data Carrier Detect(DCD)信号线弄掉了,就会发生这个错误.而且,直至关闭端口这个情况会一直持续.
char buffer[];int Length;int nByte;nByte = write(fd, buffer ,Length)
读取数据:使用文件操作read函数读取,如果设置为原始数据模式(Raw Date Mode)传输数据,那么read函数返回的字符数是实际串口收到的字符数,也就是返回从串口输入缓冲区中实际得到的字符的个数.在不能得到数据的情况下,read(2)系统调用就会一直等着,只到有端口上新的字符可以读取或者发生超时或者错误的情况发生.
char buff[];int Len;int readByte = read(fd,buff,Len);
如果需要read(2)函数迅速返回的话,可以使用操作文件的函数来实现异步读取,如fcntl,或者select等来操作: fcntl(fd, F_SETFL, FNDELAY);标志FNDELAY可以保证read()函数在端口上读不到字符的时候返回0.需要回到正常(阻塞)模式的时候,需要再次在不带FNDELAY标志的情况下调用fcntl()函数:
(3)函数编程,需要的头文件如下
#include <stdio.h> /*标准输入输出定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <unistd.h> /*Unix 标准函数定义*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> /*文件控制定义*/
#include <termios.h> /*PPSIX 终端控制定义*/
#include <errno.h> /*错误号定义*/

一个树莓派发送数据数据给电脑串口的程序如下:需要根据具体的情况修改USB口
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h> //serial port set function
void setTermios(struct termios *pNewtio, unsigned short uBaudRate)
{
bzero(pNewtio,sizeof(struct termios));
pNewtio->c_cflag = uBaudRate|CS8|CREAD|CLOCAL;
pNewtio->c_iflag = IGNPAR;
pNewtio->c_oflag = ;
pNewtio->c_lflag = ;
pNewtio->c_cc[VINTR] = ;
pNewtio->c_cc[VQUIT] = ;
pNewtio->c_cc[VERASE] = ;
pNewtio->c_cc[VKILL] = ;
pNewtio->c_cc[VEOF] = ;
pNewtio->c_cc[VTIME] = ;
pNewtio->c_cc[VMIN] = ;
pNewtio->c_cc[VSWTC] = ;
pNewtio->c_cc[VSTART] = ;
pNewtio->c_cc[VSTOP] = ;
pNewtio->c_cc[VSUSP] = ;
pNewtio->c_cc[VEOL] = ;
pNewtio->c_cc[VREPRINT] = ;
pNewtio->c_cc[VDISCARD] = ;
pNewtio->c_cc[VWERASE] = ;
pNewtio->c_cc[VLNEXT] = ;
pNewtio->c_cc[VEOL2] = ;
}
int main(int argc,char **argv)
{
int fd;
int nCount,nTotal;
int i,j,m;
int ReadByte = ; int Buffer[];
struct termios oldtio,newtio;
char *dev = "/dev/tq2440_serial0"; if((argc!=)||(sscanf(argv[],"%d",&nTotal)!=))
{
printf("Usage:COMSend count datat! ");
return -;
} if((fd=open(dev,O_RDWR|O_NOCTTY|O_NDELAY))<) //open serial COM2
{
printf("Can't open serial port! ");
return -;
}
tcgetattr(fd,&oldtio);
setTermios(&newtio,B9600);
tcflush(fd,TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio); //Send data
for(i=;i<nTotal;i++)
{
nCount = write(fd,argv[],strlen(argv[]));
printf("send data OK!count=%d ",nCount);
sleep();
} //receive data
for(j=;j<;j++)
{
ReadByte = read(fd,Buffer,);
if(ReadByte>)
{
printf("readlength=%d ",ReadByte);
Buffer[ReadByte]='\0';
printf("%s ",Buffer);
sleep();
}
else printf("Read data failure times=%d ",j);
}
printf("Receive data finished! ");
tcsetattr(fd,TCSANOW,&oldtio);
close(fd);
return ;
}
参考文章:http://blog.sina.com.cn/s/blog_644949120100sc8n.html
http://www.cnblogs.com/jason-lu/articles/3173988.html
linux与开发板串口通信的更多相关文章
- linux下的qt串口通信
1.linux下的qt串口通信跟windows唯一的差别就是端口号的名字,windows下面是COM,而linux是ttyUSB0的路径 2.一般情况下linux插上USB转串口线就可以在/dev/目 ...
- linux下开发板网络速度测试记录
由于做的项目对于网络和USB的读写速度有很高的要求,因此新拿回来的板子要测试网络和usb的最佳传输速度.要考虑不少因素,先把我能想到的记录下来. 测试的环境是开发板和ubuntu虚拟机 ...
- iTOP-4412开发板-串口转接小板的使用文档
本文档介绍如何使用 迅为iTOP-4412 精英版如何使用串口转接板,串口小板如下所示.和串口转接板模块相关的资料如下:“iTOP-4412-Android-串口测试文档(升级版)_V2.X.zip” ...
- 迅为iTOP-4418开发板串口虚拟控制台配置为普通串口
如何将 iTOP-4418 的串口控制台配置为普通串口.在最终的产品中,如果需要额外的串口,可以将调试用的控制台串口作为普通串口使用,因为交付给最终用户手中的产品,一般不需要调试串口.屏蔽串口控制台需 ...
- 漫谈LiteOS之开发板-串口(基于GD32450i-EVAL)
[摘要] 主要讲解物联网的技术积累,本期我们先带领大家学习漫谈LiteOS之漫谈开发板第一集-串口,本文基于GD32450i-EVAL对串口以及其通信做了一个简要的分析,以及开发过程中遇到的一些技术 ...
- 如何在嵌入式Linux上开发一个语音通信解决方案
开发一个语音通信解决方案是一个软件项目.既然是软件项目,就要有相应的计划:有多少功能,安排多少软件工程师去做,这些工程师在这一领域的经验如何,是否需要培训,要多长时间做完,中间有几个主要的milest ...
- SecureCRT连接开发板 串口传输、tftp传输
1.串口传输 使用命令:rx r是service, x是X-model模式 ①.rx 文件名 再按Enter键 ②.将需要传到板子上的文件 拖到SecureCRT里面,选择发送X-model选项 注 ...
- 创龙TMS320C6748开发板串口和中断学习笔记
1. 硬件上,底板有2个串口,UART1和UART2(使用了MAX3232电平转换芯片),其中UART2也可以转RS485的. 2. 看下数据手册部分,不过一直不理解过采样的意思,16字节的FIFO ...
- 如何选安卓android|linux系统开发板,简化学习难度,缩短开发进程
平台一:iTOP-4412精英版 系统支持:Android 4.0.3系统 / Android 4.4系统 / Linux + Qt系统 / Ubuntu12.04系统 开发板特点:Cortex-A ...
随机推荐
- Kubernetes控制节点安装配置
#环境安装Centos 7 Linux release 7.3.1611网络: 互通配置主机名设置各个服务器的主机名hosts#查找kubernetes支持的docker版本Kubernetes v1 ...
- 实现如下语法的功能:var a = (5).plus(3).minus(6); //2
从汤姆大叔的博客里看到了6个基础题目:本篇是第5题 - 实现如下语法的功能:var a = (5).plus(3).minus(6); //2 解题关键: 1.理解使用(5)和5的区别 2.构造函数原 ...
- HDU 6108.小C的倍数问题 (2017"百度之星"程序设计大赛 - 初赛(A)1001)
补完题?不存在的. 这么久了,还是一条咸鱼,看一堆乱七八糟的东西,写一堆没用的水题,一点进步都没有,还是那么菜,菜的掉渣. 这个百毒之星初赛A还会写两道最简单的水题,初赛B一点也不会,菜的难过... ...
- MySQL读写分离-架构
MySQL读写分离-架构 简介 对于很多大型网站(pv值百万.千万)来说,在所处理的业务中,其中有70%的业务是查询(select)相关的业务操作(新闻网站,插入一条新闻.查询操作),剩下的则是写(i ...
- python实现无重复字符串的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&qu ...
- luogu P3817 小A的糖果
题目描述 小A有N个糖果盒,第i个盒中有a[i]颗糖果. 小A每次可以从其中一盒糖果中吃掉一颗,他想知道,要让任意两个相邻的盒子中加起来都只有x颗或以下的糖果,至少得吃掉几颗糖. 输入输出格式 输入格 ...
- C++中static、const使用方法简介
众所周知,在c++中,static和const的使用方法是难点,也是重点,值得我们随时温习,所谓温故而知新是也. 下面我们首先说一说static. 1.static的作用 static变量的作用,主要 ...
- 微软官方的精简版Windows 7——Windows Thin PC
Windows Thin PC是微软的Window 7的精简版本,它的一个非常明显的特点是系统资源占用小.如下是官方的系统配置需求: CPU: 主频1 GHz 内存: 1GB(实际占用约5 ...
- Android录制视频报错setVideoSize called in a invalid state 1
录制视频时想获取手机支持的录制视频的分辨率,使用代码如下: List<Camera.Size> videoSize = camera.getParameters().getSupporte ...
- java 的""和null的区别
null和""的区别 问题一: null和""的区别 String s=null; string.trim()就会抛出为空的exception String s ...