Chinaunix首页 | 论坛 | 博客
  • 博客访问: 420776
  • 博文数量: 117
  • 博客积分: 5235
  • 博客等级: 大校
  • 技术积分: 1775
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-12 15:51
文章分类

全部博文(117)

文章存档

2012年(9)

2011年(2)

2010年(21)

2009年(13)

2008年(72)

我的朋友

分类: LINUX

2009-03-18 10:30:31

背景:
    与硬件打资产的程序最简单者应属串口的通信,下面是来自于ibm的串口程序教程及代码。也许是一个好的开始。

正文:
1. 串口常识
    串行口的典型代表是RS-232-C 及其兼容插口,25 针串行口还具有20mA 电流环接
口功能,用9,11,18,25针来实现。
    RS-232-C 是美国电子工业协会EIA(Electronic Industry Association)制定的一种串行物理接口标准。RS 是英文“推荐标准”的缩写,232 为标识号,C 表示修改次数。RS-232-C 总线标准设有25 条信号线,包括一个主通道和一个辅助通道,在多数情况下主要使用主通道,对于一般双工通信,仅需几条信号线就可实现,如一条发送线、一条接收线及一条地线。
    RS-232-C 标准规定的数据传输速率为每秒50,75,100,150,300,600,1200,2400,4800,9600,19200 波特。
    一般微机提供标准的RS232C 接口,该接口采用负逻辑,与CMOS、TTL 电路的相连需要专用集成电路进行电平转换。一般应用情况下,RC232C 的最高传输速率为20 kb/s, 最大传输线长为30 米。相比较而言,它的传输速率低、传输距离近、抗共模干扰能力差,在条件较恶劣的现场控制中,很难实现数据的正常传输和获取。
    在要求通信距离为几十米到上千米时,广泛采用 RS485 接口。RS485 采用差分接收和驱动,提高抗共模干扰驱动能力,并且提供多点应用,同一线上最多可接32 个驱动器和接收器,最大传输速率10Mb/s(12m),最大传输距离为1200m(10kb/s),可以较好的实现现场数据的获取和控制。
2. 编程流程
2.1 头文件
2.2 打开串口
2.3 设置串口
核心是设置一个结构:

struct termio
{    unsigned short c_iflag;    /* 输入模式标志 */    
    unsigned short c_oflag;        /* 输出模式标志 */    
    unsigned short c_cflag;        /* 控制模式标志*/    
    unsigned short c_lflag;        /* local mode flags */    
    unsigned char c_line;         /* line discipline */    
    unsigned char c_cc[NCC]; /* control characters */
};


2.4 读写串口
2.5 关闭串口
3. 实例代码

#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>

#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 //POSIX compliant source

#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

void signal_handler_IO (int status); //definition of signal handler

int wait_flag=TRUE; //TRUE while no signal received

char devicename[80];
long Baud_Rate = 38400; // default Baud Rate (110 through 38400)

long BAUD; // derived baud rate from command line

long DATABITS;
long STOPBITS;
long PARITYON;
long PARITY;
int Data_Bits = 8; // Number of data bits

int Stop_Bits = 1; // Number of stop bits

int Parity = 0; // Parity as follows:

                  // 00 = NONE, 01 = Odd, 02 = Even, 03 = Mark, 04 = Space

int Format = 4;
FILE *input;
FILE *output;
int status;

main(int Parm_Count, char *Parms[])
{
   char version[80] = " POSIX compliant Communications test program version 1.00 4-25-1999\r\n";
   char version1[80] = " Copyright(C) Mark Zehner/Peter Baumann 1999\r\n";
   char version2[80] = " This code is based on a DOS based test program by Mark Zehner and a Serial\r\n";
   char version3[80] = " Programming POSIX howto by Peter Baumann, integrated by Mark Zehner\r\n";
   char version4[80] = " This program allows you to send characters out the specified port by typing\r\n";
   char version5[80] = " on the keyboard. Characters typed will be echoed to the console, and \r\n";
   char version6[80] = " characters received will be echoed to the console.\r\n";
   char version7[80] = " The setup parameters for the device name, receive data format, baud rate\r\n";
   char version8[80] = " and other serial port parameters must be entered on the command line \r\n";
   char version9[80] = " To see how to do this, just type the name of this program. \r\n";
   char version10[80] = " This program is free software; you can redistribute it and/or modify it\r\n";
   char version11[80] = " under the terms of the GNU General Public License as published by the \r\n";
   char version12[80] = " Free Software Foundation, version 2.\r\n";
   char version13[80] = " This program comes with ABSOLUTELY NO WARRANTY.\r\n";
   char instr[100] ="\r\nOn the command you must include six items in the following order, they are:\r\n";
   char instr1[80] =" 1. The device name Ex: ttyS0 for com1, ttyS1 for com2, etc\r\n";
   char instr2[80] =" 2. Baud Rate Ex: 38400 \r\n";
   char instr3[80] =" 3. Number of Data Bits Ex: 8 \r\n";
   char instr4[80] =" 4. Number of Stop Bits Ex: 0 or 1\r\n";
   char instr5[80] =" 5. Parity Ex: 0=none, 1=odd, 2=even\r\n";
   char instr6[80] =" 6. Format of data received: 1=hex, 2=dec, 3=hex/asc, 4=dec/asc, 5=asc\r\n";
   char instr7[80] =" Example command line: com ttyS0 38400 8 0 0 4 \r\n";
   char Param_strings[7][80];
   char message[90];

   int fd, tty, c, res, i, error;
   char In1, Key;
   struct termios oldtio, newtio; //place for old and new port settings for serial port

   struct termios oldkey, newkey; //place tor old and new port settings for keyboard teletype

   struct sigaction saio; //definition of signal action

   char buf[255]; //buffer for where data is put

   
   input = fopen("/dev/tty", "r"); //open the terminal keyboard

   output = fopen("/dev/tty", "w"); //open the terminal screen


   if (!input || !output)
   {
      fprintf(stderr, "Unable to open /dev/tty\n");
      exit(1);
   }

   error=0;
   fputs(version,output); //display the program introduction

   fputs(version1,output);
   fputs(version2,output);
   fputs(version3,output);
   fputs(version4,output);
   fputs(version5,output);
   fputs(version6,output);
   fputs(version7,output);
   fputs(version8,output);
   fputs(version9,output);
   fputs(version10,output);
   fputs(version11,output);
   fputs(version12,output);
   fputs(version13,output);
   //read the parameters from the command line

   if (Parm_Count==7) //if there are the right number of parameters on the command line

   {
      for (i=1; i<Parm_Count; i++) // for all wild search parameters

      {
         strcpy(Param_strings[i-1],Parms[i]);
      }
      i=sscanf(Param_strings[0],"%s",devicename);
      if (i != 1) error=1;
      i=sscanf(Param_strings[1],"%li",&Baud_Rate);
      if (i != 1) error=1;
      i=sscanf(Param_strings[2],"%i",&Data_Bits);
      if (i != 1) error=1;
      i=sscanf(Param_strings[3],"%i",&Stop_Bits);
      if (i != 1) error=1;
      i=sscanf(Param_strings[4],"%i",&Parity);
      if (i != 1) error=1;
      i=sscanf(Param_strings[5],"%i",&Format);
      if (i != 1) error=1;
      sprintf(message,"Device=%s, Baud=%li\r\n",devicename, Baud_Rate); //output the received setup parameters

      fputs(message,output);
      sprintf(message,"Data Bits=%i Stop Bits=%i Parity=%i Format=%i\r\n",Data_Bits, Stop_Bits, Parity, Format);
      fputs(message,output);
   } //end of if param_count==7

   if ((Parm_Count==7) && (error==0)) //if the command line entrys were correct

   { //run the program

      tty = open("/dev/tty", O_RDWR | O_NOCTTY | O_NONBLOCK); //set the user console port up

      tcgetattr(tty,&oldkey); // save current port settings //so commands are interpreted right for this program

      // set new port settings for non-canonical input processing //must be NOCTTY

      newkey.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
      newkey.c_iflag = IGNPAR;
      newkey.c_oflag = 0;
      newkey.c_lflag = 0; //ICANON;

      newkey.c_cc[VMIN]=1;
      newkey.c_cc[VTIME]=0;
      tcflush(tty, TCIFLUSH);
      tcsetattr(tty,TCSANOW,&newkey);

      switch (Baud_Rate)
      {
         case 38400:
         default:
            BAUD = B38400;
            break;
         case 19200:
            BAUD = B19200;
            break;
         case 9600:
            BAUD = B9600;
            break;
         case 4800:
            BAUD = B4800;
            break;
         case 2400:
            BAUD = B2400;
            break;
         case 1800:
            BAUD = B1800;
            break;
         case 1200:
            BAUD = B1200;
            break;
         case 600:
            BAUD = B600;
            break;
         case 300:
            BAUD = B300;
            break;
         case 200:
            BAUD = B200;
            break;
         case 150:
            BAUD = B150;
            break;
         case 134:
            BAUD = B134;
            break;
         case 110:
            BAUD = B110;
            break;
         case 75:
            BAUD = B75;
            break;
         case 50:
            BAUD = B50;
            break;
      } //end of switch baud_rate

      switch (Data_Bits)
      {
         case 8:
         default:
            DATABITS = CS8;
            break;
         case 7:
            DATABITS = CS7;
            break;
         case 6:
            DATABITS = CS6;
            break;
         case 5:
            DATABITS = CS5;
            break;
      } //end of switch data_bits

      switch (Stop_Bits)
      {
         case 1:
         default:
            STOPBITS = 0;
            break;
         case 2:
            STOPBITS = CSTOPB;
            break;
      } //end of switch stop bits

      switch (Parity)
      {
         case 0:
         default: //none

            PARITYON = 0;
            PARITY = 0;
            break;
         case 1: //odd

            PARITYON = PARENB;
            PARITY = PARODD;
            break;
         case 2: //even

            PARITYON = PARENB;
            PARITY = 0;
            break;
      } //end of switch parity

       
      //open the device(com port) to be non-blocking (read will return immediately)

      fd = open(devicename, O_RDWR | O_NOCTTY | O_NONBLOCK);
      if (fd < 0)
      {
         perror(devicename);
         exit(-1);
      }

      //install the serial handler before making the device asynchronous

      saio.sa_handler = signal_handler_IO;
      sigemptyset(&saio.sa_mask); //saio.sa_mask = 0;

      saio.sa_flags = 0;
      saio.sa_restorer = NULL;
      sigaction(SIGIO,&saio,NULL);

      // allow the process to receive SIGIO

      fcntl(fd, F_SETOWN, getpid());
      // Make the file descriptor asynchronous (the manual page says only

      // O_APPEND and O_NONBLOCK, will work with F_SETFL...)

      fcntl(fd, F_SETFL, FASYNC);

      tcgetattr(fd,&oldtio); // save current port settings

      // set new port settings for canonical input processing

      newtio.c_cflag = BAUD | CRTSCTS | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
      newtio.c_iflag = IGNPAR;
      newtio.c_oflag = 0;
      newtio.c_lflag = 0; //ICANON;

      newtio.c_cc[VMIN]=1;
      newtio.c_cc[VTIME]=0;
      tcflush(fd, TCIFLUSH);
      tcsetattr(fd,TCSANOW,&newtio);

      // loop while waiting for input. normally we would do something useful here

      while (STOP==FALSE)
      {
         status = fread(&Key,1,1,input);
         if (status==1) //if a key was hit

         {
            switch (Key)
            { /* branch to appropiate key handler */
               case 0x1b: /* Esc */
                  STOP=TRUE;
                  break;
               default:
                  fputc((int) Key,output);
// sprintf(message,"%x ",Key); //debug

// fputs(message,output);

                  write(fd,&Key,1); //write 1 byte to the port

                  break;
            } //end of switch key

         } //end if a key was hit

         // after receiving SIGIO, wait_flag = FALSE, input is available and can be read

         if (wait_flag==FALSE) //if input is available

         {
            res = read(fd,buf,255);
            if (res>0)
            {
               for (i=0; i<res; i++) //for all chars in string

               {
                  In1 = buf[i];
                  switch (Format)
                  {
                     case 1: //hex

                        sprintf(message,"%x ",In1);
                        fputs(message,output);
                        break;
                     case 2: //decimal

                        sprintf(message,"%d ",In1);
                        fputs(message,output);
                        break;
                     case 3: //hex and asc

                        if ((In1<32) || (In1>125))
                        {
                           sprintf(message,"%x",In1);
                           fputs(message,output);
                        }
                        else fputc ((int) In1, output);
                        break;
                     case 4: //decimal and asc

                     default:
                        if ((In1<32) || (In1>125))
                        {
                           sprintf(message,"%d",In1);
                           fputs(message,output);
                        }
                        else fputc ((int) In1, output);
                        break;
                     case 5: //asc

                        fputc ((int) In1, output);
                        break;
                  } //end of switch format

               } //end of for all chars in string

            } //end if res>0

// buf[res]=0;

// printf(":%s:%d\n", buf, res);

// if (res==1) STOP=TRUE; /* stop loop if only a CR was input */

            wait_flag = TRUE; /* wait for new input */
         } //end if wait flag == FALSE


      } //while stop==FALSE

      // restore old port settings

      tcsetattr(fd,TCSANOW,&oldtio);
      tcsetattr(tty,TCSANOW,&oldkey);
      close(tty);
      close(fd); //close the com port

   } //end if command line entrys were correct

   else //give instructions on how to use the command line

   {
      fputs(instr,output);
      fputs(instr1,output);
      fputs(instr2,output);
      fputs(instr3,output);
      fputs(instr4,output);
      fputs(instr5,output);
      fputs(instr6,output);
      fputs(instr7,output);
   }
   fclose(input);
   fclose(output);
} //end of main


/***************************************************************************
* signal handler. sets wait_flag to FALSE, to indicate above loop that *
* characters have been received. *
***************************************************************************/


void signal_handler_IO (int status)
{
// printf("received SIGIO signal.\n");

   wait_flag = FALSE;
}


文件:com.tar
大小:3KB
下载:下载

阅读(1045) | 评论(0) | 转发(0) |
0

上一篇:框架初建

下一篇:进程间通信 小总结

给主人留下些什么吧!~~