`

CTDP linux 程序员手册 C和C++编程(12)一个 Linux 串口测试例子

阅读更多

下面的这个 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&#60Parm_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" 并且放在系统目录内,可以作为一个脚本启动它。
google_ad_client = "pub-2416224910262877"; google_ad_width = 728; google_ad_height = 90; google_ad_format = "728x90_as"; google_ad_channel = ""; google_color_border = "E1771E"; google_color_bg = "FFFFFF"; google_color_link = "0000FF"; google_color_text = "000000"; google_color_url = "008000";
分享到:
评论

相关推荐

    CTDP:中文文本数据处理

    1、将文件夹中所有的txt文件中的内容,按行读取,每一行作为一个post,对每一个post以所有txt中的内容作为全体计算tf-idf,输出为与原始txt及每一行对应的tf-idf。由于结果包含大量的0,所以采取了稀疏矩阵的存储...

    型岩溶槽谷区降雨条件下地下河水质短时间尺度变化过程研究―――以重庆南山老龙洞地下河为例① (2012年)

    采用CTDP300多参数水质自动记录仪对重庆市南山老龙洞地下河出口处的地下水在降雨条件下水位、水温、pH值和电导率进行监测,以及2h时间间隔的地下水水化学指标(HCO3- ,Ca2+ ,Mg2+ ,NO3- ,PO34- ,SO24- , Fe2+ ,Mn2+ ,...

    川东槽谷区岩溶泉水物理化学动态特征及其环境效应研究———以重庆青木关岩溶槽谷姜家泉为例 (2009年)

    以重庆青木关岩溶槽谷姜家泉野外观测试验基地为例,利用CTDP300多参数水质自动记录仪、NITRATAXplussc在线硝氮分析仪及HOBO小型气象站,分别对岩溶泉在不同降雨条件下水化学的动态变化特征进行了监测研究。结果表明:...

    第五次作业函数第一题代码

    第五次作业函数第一题--

    基于深度学习的作物病害诊断内含数据集和运行环境说明.zip

    本项目旨在利用深度学习方法实现作物病害的自动诊断。作物病害是农业生产中的重要问题,及时诊断和处理对于减少产量损失至关重要。 我们采用深度学习算法,通过分析作物的图像,实现对病害的自动识别和分类。项目使用的数据集包括公开的作物病害图像数据集,如ISIC等,并进行了预处理,包括图像增强、分割和特征提取等。 在运行环境方面,我们使用Python编程语言,基于TensorFlow、PyTorch等深度学习框架进行开发。为了提高计算效率,我们还使用了GPU加速计算。此外,我们还采用了Docker容器技术,确保实验结果的可重复性。 项目完成后,将实现对作物病害的快速、准确诊断,为农业生产提供有力支持,有助于减少产量损失。同时,项目成果也可应用于其他图像识别和分类任务。

    机械设计CD驱动印刷设备step非常好的设计图纸100%好用.zip

    机械设计CD驱动印刷设备step非常好的设计图纸100%好用.zip

    tensorflow-2.7.2-cp37-cp37m-manylinux2010-x86-64.whl

    python烟花代码

    python烟花代码示例

    附件中是一个简单的烟花效果的代码示例: 在Python中,可以使用多种方式来模拟烟花效果,其中一种常用的方法是使用turtle模块,它提供了一个画布和一个小海龟,可以用来绘制各种图形。 这段代码首先导入了turtle模块和random模块,然后在屏幕上绘制了10次烟花爆炸的效果。每次爆炸都是由5个小圆组成,颜色随机选择,圆的大小也是随机的。 请注意,这段代码需要在支持turtle模块的Python环境中运行,并且需要有图形界面的支持。如果你在没有图形界面的环境中(比如某些服务器或者命令行界面),这段代码可能无法正常运行。

    商业化产品经理,到底如何实现产品商业化?.docx

    商业化产品经理,到底如何实现产品商业化?.docx

    Panduit 工业以太网部件内部销售指南

    Panduit 工业以太网部件内部销售指南

    Java版三维装箱代码示例

    在Java中,实现一个三维装箱(也称为三维背包问题)的算法通常涉及到组合优化和动态规划。这个问题是一个典型的优化问题,其中目标是在三个维度的限制下最大化价值的总和。下面是一个简单的Java代码示例,它使用动态规划来解决三维装箱问题。 请注意,这个代码只是一个简单的示例,它假设所有物品的第三个维度的大小都是1,并且没有给出如何回溯选择物品的完整逻辑。在实际应用中,三维装箱问题可能更加复杂,需要考虑所有三个维度的限制,并且可能需要更复杂的算法来解决。 此外,这个问题的解决方案可能需要根据具体问题的要求进行调整,例如物品是否可以分割、是否允许超过一个的物品等。如果你有特定的问题描述或者需要进一步的帮助,请提供更多的细节。

    常用品牌EPLAN部件库

    常用品牌EPLAN部件库

    单片机开发的教程.doc

    单片机开发的教程可以分为以下几个步骤: 1. 了解单片机基础知识:在学习单片机开发之前,需要了解单片机的相关知识,包括单片机的基本结构、指令系统、编程语言等。 2. 选择开发板:选择一款适合自己学习开发板的型号和厂商,通常需要关注开发板的性价比、开发环境是否友好等因素。 3. 学习开发环境:根据所选的开发板,学习相关的开发环境和使用方法,例如Keil、IAR等集成开发环境。 4. 掌握编程语言:单片机常用的编程语言包括C语言和汇编语言,根据实际情况选择其中一种进行学习。 5. 基础操作:熟悉单片机的引脚定义和IO口配置,了解单片机的启动代码,可以通过修改启动代码进行基本功能调试。 6. 综合实践:根据具体项目需求,进行单片机开发的综合实践。在实践中需要掌握如何编写程序、如何进行硬件调试、如何使用相关工具软件等技能。 下面是一个单片机开发的简单教程介绍: 首先,确定所使用的单片机型号和开发板类型。在这个阶段,需要查阅相关资料,了解开发板的规格书、芯片规格等基本资料。 其次,安装并配置开发环境。根据所选的开发板,安装相应的集成开发环境(IDE),并配置好开发环境。 接着,学习并掌

    Q1.ipynb

    Q1.ipynb

    (自适应手机端)IT网络建站公司pbootcms模板 互联网营销企业网站源码下载.zip

    (自适应手机端)IT网络建站公司pbootcms模板 互联网营销企业网站源码下载.zip

    Bematech 激光扫描器用户手册

    Bematech 激光扫描器用户手册

    激励视频接入文档.pdf

    激励视频接入文档.pdf

    java jdk1.8 202版本下载window linux打包

    java jdk1.8 202版本下载window linux打包

    Lite Beam M5快速指南 Lite Beam M5天线设置指南

    Lite Beam M5快速指南

    互联网金融导论.docx

    互联网金融导论.docx

Global site tag (gtag.js) - Google Analytics