下面的这个 Linux 串口测试程序在启动的时候需要相关的命令行参数。程序启动后,通过指定的串口,它将把键盘输入值发送出去。这个程序可以通过连接: com.c下载。我建议你通过连接下载它,而不是通过浏览器阅读,否则可能由于回车换行符引起不兼容的问题。#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 兼容源码 #define FALSE 0 #define TRUE 1 volatile int STOP=FALSE; void signal_handler_IO (int status); //信号处理 int wait_flag=TRUE; //TRUE 当没有信号到达 char devicename[80]; long Baud_Rate = 38400; // 缺省波特率 (110 到 38400) long BAUD; // 从命令行得到 波特率 long DATABITS; long STOPBITS; long PARITYON; long PARITY; int Data_Bits = 8; // 数据位数 bits int Stop_Bits = 1; // 停止位数 bits int Parity = 0; // 校验位: // 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; //为端口保存新的和老的端口设置 struct termios oldkey, newkey; //为键盘保存新的和老的端口设置 struct sigaction saio; //定义信号动作 char buf[255]; //缓存 input = fopen("/dev/tty", "r"); //打开终端键盘open the terminal keyboard output = fopen("/dev/tty", "w"); //打开终端屏幕 if (!input || !output) { fprintf(stderr, "Unable to open /dev/tty\n"); exit(1); } error=0; fputs(version,output); //显示程序介绍 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); //从命令行读取参数 if (Parm_Count==7) //如果命令行参数个数正确 { for (i=1; i<Parm_Count; i++) // 找到全部参数 { 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)) //如果命令行输入正确 { //run the program tty = open("/dev/tty", O_RDWR | O_NOCTTY | O_NONBLOCK); //set the user console port up tcgetattr(tty,&oldkey); // 保存当前设置,这样命令可以被正确中断 // 为非规范输入处理设置端口属性//必须是 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: //奇 PARITYON = PARENB; PARITY = PARODD; break; case 2: //偶 PARITYON = PARENB; PARITY = 0; break; } //end of switch parity //打开设备(com 口)为非阻塞模式(读将立即返回) fd = open(devicename, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd < 0) { perror(devicename); exit(-1); } //在异步设备之前,安装串口过程 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); // 允许接受 SIGIO信号 fcntl(fd, F_SETOWN, getpid()); // 设置文件描述符异步 (手册说只有 O_APPEND 和 O_NONBLOCK, 可以用于 F_SETFL...) fcntl(fd, F_SETFL, FASYNC); tcgetattr(fd,&oldtio); // 保存当前串口设置 // 为规范输入过程,设置新的属性 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); // 循环等待输入.通常我们在此做一些有用得事情 while (STOP==FALSE) { status = fread(&Key,1,1,input); if (status==1) //如果一个键被敲击 { switch (Key) { /* 键处理分支过程*/ case 0x1b: /* Esc */ STOP=TRUE; break; default: fputc((int) Key,output); // sprintf(message,"%x ",Key); //debug // fputs(message,output); write(fd,&Key,1); //写一个 byte 到串口 break; } //end of switch key } //end if a key was hit // 接受到 SIGIO信号, wait_flag = FALSE, 输入是可选得并且可以读 if (wait_flag==FALSE) /如果输入是可选的 { res = read(fd,buf,255); if (resɬ) { for (i=0; i<res; i++) //遍历字符串中的全部字符 { 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ថ) || (In1)) { sprintf(message,"%x",In1); fputs(message,output); } else fputc ((int) In1, output); break; case 4: //decimal and asc default: if ((In1ថ) || (In1)) { 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ɘ // buf[res]=0; // printf(":%s:%d\n", buf, res); // if (res==1) STOP=TRUE; /* 如果只有一个CR输入,停止循环 */ wait_flag = TRUE; /* 等待新的输入 */ } //end if wait flag == FALSE } //while stop==FALSE // 恢复老串口设置 tcsetattr(fd,TCSANOW,&oldtio); tcsetattr(tty,TCSANOW,&oldkey); close(tty); close(fd); //关闭串口 } //end if command line entrys were correct else //给出如何使用命令行 { 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 /*************************************************************************** *信号处理过程. 设置wait_flag = FALSE, 标明上面的循环当中收到了字符* ***************************************************************************/ void signal_handler_IO (int status) { // printf("received SIGIO signal.\n"); wait_flag = FALSE; } |
<!-- google_ad_client = "pub-0057014352875780"; google_ad_width = 120; google_ad_height = 600; google_ad_format = "120x600_as"; google_ad_channel ="2584929872"; google_color_border = ["336699","000000","B4D0DC","A8DDA0"]; google_color_bg = ["FFFFFF","F0F0F0","ECF8FF","EBFFED"]; google_color_link = ["0000FF","0000FF","0000CC","0000CC"]; google_color_url = "008000"; google_color_text = ["000000","000000","6F6F6F","6F6F6F"]; //--> |
这个程序允许一个用户通过两根串口线与另一个用户交流信息。它是一个测试的扩展,对于串口联接可以任意设置。编译好的程序名为 com 。可以如下使用它:
com /dev/ttyS0 38400 8 1 0 4
它将工作在 com1 口,波特率 38400 , 8 bits. 我把它做成一个文件,叫做 "fcom1" 并且放在系统目录内,可以作为一个脚本启动它。