📄 sk.c
字号:
//注意: 此版本打印格式为山东省济南市地税局服务业机建筑业发票 2004.5.8#include <stdio.h> /*标准输入输出定义 */#include <stdlib.h> /*标准函数库定义 */#include <unistd.h> /*Unix标准函数定义 */#include <sys/types.h> /**/#include <sys/stat.h> /**/#include <fcntl.h> /*文件控制定义 */#include <termios.h> /*PPSIX终端控制定义*/#include <errno.h> /*错误号定义 */#include <time.h> /*时间函数*/#include <sys/time.h>//#include <sys/io.h>#include <getopt.h> #include <linux/lp.h> #include <string.h>#include <sys/ioctl.h>#include "sk.h"#include "error.h"//#include "TaxCtrlPro.h"//---------------------------------------------------------------------------#define FALSE -1#define TRUE 0#define USE_44B0_POS#define SKPORT 2 //定义 税控器接入 端口//#define TaxUnitPort 2 //com 1//#define SPRTPRINTER#define init_debug#define sm_debug//#define debug#define SprtPrinter //斯普瑞特打印机//#define GongDaLptPrinter //公达打印机//#define StarPrinter //Star打印机//#define debugint printinvoicetype; //设定打印发票类型: 1:餐饮;0:建筑;//---------------------------------------------------------------------------unsigned char *com_dev1 ="/dev/ttyS0"; //串口1//unsigned char *com_dev1 ="/dev/ttyUSB0"; //usb 1unsigned char *com_dev2 ="/dev/ttyS1"; //串口2unsigned char *com_dev3 ="/dev/ttyS2"; //串口3unsigned char *com_dev4 ="/dev/ttyS3"; //串口4/*const char *com_dev1 ="/dev/ttyS0";const char *com_dev2 ="/dev/ttyS1";const char *com_dev3 ="/dev/ttyS2";const char *com_dev4 ="/dev/ttyS3";*///---------------------------------------------------------------------------int execute_blackmark_flag=1; //execute_blackmark_flag=1:打印时检测黑标 =0:不检测黑标unsigned char sellpath[] = "/tmp/tmpsellnote.txt";int idComm1,idComm2,idComm3,idComm4; //串口 ID int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, 0};int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, 0};//---------------------------------------------------------------------------struct OneBillDate_struct //当前张发票信息结构{ unsigned char bill_type; char tax_items_list[6]; int item_total_money[6];};unsigned char User_Name[41]; //本税控器单位名称unsigned char User_ID[17]; //本税控器纳税人编码unsigned char User_Machine[17]; //本税控器机器编号unsigned char prevent_forge_code[25]; //防伪税控码//---------------------------------------------------------------------------void Show_Bill_Query_Info(struct Query_1 *checkData);void Show_boot_strap_init(struct TaxStatus *statusData);void Show_DAY_Query_Info(struct Query_2 *checkData);void Show_DECLARE_Query_Info(struct Query_3 *checkData);void Show_TAX_BringIntoEffect_Info(struct InvoiceListData *checkData);void ShowSaleData_wst(struct SaleData *nowSaleData);int JudgeNowBillNumberInfo(unsigned char *now_hex_bill_number,unsigned char *now_hex_billend_number);void Print_NoSoft_Line(unsigned char *Line_Str);int Boot_StrapRenewBill(void); //功能: 开机发票重现void m_dtrtoggle(int fd,int sec) { /* Posix - set baudrate to 0 and back */ struct termios tty, old; tcgetattr(fd, &tty); tcgetattr(fd, &old); cfsetospeed(&tty, B0); cfsetispeed(&tty, B0); tcsetattr(fd, TCSANOW, &tty); if (sec>0) { sleep(sec); tcsetattr(fd, TCSANOW, &old); }}//---------------------------------------------------------------------------//设置串口通信速率//fdtmp 类型 int 打开串口的文件句柄//speed 类型 int 串口速度void SetSpeed(int fdtmp, int speed){ int i; int status; int tmp; struct termios Opt; tmp=tcgetattr(fdtmp, &Opt); for(i= 0; i < sizeof(speed_arr) / sizeof(int); i++) { if(speed == name_arr[i]) { //tcflush(fd, TCIOFLUSH); cfsetispeed(&Opt, speed_arr[i]); cfsetospeed(&Opt, speed_arr[i]); Opt.c_cflag |= (CLOCAL | CREAD); Opt.c_lflag &=~(ICANON | ECHO | ECHOE | ISIG); //设置为RAW模式 Opt.c_oflag &=~OPOST; //设置为RAW模式 Opt.c_iflag &=~(IXON | ICRNL); //通讯中不处理控制字符 //tcflush(fdtmp,TCIOFLUSH); status = tcsetattr(fdtmp, TCSANOW, &Opt); if(status != 0) perror("tcsetattr fd1"); return; } tcflush(fdtmp,TCIOFLUSH); }}//---------------------------------------------------------------------------//设置串口数据位,停止位和效验位// fd 类型 int 打开的串口文件句柄*// databits 类型 int 数据位 取值 为 7 或者8*// stopbits 类型 int 停止位 取值为 1 或者2*// parity 类型 int 效验类型 取值为N,E,O,,Sint SetParity(int fd,int databits,int stopbits,int parity){ struct termios options; if( tcgetattr( fd,&options) != 0) { perror("SetupSerial 1"); return(-1); } options.c_cflag &= ~CSIZE; switch (databits) /*设置数据位数*/ { case 7: options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: fprintf(stderr,"Unsupported data size\n"); return (FALSE); } switch (parity) { case 'n': case 'N': options.c_cflag &= ~PARENB; /* Clear parity enable */ options.c_iflag &= ~INPCK; /* Enable parity checking */ break; case 'o': case 'O': options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'e': case 'E': options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD; /* 转换为偶效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'S': case 's': /*as no parity*/ options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; break; default: fprintf(stderr,"Unsupported parity\n"); return (FALSE); } /* 设置停止位*/ switch (stopbits) { case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: fprintf(stderr,"Unsupported stop bits\n"); return (FALSE); } /* Set input parity option */ if (parity != 'n') options.c_iflag |= INPCK; options.c_cc[VTIME] = 10; // 15 seconds options.c_cc[VMIN] = 0; tcflush(fd,TCIOFLUSH); /* Update the options and do it NOW */ if(tcsetattr(fd,TCSANOW,&options) != 0) { perror("SetupSerial 3"); return (-1); } return (0);}//---------------------------------------------------------------------------//打开串口int OpenDev(const char *Dev){ int fd = open( Dev, O_RDWR | O_NOCTTY); if ( (-1 == fd) || (-2 == fd) ) { /*设置数据位数*/ perror("Can't Open Serial Port"); return -1; } return fd;}//---------------------------------------------------------------------------//串口初始化int ComPortInit( int PortNo,int speed ){ unsigned char buf[80]; int fd_com=0; memset( buf,0,80 ); switch( PortNo ) { case 1: fd_com = OpenDev( com_dev1 ); break; case 2: fd_com = OpenDev( com_dev2 ); break; case 3: fd_com = OpenDev( com_dev3 ); break; case 4: fd_com = OpenDev( com_dev4 ); break; } if(fd_com > 0) SetSpeed( fd_com,speed ); else { sprintf( buf,"Can't Open Serial Port %d",PortNo ); return -1; } if( SetParity( fd_com,8,1,'N' )== FALSE ) { sprintf( buf,"Set COM%d Parity Error",PortNo ); return -2; } return fd_com; //返回 串口 ID}//---------------------------------------------------------------------------void MyDebugShow(unsigned char *data,int len){ #ifdef debug printf("Debug Info:"); for(int i=0;i<len;i++) printf(" %x",data[i]); printf("\n"); #endif ;}//功能: 用于串口接收数据(原因:'税控器发回的数据带有杂音,第一位不是0x1b,这时需要用此种方式接收)//参数: idcom:串口句柄// Buf:接收数据// TimeOutCnt:延时//返回: 0->数据接收正常; 1->接收失败;int ReceiveComData(int idComm,unsigned char *Buf,long TimeOutCnt){ int CtrlFlg = 0,cnt = 0,i = 0; unsigned char ch[]={0,0}; unsigned char check=0; //检查和 int err = 0; //idComm1 = ComPortInit( SKPORT , 9600 ); //if(idComm1 == -1) return 0x84; //串口不能打开 do{ if( read(idComm1,ch,1) == 1) { i = 0; switch(CtrlFlg) { case 0: if( ch[0] == 0x1B ) { Buf[ cnt ++ ] = 0x1B; check += ch[0]; CtrlFlg = 1;} break; case 1: if( ch[0] == 0x80 || ch[0] == 0x81 ) { Buf[ cnt++ ] = ch[0]; check += ch[0]; CtrlFlg = 2;} else CtrlFlg = 9; //接收到的'0x1b'为无效信息 break; case 2: Buf[cnt++] = ch[0]; //CMD No check += ch[0]; CtrlFlg = 3; break; case 3: Buf[cnt++] = ch[0]; check += ch[0]; if(Buf[3]==5) CtrlFlg = 5; //如果Buf[3]=5则表示返回数据长度为0 else CtrlFlg = 4; //lenth break; case 4: Buf[cnt++] = ch[0]; check += ch[0]; if( cnt+1 == (int)Buf[3] ) //if( cnt-1 == (int)Buf[3] ) CtrlFlg = 5; break; case 5: Buf[cnt++]= ch[0]; //接收到的检查和 if(ch[0] == check) //判断检查和 { CtrlFlg = 6; err = 0;} //接收结束 else { CtrlFlg = 8; err = 0xa1;} //检查和错误 break; } //end switch }//end if( ) i++; } while( CtrlFlg < 6 && (i < TimeOutCnt) ); //close(idComm1); //关闭串口 if(i == TimeOutCnt) err = 0x95; //接收失败 return err;}//---------------------------------------------------------------------------//功能: 用于接收税控器收到指令后返回的应答,并且判断接收是否正常//参数: idcom: 串口句柄// sendData: 已发送的命令// TimeOutCnt: 接收应答延时//返回: 0->应答正常; !=0->接收应答失败;int ReceiveResponsion(int idComm,unsigned char *sendData,long TimeOutCnt){ int i,err; unsigned char return_buf[20]; memset(return_buf,0x0,20); err = ReceiveComData(idComm,return_buf,10); if(err) return err; for(i=0;i<3;i++) if(return_buf[i] != sendData[i]) err = 0x95; //应答错误 return err;}//---------------------------------------------------------------------------//功能: 发送单个命令//参数: commandContent: 所发送的命令字符串// commandLength: 发送命令的长度 // returnBuf: 发送命令后返回的数据//返回: =0->正常 !=0->错误int SendOneCommand(unsigned char *commandContent,int commandLength){ int err=0x95,i,send_count=0; int write_len=0; unsigned char returnBuf[20]; for(i=0;i<(commandLength-1);i++) //产生检查和 commandContent[commandLength-1] = commandContent[commandLength-1] + commandContent[i]; //idComm1 = ComPortInit( SKPORT , 9600 ); //if(idComm1 == -1) return 0x84; //打开串口失败 memset(returnBuf,0x0,20); while(send_count<4) { /* for(i=0;i<commandLength;i++) { write_len = write(idComm1,commandContent+i,1); //'write'函数返回写数据长度 if(!write_len) {usleep(10); break;} } if(write_len!=1) ; else { err = ReceiveResponsion(idComm1,commandContent,10); if( !err ) { send_count = 8; err = 0;} send_count++; } */ write_len = write(idComm1,commandContent,commandLength); //'write'函数返回写数据长度 if(write_len == commandLength) { err = ReceiveResponsion(idComm1,commandContent,10); if( !err ) { send_count = 8; err = 0;} send_count++; } } //close(idComm1); //关闭串口 return err; //命令发送成功}//功能: 发送命令并且接收数据//参数: commandContent: 所发送的命令字符串// commandLength: 发送命令的长度 // returnBuf: 发送命令后返回的数据//返回: =0->正常 !=0->错误int SendCommand(unsigned char *commandContent,int commandLength,unsigned char *returnBuf){ int i,err; //idComm1 = ComPortInit( SKPORT , 9600 ); idComm1 = ComPortInit( SKPORT , 38400 ); if(idComm1 == -1) return 0x84; //打开串口失败 err = SendOneCommand(commandContent,commandContent[3]); //发送数据 #ifdef debug printf("SendOneCommand Return Value = %d\n",err); #endif if( err ) return err; //发送失败
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -