树莓派UART串口编程--使用wiringPi库-C开发【2-修改驱动】

一、前言

上一篇博文记录了使用wiringPi提供的串口驱动wiringSerial.c wiringSerial.h,并基于该驱动对串口进行简单的通信,测试中发现该串口的驱动比较简单,接收数据会存在分包的现象,另外一点是串口配置只提供了波特率参数配置,未提供其他如校验、数据位和停止位驱动。这一片博文主要是对驱动进行修改。

二、修改驱动

wiringPi的驱动源码可以在https://projects.drogon.net/raspberry-pi/wiringpi/中下载。找到wiringSerial.c 和 wiringSerial.h两个文件,复制一份并重名命为wiringSerial_Driver.c wiringSerial_Driver.h。以便于我们修改。

具体地,修改包括初始化函数、串口接收函数和串口发送函数。

2.1 初始化函数修改

可以同时初始化波特率、停止位、校验位和数据位。参数gsfd为全局定义的串口打开设备ID号,static int gsfd;

linux串口编程主要是对termios进行初始化,需要包含头文件:#include <termios.h>

在Rpi3B中输入:

man termios

可以查看termios的描述,具体不多讲,看说明文档即可,以下仅罗列部分:


NAMEtermios,  tcgetattr, tcsetattr, tcsendbreak, tcdrain, tcflush, tcflow, cfmakeraw, cfgetospeed, cfgetispeed, cfsetispeed, cfsetospeed, cfsetspeed - getand set terminal attributes, line control, get and set baud rateSYNOPSIS#include <termios.h>#include <unistd.h>int tcgetattr(int fd, struct termios *termios_p);int tcsetattr(int fd, int optional_actions,const struct termios *termios_p);int tcsendbreak(int fd, int duration);int tcdrain(int fd);int tcflush(int fd, int queue_selector);int tcflow(int fd, int action);void cfmakeraw(struct termios *termios_p);speed_t cfgetispeed(const struct termios *termios_p);speed_t cfgetospeed(const struct termios *termios_p);int cfsetispeed(struct termios *termios_p, speed_t speed);int cfsetospeed(struct termios *termios_p, speed_t speed);int cfsetspeed(struct termios *termios_p, speed_t speed);Feature Test Macro Requirements for glibc (see feature_test_macros(7)):cfsetspeed(), cfmakeraw(): _BSD_SOURCEDESCRIPTIONThe termios functions describe a general terminal interface that is provided to control asynchronous communications ports.The termios structureMany of the functions described here have a termios_p argument that is a pointer to a termios structure.  This structure contains at least the follow‐ing members:tcflag_t c_iflag;      /* input modes */tcflag_t c_oflag;      /* output modes */tcflag_t c_cflag;      /* control modes */tcflag_t c_lflag;      /* local modes */cc_t     c_cc[NCCS];   /* special characters */The  values  that  may be assigned to these fields are described below.  In the case of the first four bit-mask fields, the definitions of some of theassociated flags that may be set are exposed only if a specific feature test macro (see feature_test_macros(7))  is  defined,  as  noted  in  brackets("[]").In  the  descriptions  below,  "not  in  POSIX"  means that the value is not specified in POSIX.1-2001, and "XSI" means that the value is specified inPOSIX.1-2001 as part of the XSI extension.

那么具体的驱动可以改写成一下内容:

int myserialOpen (const char *device, const int baud, const int nbit, const char parity, const int nstop)
{struct termios options ;speed_t myBaud ;int     status;switch (baud){case      50:	myBaud =      B50 ; break ;case      75:	myBaud =      B75 ; break ;case     110:	myBaud =     B110 ; break ;case     134:	myBaud =     B134 ; break ;case     150:	myBaud =     B150 ; break ;case     200:	myBaud =     B200 ; break ;case     300:	myBaud =     B300 ; break ;case     600:	myBaud =     B600 ; break ;case    1200:	myBaud =    B1200 ; break ;case    1800:	myBaud =    B1800 ; break ;case    2400:	myBaud =    B2400 ; break ;case    4800:	myBaud =    B4800 ; break ;case    9600:	myBaud =    B9600 ; break ;case   19200:	myBaud =   B19200 ; break ;case   38400:	myBaud =   B38400 ; break ;case   57600:	myBaud =   B57600 ; break ;case  115200:	myBaud =  B115200 ; break ;case  230400:	myBaud =  B230400 ; break ;case  460800:	myBaud =  B460800 ; break ;case  500000:	myBaud =  B500000 ; break ;case  576000:	myBaud =  B576000 ; break ;case  921600:	myBaud =  B921600 ; break ;case 1000000:	myBaud = B1000000 ; break ;case 1152000:	myBaud = B1152000 ; break ;case 1500000:	myBaud = B1500000 ; break ;case 2000000:	myBaud = B2000000 ; break ;case 2500000:	myBaud = B2500000 ; break ;case 3000000:	myBaud = B3000000 ; break ;case 3500000:	myBaud = B3500000 ; break ;case 4000000:	myBaud = B4000000 ; break ;default:return -2 ;}/* 有O_NONBLOCK 即为非阻塞方式,默认阻塞方式,等待vim vtime*/if ((gsfd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)return -1 ;fcntl (gsfd, F_SETFL, O_RDWR) ;// Get and modify current options:tcgetattr (gsfd, &options) ;cfmakeraw   (&options) ;cfsetispeed (&options, myBaud) ;cfsetospeed (&options, myBaud) ;//data bitswitch (nbit){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;}//data parityswitch(parity)  {case 'n':case 'N':options.c_cflag &= ~PARENB ;options.c_cflag &= ~INPCK;break;case 'o':case 'O': options.c_cflag |= PARENB ;options.c_cflag |= PARODD ;options.c_cflag |= INPCK  ;options.c_cflag |= ISTRIP	; break;case 'e':case 'E': options.c_cflag |= PARENB ;options.c_cflag &= ~PARODD;options.c_cflag |= INPCK 	;options.c_cflag |= ISTRIP	;break;default:options.c_cflag &= ~PARENB ;options.c_cflag &= ~INPCK;break;}//data stopbitsswitch(nstop){case 1: options.c_cflag &= ~CSTOPB ; break;case 2: options.c_cflag |= CSTOPB ;  break; default: options.c_cflag &= ~CSTOPB ; break;    }options.c_cflag |= (CLOCAL | CREAD) ;options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;options.c_oflag &= ~OPOST ;options.c_cc [VMIN]  =   0 ;options.c_cc [VTIME] = 10 ;	// 0.5 seconds (100 deciseconds)tcsetattr (gsfd, TCSANOW, &options) ;ioctl (gsfd, TIOCMGET, &status);status |= TIOCM_DTR ;status |= TIOCM_RTS ;ioctl (gsfd, TIOCMSET, &status);usleep (10000) ;	// 10mSreturn gsfd ;
}

2.2 接收函数修改

提一下,Linux串口接收主要由阻塞和非阻塞接收两种方式,关于如何配置Linux串口驱动可以参考这篇博文:Linux 使用fcntl c_cc[VMIN] c_cc[CTIME]设置串口阻塞与非阻塞读取数据

实际测试时发现wiringSerial的接收函数serialDataAvail缓存大小只有8字符,因此,超过8字符的数据将会分包,接收函数修改主要是对数据进行拼包,具体实现如下:

int myserialDataRead( char *buf,  int * size)
{int size_i,i;i = 0;size_i = 0;while(1){i = read(gsfd, buf+size_i ,1024);size_i += i;if(i == 8){}else if(i>0 && i <= 8){*size = size_i;return 0;}else{return -1;}}
}

2.3 发送函数修改

发送函数基本和wiringSerial提供的驱动一致,只是将传入的设备ID用全局变量替代,这样在使用该函数时无需输入串口的ID。具体修改如下:

void myserialDataSend(const char * ptr,int size)
{while(size--){serialPutchar(gsfd,*(ptr++));} 
}

三、编译测试

对应的头文件增加函数的声明,编写main.c测试文件:

#include<wiringPi.h>
#include"wiringSerial_Driver.h"
#include<stdio.h>
#include<string.h>int main()
{int filedevid;int recbytenum;int rxflag;int i;char buf[1024];char bufprintf[1024];memset(buf,0,1024);memset(bufprintf,0,1024);wiringPiSetup();if((filedevid=myserialOpen("/dev/ttyAMA0",115200,8,'E',1))<0){printf("/dev/ttyAMA0 Open Faild\r\n");return -1;}else{printf("/dev/ttyAMA0 Open with 115200,115200,8,'E',1, success\r\n");while(1){rxflag = myserialDataRead(buf,&recbytenum);if(rxflag != -1){printf("Rpi3 uart rx %d byte: %s\r\n",recbytenum,buf);sprintf(bufprintf,"Rpi3 uart Tx %d byte: %s\r\n",recbytenum,buf);myserialDataSend(bufprintf, recbytenum);}}}
}

编写makefile,进行编译并运行如下:

可以看到,数据以及拼包成功,说明驱动修改有效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/405644.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】全面理解javascript的arguments,callee,caller,call,apply概念(修改版)

(注&#xff1a;在看到大家如此关注JS里头的这几个对象&#xff0c;我试着把原文再修改一下&#xff0c;力求能再详细的阐明个中意义 2007-05-21&#xff09;在提到上述的概念之前&#xff0c;首先想说说javascript中函数的隐含参数&#xff1a;arguments Arguments 该对象代表…

windows延缓写入失败相关问题解决办法

From: http://www.ggsafe.com/news/1324547234222.shtml 我们在使用电脑时&#xff0c;有时在不正常关机后电脑会出现这样那样的问题。windows延缓写入失败就是其中一个&#xff0c;很多网友在互联网上发帖求助windows延缓写入失败怎么办&#xff0c;出现这种情况一般都是由于电…

wince linux 性能,wince remote call profiler(性能分析)

如何使用1 建立工程,CPU类型必须于目标机型一致如ARMV4I,所以选择WCE Application,然后选择empty project2 project settings 中,link页,Object/library modules中添加 cecap.lib(前面有空格),Ingore libraries中添加,libc.lib(前面有逗号).C/C页Project Options最后添加 /call…

前端小知识点(4):JS 运行机制和存储

目录 被忽视的内存管理 JS工作原理 JS代码如何运行 JavaScript内存的生命周期 栈内存、堆内存 代码案例 运行结果 被忽视的内存管理 JavaScript不像C、C等语言——程序员必须通过调用内存管理接口&#xff0c;比如 malloc()和free()&#xff0c;自己手动分配和释放内存。…

Linux ps aux查看进程

一、ps 命令 ps 是Process Status的缩写&#xff0c;用于查看进程状态&#xff0c;ps 可以显示linux系统的所有进程信息。 用法&#xff1a; ps a 显示现行终端机下的所有程序&#xff0c;包括其他用户的程序。ps -A 显示所有程序。 ps c 列出程序时&#xff0c;显示每个程序…

2010数据库SQL Server 盘点

让我们一起来盘点一下2010数据库SQL Server 发布了那些给力的新品。 1. 微软发布SQL Server 2008 R2 微软公司于2010年4月21日宣布推出Microsoft SQL Server 2008 R2。SQL Server 2008 R2已经可以看作是本年度的一次重量级发布。微软公司努力将SQL Server打造为一个信息平台&am…

linux下有四个作业优先级,第一次作业:对Linux系统分析

一.操作系统的组成1.无进程的内核在一些操作系统当中操作系统的内核在所有的进程之外执行。也就是说操作系统有自己的内存区域和系统栈&#xff0c;当进程发生 中断&#xff0c;陷阱或系统调用时&#xff0c;此进程的上下文环境被保存在系统栈中&#xff0c;控制权转移给内…

前端小知识点(6):听了好多闭包,这次可能最懂

目录 一、作用域和作用域链 二、闭包 三、无意间共享环境[可以通过闭包解决] 代码一 结果一 代码二 结果二 代码三 结果三 一、作用域和作用域链 当函数声明的时候&#xff0c;函数会通过内部属性[scope]来记录创建范围 二、闭包 什么是闭包&#xff1a;闭包是一个函数加…

Linux的Qt编译出现:-1: error: cannot find -lGL问题的解决方法

Qt是支持跨平台的C图形用户界面应用程序开发框架&#xff0c;在一个平台上开发好应用程序可以在多个平台方便移植。 在将windows平台上开发的Qt界面程序移植到Linux Ubuntu系统中&#xff0c;在构建项目时出现以下编译问题&#xff1a; error: cannot find -lGL。 即&#xf…

git rebase原理(转)

git rebase 不会取回代码 要用git fetch先取回&#xff0c; git rebase 是合并代码。 &#xff08;1&#xff09;首先用git fetch返回服务器上的代码 &#xff08;2&#xff09;首先用git rebase origin/master 合并 &#xff08;3&#xff09;如果发生冲突了会提示&#xff0c…

前端小知识点(7):正则前瞻

目录 一、js中的正则表达式&#xff0c;只有前瞻没有后顾 正向前瞻&#xff1a;(?) 》匹配符合的 代码1 结果1 代码2 结果2 一、js中的正则表达式&#xff0c;只有前瞻没有后顾 正向前瞻&#xff1a;(?) 》匹配符合的 负向前瞻&#xff1a;(?!) 》匹配不…

c语言编译生成cpp,C语言的编译过程

编译&#xff1a; 编译程序读取源程序(字符流)&#xff0c;对之进行词法和语法的分析&#xff0c;将高级语言指令转换为功能等效的汇编代码&#xff0c;再由汇编程序转换为机器语言&#xff0c;并且按照操作系统对可执行文件格式的要求链接生成可执行程序。流程&#xff1a;C源…

设置启用树莓派的HDMI显示

树莓派所有的启动初始化都是在config.txt中完成的&#xff0c;因此&#xff0c;若插入HDMI树莓派没有显示桌面&#xff0c;则是没有配置HDMI。 首先在找到config.txt&#xff0c;两种方法&#xff1a; 第一种方法&#xff0c;将SD卡取出&#xff0c;用读卡器在windows上找到&…

前端小知识点(8):作者为什么设计原型

目录 一、从古代说起 二、Brendan Eich的选择 三、new运算符的缺点 四、prototype属性的引入 五、总结 六代码部分 一、从古代说起 要理解Javascript的设计思想&#xff0c;必须从它的诞生说起。 1994年&#xff0c;网景公司&#xff08;Netscape&#xff09;发布了Navi…

前端小知识点(9):函数和对象之间的关系

目录 函数与对象之间的关系 代码演示 运行结果 函数与对象之间的关系 函数 有什么 &#xff1a; 函数也是对象 函数有&#xff1a;prototype 对象 有什么 对象&#xff1a;__proto__ 原型对象里面有什么&#xff1a;constructor 代码演示 //fun是一个函数&#xf…

Linux 给Qt应用软件创建图标启动

一、描述 Ubuntu源码编译安装Eclipse和Qt后&#xff0c;没有自动创建图标&#xff0c;每次启动需要进入到目录下运行脚本&#xff0c;比较麻烦。 可通过创建类似于windows系统的快捷方式进行快捷启动。 快捷方式一般以.desktop后缀命名&#xff0c;并保存到/usr/share/appli…

scheme解释器 C语言实现,使用Scala写了个简单的Scheme解释器

大家好&#xff0c;我使用scala实现了个简单的解释器&#xff0c;能够实现整数的加减乘除。我是照着快学 19章的 3 - 4 * 5 这个例子做的。思路也是按照它的来的。大概是这样 1)首先定义 factor是整数2)那么 term &#xff1a; ( factorfactor...) 就是一个完整的表达式了3) …

Android 的用户层 uevent处理机制

From: http://blog.csdn.net/linphusen/article/details/5667647 摘录几篇android研发日志 1 http://blog.csdn.net/linweig/archive/2010/06/01/5640697.aspx Firmware 加载原理分析&#xff0d;&#xff0d;&#xff0d;&#xff0d;分析的比较透彻&#xff0c;我在wifimod…

前端小知识点(10):原型链

目录 原型链 : 代码1 运行结果1 代码二 运行结果2 原型链 : 每一个对象都有一个原型&#xff08;__proto__&#xff09;&#xff0c;这个原型还可以拥有自己的原型&#xff0c;形成最终的原型链。 查找一个对象特定的属性或者方法&#xff0c;我们先去当前对象中找&#xff…

PS/2键盘鼠标接口各针脚定义

PS/2键盘鼠标接口各针脚定义(附图)好像很长时间也没有把这个最不被人重视的硬件问题提出来了&#xff0c;今天&#xff01;我们就来谈谈键盘、鼠标PS/2接头各针脚定义(图)。针脚序号颜色名称简称意义电平1绿(G)Keyboard DATADATA (D)数据负线高电平2ReservervedN/C未定义预留空…