![]() |
Using Linux to Send Commands to ADR Interfaces This page will demonstrate how to send and receive data from the ADR112 or any other ADR interface, using Linux gcc programmes. It shows the commands used to configure the serial port, send data out through the serial port, and receive data through the serial port. Additional help is available from the Linux HowTo documents found at a variety of locations around the web (hint: use a search engine). The man pages of your Linux system are invaluable as well. I make no effort to explain all of the parameters used in the various API calls. Read The Famous Manual. This page is divided into several sections. The first section presents the source code with brief usage details. The second section shows pictorial examples and screen shots. Some troubleshooting hints are given in the second section. The third section describes some details (skip it if the first two sections provide what you need.) Linux VersionI tested this program using Redhat 7.3, however I believe this code will operate correctly under all recent Linux kernels (your mileage may vary). The code was compiled with version 2.96-110 of the gcc compiler. Any recent vintage of the gcc compiler should be fine.Source CodeThere are four files needed to compile the Linux example.
adrport.h// adrport.h // Copyright MMI, MMII by Sisusypro Incorporated int OpenAdrPort (char* sPortNumber); int WriteAdrPort(char* psOutput); int ReadAdrPort(char* psResponse, int iMax); void CloseAdrPort(); adrport.c// adrport.c - Serial Port Handler // Copyright MMI, MMII by Sisusypro Incorporated // Permission is hereby granted to freely copy, // modify, utilize and distribute this example in // whatever manner you desire without restriction. #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <string.h> #include <errno.h> #include "adrport.h" static int fd = 0; // opens the serial port // return code: // > 0 = fd for the port // -1 = open failed int OpenAdrPort(char* sPortNumber) { char sPortName[64]; printf("in OpenAdrPort port#=%s\n", sPortNumber); sprintf(sPortName, "/dev/ttyS%s", sPortNumber); printf("sPortName=%s\n", sPortName); // make sure port is closed CloseAdrPort(fd); fd = open(sPortName, O_RDWR | O_NOCTTY | O_NDELAY); if (fd < 0) { printf("open error %d %s\n", errno, strerror(errno)); } else { struct termios my_termios; printf("fd is %d\n", fd); tcgetattr(fd, &my_termios); // NOTE: you may want to save the port attributes // here so that you can restore them later printf("old cflag=%08x\n", my_termios.c_cflag); printf("old oflag=%08x\n", my_termios.c_oflag); printf("old iflag=%08x\n", my_termios.c_iflag); printf("old lflag=%08x\n", my_termios.c_lflag); printf("old line=%02x\n", my_termios.c_line); tcflush(fd, TCIFLUSH); my_termios.c_cflag = B9600 | CS8 |CREAD | CLOCAL | HUPCL; cfsetospeed(&my_termios, B9600); tcsetattr(fd, TCSANOW, &my_termios); printf("new cflag=%08x\n", my_termios.c_cflag); printf("new oflag=%08x\n", my_termios.c_oflag); printf("new iflag=%08x\n", my_termios.c_iflag); printf("new lflag=%08x\n", my_termios.c_lflag); printf("new line=%02x\n", my_termios.c_line); } // end if return fd; } // end OpenAdrPort // writes zero terminated string to the serial port // return code: // >= 0 = number of characters written // -1 = write failed int WriteAdrPort(char* psOutput) { int iOut; if (fd < 1) { printf(" port is not open\n"); return -1; } // end if iOut = write(fd, psOutput, strlen(psOutput)); if (iOut < 0) { printf("write error %d %s\n", errno, strerror(errno)); } else { printf("wrote %d chars: %s\n", iOut, psOutput); } // end if return iOut; } // end WriteAdrPort // read string from the serial port // return code: // >= 0 = number of characters read // -1 = read failed int ReadAdrPort(char* psResponse, int iMax) { int iIn; printf("in ReadAdrPort iMax=%d\n", iMax); if (fd < 1) { printf(" port is not open\n"); return -1; } // end if strncpy (psResponse, "N/A", iMax<4?iMax:4); iIn = read(fd, psResponse, iMax-1); if (iIn < 0) { if (errno == EAGAIN) { return 0; // assume that command generated no response } else { printf("read error %d %s\n", errno, strerror(errno)); } // end if } else { psResponse[iIn<iMax?iIn:iMax] = '\0'; printf("read %d chars: %s\n", iIn, psResponse); } // end if return iIn; } // end ReadAdrPort // closes the serial port void CloseAdrPort() { // you may want to restore the saved port attributes if (fd > 0) { close(fd); } // end if } // end CloseAdrPort adrserial.c// adrserial.c - Serial Port Test Example // Copyright MMII by Sisusypro Incorporated // WARNING: Example only. Lacks error checking! #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "adrport.h" // this is the mainline thingee int main(int argc, char *argv[]) { char sCmd[254]; char sResult[254]; if (argc < 2 || argc > 2) { printf("adrserial needs 1 parameter for the serial port\n"); printf(" ie. use 'adrserial 0' to connect to /dev/ttyS0\n"); return 0; } // end if printf("Type q to quit.\n\n"); if (OpenAdrPort(argv[1]) < 0) return 0; while (1) { int iSpot; printf("?:"); gets(sCmd); if (sCmd[0] == 'q' || sCmd[0] == 'Q') return 0; iSpot = strlen(sCmd); sCmd[iSpot] = 0x0d; // stick a <CR> after the command sCmd[iSpot+1] = 0x00; // terminate the string properly if (WriteAdrPort(sCmd) < 0) return 0; sleep(1); // give the ADR card some time to respond if (ReadAdrPort(sResult,254) > 0) { printf("****Response is %s\n", sResult); } // end if } // end while CloseAdrPort(); } // end main MakefileCFLAGS=-g -Wall adrserial: adrserial.c adrport.c gcc -g -c -Wall adrserial.c -o adrserial.o gcc -g -c -Wall adrport.c -o adrport.o gcc adrport.o adrserial.o -o adrserial Ontrak will send you a tarred and gzipped version of the above files (see bottom of this page), but it includes nothing beyond what is listed above. Building the Linux Example
Running the adrserial ExamplePermissionsFirst off, you have to grant permission to access the serial port. On my system I logged in with root authority and used chmod to grant all users read/write access to the serial port.chmod o+rw /dev/ttyS0 The adrserial programme has a single parameter: the numeric
value for the selected serial port. On my system the ADR card is connected to the
first serial port which is known as /dev/ttyS0 in Linux. (please adjust the following
instructions to match your system.)
Here is a screen-shot of 2 ADR commands.
After these two commands the LED connected to PA1 is lit up.
The rpa command instructs the ADR card to report the status of all 8 lines on PortA.
Prior to the next command I used the red wire to feed +5 volts to PA7. This caused the LED
on PA7 to light up.
An rpa command was sent to the ADR card eliciting the following response.
The shell prompt is the userid followed by the directory in which the example resides:
The current directory (ie dot) is not in the path. Thus it must be specified in the
command to start the programme:
The programme can be run from a normal tty console session (ie. command line). You do not
need to start an xterm. You do not need to start the x-window environment.
On our development system (Redhat Linux 7.3) the file /usr/include/asm/errno.h contains a long list of defined error constants. Looking up the EAGAIN constant shows a value of 11. Searching For Error Codes. You can use the "find" and "grep" commands to locate all the headers referring to a given defined constant. For example, the header files that refer to the EAGAIN constant can be listed with the following command: find /usr/include -exec grep -l 'EAGAIN' {} \; Many ThanksThis example is based on information gleaned from many Internet Web sites. Special accolades go to the following.Thanks to all of the Linux and gcc developers, documenters and testers. Thanks to Michael R. Sweet for his "Serial Port Programming Guide". Thanks to Luis F. Guzman for explaining the "find" command on the Central Indiana Linux Users Group page. Thanks to Redhat for providing free ftp distribution of Linux. FreedomThis programme is free. Free of cost. Free of restrictions. You can use it, copy it, modify it, distribute it and include it in your own application programme.This programme is also free of any warranty, express or implied, for fitness or merchantability. Use at your own risk. I hope this assists your programming efforts. John Homppi
To retrieve the Linux files used in this example (15K ) via email, send your name and address to tfortin@vianet.on.ca ( for our snail mail list ) requesting "LINUX EXAMPLE" and we will send the example via email. After you receive the LinuxEg.tar.gz file you must decompress it with: gunzip LinuxEg.tar.gzand then untar it with: tar -xvf LinuxEg.tar |
|