未加星标

Easy Portable Serial Ports

字体大小 | |
[系统(linux) 所属分类 系统(linux) | 发布者 店小二05 | 时间 2018 | 作者 红领巾 ] 0人收藏点击收藏

Modern operating systems insulate us ― as programmers, especially ― from so much work. Depending on how far back you go, programmers had to manage their own fonts, their own allocation space on mass storage, or even their own memory allotments. Every year, though, it seems like things get easier and easier. So why is it so annoying to open a simple serial port? It isn’t hard, of course, but on every operating system it seems to be painful ― probably in an attempt to be flexible. And it is even worse if you want portability. I needed to write some C code that read data from an FPGA’s embedded logic analyzer, and I was annoyed at having to write yet more serial port code. I have my own shim library, but it isn’t well tested and isn’t all that flexible ― it does what I need, but I wanted something better. What I wound up with the serial library from Sigrok . You knowSigrok? The logic analyzer software.


Easy Portable Serial Ports
You might counter that the serial port is old hat, so no one wants to support it with modern systems. While the physical serial port might be on life support, there’s no shortage of equipment that connects via USB that appears to be a serial port. So while I was talking to an FTDI chip on an FPGA board, you could just as well be talking to an Arduino or a USB voltmeter or anything.

I guess the Sigrok developers had the same problem I did and they took the time to write a nice API and port it to major platforms. Although Sigrok uses it, they maintain it as a separate project and it was just what I needed. Sort of. I say sort of because the version installed with Ubuntu was old and I needed some features on the newest release, but ― as usual ― the Internet came to the rescue. A quick Git command, and four lines of build instructions and we were ready to go.

Getting Started

Since I use linux, the build instructions on the page worked fine. The install goes into /usr/local so I removed the libserialport-dev package just to be sure I didn’t get the wrong one by mistake.

The library provides a header file, libserialport.h. That file defines an sp_port type that is opaque. Since you don’t know the size of it, you can only create a pointer to it. You can get the pointer filled in by calling sp_get_port_by_name . You can also have the library give you a list of ports available . Once you have the port you can open it. There are simple calls for setting most things , but you usually only need to call sp_set_baudrate .

There’s also simple calls for doing blocking and non-blocking reads and writes and figuring out if there are characters waiting to be read.

My Example

I wound up writing about 50 lines of code to ping the analyzer with two commands and pull the data out to the terminal. You can find it below. It was just quick and dirty ― I didn’t try to optimize the reads or anything.

I doubt you’ll implement my code since you don’t have the logic analyzer. I will share that eventually in another post, though. But if you do want to have a go, you could easily code an Arduino to pick up two bytes on the serial port and then dump out 4,096 bytes.

Of course, this wasn’t my final code, but it shows how easy it was to write some portable code to work with the serial port.

// WordPress loves to eat angle brackets, so if the 3 includes below are blank
// they are: stdio.h stdlib.h and libserialport.h
#include <stdio.h>
#include <stdlib.h>
#include <libserialport.h>
#define BAUD 9600
// Commands to LA
#define USERCMD_RESET 0
#define USERCMD_RUN 1
int main(int argc, char *argv[])
{
struct sp_port *port;
int err;
int i,cmd;
int count=4096;
// We need a serial port name
if (argc<2)
{
fprintf(stderr,"Usage la port\n");
exit(1);
}
// Open serial port
err=sp_get_port_by_name(argv[1],&port);
if (err==SP_OK)
err=sp_open(port,SP_MODE_READ_WRITE);
if (err!=SP_OK)
{
fprintf(stderr,"Can't open port %s\n",argv[1]);
exit(2);
}
// set Baud rate
sp_set_baudrate(port,BAUD);
// write reset
cmd=USERCMD_RESET;
sp_blocking_write(port,&cmd,1,100);
// write run
cmd=USERCMD_RUN;
sp_blocking_write(port,&cmd,1,100);
// read data
for (i=0;i<count;i++)
{
int waiting;
int c=0;
do
{
waiting=sp_input_waiting(port);
} while (waiting<=0);
// sort of inefficient -- could read a bunch of bytes at once
// could even block for all of them at once
sp_nonblocking_read(port,(void *)&c,1);
if (i%16==0) putchar('\n');
printf("%02X ",c);
}
putchar('\n');
sp_close(port);
return 0;
} Portability and Support
Easy Portable Serial Ports

The library works on Linux, Mac, FreeBSD, windows and Android. No Commodore 64 or VAX support, but we can let that slide. It is well documented , too. You might wonder what the big deal is. Well, let’s take a little detour. Keep in mind that you may have a favorite library that hides a lot of this from you and that’s great. Maybe it is even cross-platform, at which point that’s great, too. But I’m talking using the OS’s native API.


Easy Portable Serial Ports
Linux borrows heavily from Unix so it things serial ports might just be modems or teletypes. That means there are dozens and dozens of obscure options for serial ports, mostly in the wacky termios structures. Everything is a file, so opening the port isn’t that stressful. You do have to decide if you want to set strange bits like O_NOCTTY and O_NDELAY. Oh, and you probably want to tell the port not to hang if no data is available by setting the FNDELAY bit which is via another API call. Plus set the baud rate.

I won’t bore you with all the exact code, but if you really want an idea of what’s involved, here’s a pretty good reference . Just remember the benign code to open the port is just the tip of the iceberg. Keep reading at least until Chapter 3.

Windows isn’t much better. The actual API interface is similar ― but not the same ― as the Linux code. You create a file almost in the usual way. But then you get a device control block (DCB) and fill it all in to configure the port. Want timeouts? That’s another call. There’s a whole different API for non-blocking I/O although you have a few choices there. There’s also EscapeCommFunction to do other odd things.

None of this is that hard and, in fact, Windows is a bit easier only because it is less flexible. But it is very easy to just use one portable open source library.

Going Forward

Next time you want to talk serial with a PC using any language that can call a library, you ought to consider this one. Even if you don’t need the portability, it is a pleasant enough API and you don’t have to switch gears later if you do port or if you just start a different project.

If you don’t like it, there are other choices. A quick search turned up a C++ library that supports Windows, Linux, and Mac. Some popular libraries like Boost for C++ have serial port handlers, too. Here’s a simple C-language library that is pretty minimal. There are doubtless others and I’d imagine the comments will turn up a few gems, as well.

Photo Credit: Fun with VMWare by [Bill Bradford] CC-By-2.0 .

本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统

tags: port,serial,sp,code,library
分页:12
转载请注明
本文标题:Easy Portable Serial Ports
本站链接:https://www.codesec.net/view/597061.html


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 系统(linux) | 评论(0) | 阅读(25)