⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mon_test.c

📁 一个串口通讯的c语言的例子
💻 C
字号:
// 监控程序
//							POS-前置机间电文全局说明

//	起始位		电文长度		传输协议数据单元		交易数据(含MAC)	停止位	校验和
//	 1位			  2位			5位									  1位	  1位

//	起始位-------------用以同步POS和前置机间通讯的数据位,并非8583规定。一般定为X’02’。
//	电文长度-----------此项长度为2字节,用于指示一段完整电文的长度。它的传输格式为BCD。举例来说,它用X‘0122‘表示电文长度为122Bytes。?注意此长度不含它本身的2字节,不含起始位1字节,不含停止位1字节,不含校验和1字节。因此它的值为整个完整电文长度减5。
//	传输协议数据单元---长度为5字节,它的传输格式为X‘60xxxx’。它在网控器通讯中起数据分流作用。
//	交易数据-----------涉及应用的具体数据,采用ISO8583标准进行组织,各域按位序号递增排列。
//	停止位-------------对应起始位,并非8583规定。一般定位X’03’。
//	校验和-------------用以确保POS-前置机间电文正确传输的手段,各厂家均采用相同算法。

//						交易数据部分(包括各bitmap位)的详尽描述

//	ISO8583规定,任何交易电文数据的格式应该是这样的:
//	信息类型		位图表	相应于位图表的数据元素(不含位图表)

//	系统对各种信息类型已做定义,均为4位数字,应采用BCD格式传输,占2字节。例如POS联机签到的信息类型的传输格式为X‘0800’。
//	位图表为1或2个字节的索引表,它通过将各bit置0或1来指示各域的使用情况。位图表本身总是占有第一域,虽如此,位图表的第一bit还是被置为0。
//	除位图表以外、按域号递增顺序排列的其余各数据元素。
#include <stdio.h>						/* Standard input/output definitions */#include <string.h>						/* String function definitions */#include <unistd.h>						/* UNIX standard function definitions */#include <fcntl.h>						/* File control definitions */#include <errno.h>						/* Error number definitions */#include <termio.h>						/* POSIX terminal control definitions */#include <sys/time.h>#include <sys/select.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <time.h>#include <math.h>#include <stdlib.h>#include <sys/signal.h>#include "posmsg.c"
#include "comport.c"
#include "tools.c"						// 一些转换函数
//#include "buflist.c"					// 双向链表

#define PROMPT	"你想终止程序吗?\n"
char *prompt = PROMPT;

int msqid;
int iPortDevice,oPortDevice;char * chrHostName = "localhost";	// bad functionint iPort;							// = 11001;long dnum=0,znum=0,snum=0,fnum=0,xnum=0;//待处理数 当前进程数 处理成功数 处理失败数 需处理数/**************************** start of tools ****************************/char addCheckByte(u_char *buffer,int len){	char lrc='\x00',etx='\x03';		// stop byte	int i=0;			for(i=0;i<(len+2);i++){			// len + 2Byte包长度		lrc ^=buffer[i];	}	lrc ^=etx;						// 与1Byte停止位异或		return lrc;}void getTPDU(unsigned char *buffer,unsigned char *tpdu){		//取传输协议数据单元	int i=0;	for(i=0;i<5;i++)		tpdu[i]=buffer[i+3];}void chgTPDU(u_char *in,u_char *out){	out[0]=in[0];	out[1]=in[3];	out[2]=in[4];	out[3]=in[1];	out[4]=in[2];}void setPackLen(int len,char *packlen){	int temp1;	int temp2;	//printf("Len=%d\n",len);	temp1=len/100;	temp2=len%100;		//printf("temp1=%d\n",temp1);	//printf("temp2=%d\n",temp2);	packlen[0]=(temp1/10)<<4 | temp1%10;	packlen[1]=(temp2/10)<<4 | temp2%10;	packlen[2]='\0';	//printf("packlen[0]=%02x\n",packlen[0]);	//printf("packlen[1]=%02x\n",packlen[1]);}void resPackage(u_char *pack,u_char *tpdu,int len,u_char *buffer){	char stx='\x02';	//起始标记	char etx='\x03';	//结束标记	char lrc='\x00';	//校验位	char *packlen;		//长度	u_char *rcvtpdu;		//协议数据域	int i;		packlen=(char *)malloc(3);	memset(packlen,0x0,3);	rcvtpdu=(u_char *)malloc(5);	memset(packlen,0x0,5);	//set STX	buffer[0]=stx;	//printf("buffer[0]=%02x\n",buffer[0]);	setPackLen(len+5,packlen);	buffer[1]=packlen[0];	buffer[2]=packlen[1];	//change TPDU	chgTPDU(tpdu,rcvtpdu);	/*	for(i=0;i<5;i++){		printf("tpdu[%d]=%02x-chg-",i,tpdu[i]);		printf("%02x\n",rcvtpdu[i]);	}	*/	for(i=0;i<5;i++)		buffer[i+3]=rcvtpdu[i];		for(i=0;i<len;i++)		buffer[i+8]=pack[i];		//set ETX	buffer[len+8]=etx;	buffer[0]=stx;  //???	//set lrc	buffer[len+9]=addCheckByte(buffer+1,len+5);	//end	buffer[len+10]='\0';	//printf("\n打包后返回数据:\n");	//for(i=0;i<len+10;i++)	//	printf("Receive Package[%d]=[%02x]\n",i,buffer[i]);	free(packlen);	free(rcvtpdu);}void mylog(char *filename,char *log,int len){	FILE *fd;	int k;		if( (fd  = fopen( filename, "a+" )) == NULL ){		printf("\n\r[ERROR]: Open log file failure\n" );		exit(0);	}		printf("\n\r写日志\n" );   	fwrite(log,sizeof(char),len,fd);	fflush(fd);	fclose(fd);}//读二进制文件
int readfile(char *filename,unsigned char *buf){
	FILE *stream;
	int ch ,len = 0;

	if( (stream = fopen( filename,"rb")) == NULL ){
		printf( "文件打开失败!\n" );
		return -1;
	}

	while ((ch = fgetc(stream)) != EOF){
		buf[len++] = (unsigned char)ch;
//		printf( "[%02x]",ch );
	}

	fclose( stream );
	return len;
}
/**************************** end of tools ****************************///显示状态信息
void disp_sta(int x,int y,int code){	          
    switch(code){
		case 0:		printf("\033[%d;%dH%s",x,y,"                                                                                ");
			break;
		case 1:		printf("\033[%d;%dH%s",x,y,"正常");
			break;
		case 2:		printf("\033[%d;%dH%s",x,y,"无效交易");
			break;
		case 3:		printf("\033[%d;%dH%s",x,y,"无效返回码");
			break;
		case 4:		printf("\033[%d;%dH%s",x,y,"不允许交易");
			break;
		case 5:		printf("\033[%d;%dH%s",x,y,"超出限额");
			break;
		case 6:		printf("\033[%d;%dH%s",x,y,"响应超时");
			break;
		case 7:		printf("\033[%d;%dH%s",x,y,"交易成功");
			break;
		case 8:		printf("\033[%d;%dH%s",x,y,"无效操作");
			break;
		case 9:		printf("\033[%d;%dH%s",x,y,"格式错误");
			break;
		case 10:	printf("\033[%d;%dH%s",x,y,"向串口写回应报文给NCA...");
			break;
		case 11:	printf("\033[%d;%dH%s",x,y,"从 com 接收需处理的数据");
			break;
		case 12:	printf("\033[%d;%dH%s",x,y,"向 socket 送需处理数据...");
			break;
		case 13:	printf("\033[%d;%dH%s",x,y,"没有得到 com 数据!");
			break;
		case 14:	printf("\033[%d;%dH%s",x,y,"接收已处理数据...");
			break;
		case 15:	printf("\033[%d;%dH%s",x,y,"写完串口!");
			break;
		case 16:	printf("\033[%d;%dH%s",x,y,"没有得到 socket 数据!");
			break;
		case 17:	printf("\033[%d;%dH%s",x,y,"没有读到串口数据!");
			break;
		default:	printf("\033[%d;%dH%s",x,y,"                                                                      ");
	}
}
void draw_monitor_screen(){
//	int i;
	printf("\033[2J\n");	printf("\033[4;1H┌──────────────────────────────────────┐");
	printf("\033[5;1H│                    农信POS交易系统V1.0 -- 交易监控屏幕                     │");
	printf("\033[6;1H├──────┬──────────┬────┬───┬────┬──────┤");
	printf("\033[7;1H│待处理数    │正处理数            │成功数  │失败数│需处理数│当前状态    │");
	printf("\033[8;1H├──────┼──────────┼────┼───┼────┼──────┤");
//	for(i=0;i<10;i++)
//		printf("\033[%d;1H│            │                    │        │      │        │            │",i+9);
	printf("\033[9;1H│            │                    │        │      │        │            │");
    printf("\033[10;1H├──────┴──────────┴────┴───┴────┴──────┤");
	printf("\033[11;1H│提示∶                                                                      │");
	printf("\033[12;1H└──────────────────────────────────────┘");
//	printf("\033[%d;%dH%s",13,2,"待处理的数据");//	printf("\033[%d;%dH%s",22,2,"已处理的数据");}

// 更新监视数据
void upinfo(){
	uchar buf[30];

	printf("\033[%d;%dH%d",9,5,dnum);
	printf("\033[%d;%dH%d",9,20,znum);
	printf("\033[%d;%dH%d",9,40,snum);
	printf("\033[%d;%dH%d",9,50,fnum);
	printf("\033[%d;%dH%d",9,60,xnum);

	disp_sta(9,70,1);

	return;
}
// 显示交易数据信息
void dispdata(int current,unsigned char * pub,int len){
	uchar buf[30],i,dispflg;
    unsigned long amount;

	printf("\033[%d;%dH\n",current,0);
	for (i=0;i<len;i++)		printf( "[%02x]",pub[i] );

	return;
}//	处理信号void ctrl_c_op(int signo){
	char c;
	write(STDERR_FILENO,prompt,strlen(prompt));
	fflush(stdin);
	c = getchar();
	if (c == 'y'|| c == 'Y'){
		delmsg(msqid);// 删除待处理消息队列
		exit(0);
	}
}
//主程序int main(int argc,char *argv[]){	unsigned long addrlong;	unsigned char buffer[2048],rcvBuf[1024],rcvPack[1024],tpdu[6];	int rcvLen = 0,packlen,rec,i,fdw,fdr,loglen,pMaxNum;	char *pCOM,logfile[10]="jznx.log",logmsg[1024];	struct sigaction act;							// 设置退出信号
	int msgqtype;									// 1 为从 com 到 mon ,2 为从 mon 到 socketc ,3 为从 socketc 到 mon	//	act.sa_handler = ctrl_c_op;
	sigemptyset(&act.sa_mask);						// 将信号集合设置为空
	act.sa_flags = 0;
	if(sigaction(SIGQUIT,&act,NULL) < 0){			// CTRL-\ 退出当前进程,并生成主存储文件
		fprintf(stderr,"Install Signal Action Error:%s\n\a",strerror(errno));
		exit(1);
	}
	if(argc>2){										// 得到输入参数(串口设备名,Socket端口,调试输出标致)		pCOM=argv[1];		pMaxNum=atoi(argv[2]);	}else{		strcpy(logmsg,"\nPlease input Serial port & max process number, eg:\nmon /dev/tty2a 10\n");		loglen=strlen(logmsg);		logmsg[loglen]='\0'; 		mylog(logfile,logmsg,loglen);									// 写日志		printf("%s",logmsg);		exit(0);	}	if( (fdw=open(pCOM,O_WRONLY))<0||(fdr=open(pCOM, O_RDONLY))<0){		// 打开读写端口		memset(logmsg,0,100);		strcpy(logmsg,"\n\r[ERROR]: Open serial port for write failure\n");		loglen=strlen(logmsg);		logmsg[loglen]='\0'; 		mylog(logfile,logmsg,loglen);									// 写日志		return (-1);	}	setAttr(fdr);	setAttr(fdw);	setNowait(fdr);	setNowait(fdw);
	msqid = createmsg(0777|IPC_CREAT);									// 创建消息队列的 server 端

	draw_monitor_screen();	printf("\n");	while(1){		printf("\n开始从串口读数据...\n");		packlen = 0;		rec = readPort(fdr,buffer,&packlen);		printf("读到 %i 个数据.\n",packlen);		if(rec < 1){			printf("没有读到 %s 上的数据!\n",pCOM);//			disp_sta(11,9,-1);
//			disp_sta(11,9,17);
			buffer[0] = '\0';			packlen = 1;		}else{			printf("向 mon 送待处理数据...\n");			xnum++;											// 需处理数据数加一
			dnum++;											// 待处理数据数加一
		}		msgqtype = 1;		sendmsgs(buffer,packlen,msqid,msgqtype);						// 发送待处理的数据

		if (znum < pMaxNum){
			printf("从 com 接收需处理的数据\n");//			disp_sta(11,9,-1);
//			disp_sta(11,9,11);
			msgqtype = 1;			packlen = receivemsg(buffer,msqid,msgqtype);				// 接收需处理的数据		}else{															// 进程上限发空数据
			msgqtype = 1;			buffer[0] = '\0';
			packlen = 1;		}
		if(buffer[0] <> '\0'){											// 有需处理的数据			getTPDU(buffer,tpdu);										// 取得传输协议数据单元			znum++;											// 正处理数据数加一
			printf("向 socket 送需处理数据...\n");//			disp_sta(11,9,-1);
//			disp_sta(11,9,12);
//			for(i=14;i<21;i++)		disp_sta(i,1,0);
//			dispdata(13,buffer,packlen);								// 显示交易需处理数据信息
		}else{
			printf("没有得到 com 数据!\n");//			disp_sta(11,9,-1);
//			disp_sta(11,9,13);
		}
		msgqtype = 2;		sendmsgs(buffer,packlen,msqid,msgqtype);						// 发送需处理的数据
		printf("启动SOCKET进程...\n");		system("socketc 11001 30 0&");	// socket 端口,进程生存时限(秒),调试信息标致
		printf("接收已处理数据...\n");//		disp_sta(11,9,-1);
//		disp_sta(11,9,14);
		msgqtype = 3;		packlen = receivemsg(buffer,msqid,msgqtype);					// 接收已处理的数据		if( buffer[0] <> '\0'){											// 有已处理的数据			snum++;											// 处理成功数加一			znum--;											// 正处理数据数减一			dnum--;											// 待处理数据数减一			printf("报文打包...\n");//			dispdata(22,buffer,packlen);								// 显示交易已处理数据信息
			rcvLen = packlen+10;			memset(rcvPack,0,rcvLen);			resPackage(buffer,tpdu,packlen,rcvPack);					// 打包			printf("向串口写回应报文给NCA...\n");//			disp_sta(11,9,-1);
//			disp_sta(11,9,10);
			writePort(fdw,rcvPack,rcvLen);								// 写串口			printf("写完串口!\n");//			disp_sta(11,9,-1);
//			disp_sta(11,9,15);
		}else{
			if (packlen > 1){				fnum++;											// 处理失败数加一				znum--;											// 正处理数据数减一				dnum--;											// 待处理数据数减一			}			printf("得到 socket 空数据!\n");//			disp_sta(11,9,-1);
//			disp_sta(11,9,16);
		}
//		upinfo();														// 更新监视数据
	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -