📄 pack_comm.c
字号:
/*-------------------------------------------------------------
功能:在一定通讯协议下与上位管理系统之间的数据包串口通讯
说明:符合国家标准GB18240.1-2003和GB18240.2-2003的税控机软件
日期:2003年6月12日
---------------------------------------------------------------*/
#include "include.h"
#define ANSWER_ACK 0X32
#define ANSWER_NAK 0X33
#define TOTAL_DATA_LEN 1024 //每包数据总长度
//#define FAU_DATA_START_ADD 0X40000
//uchar code bbb[]={//0x32,0};
//0x00 ,0x35 ,0x00 ,0x01 ,0xC9 ,0xCC ,0xC6 ,0xB7 ,0x30 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,0x00 ,0x00 ,0x00 ,0x00,0x00
//,0x00 ,0x20 ,0x4E ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
//0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x01 ,0x02 ,0x31 ,0x54 ,0x7E ,0x99 };
//==================================================================
void send_ACK_NAK(uchar command)
{
uchar buf[6];
uint crctemp;
buf[0]=0x68;
buf[1]=command;
buf[2]=0;
crctemp=crcxdata(2,buf+1);
buf[3]=crctemp;
buf[4]=crctemp>>8;
buf[5]=0x66;
send_str(6,buf);
}
//=================================================================
void Back_Outorder(uchar mode,uchar index,uchar len,uchar *out_data)
{
uint cs;
uchar data_len;
uchar buf[256];
if(mode==0)
{
buf[0]='E';
buf[1]='R';
send_str(2,buf);
}
else
{
buf[0]='O';
buf[1]='K';
buf[2]=index;
buf[3]=len+4;
memcpy(&buf[4],out_data,len);
data_len=buf[3];
cs=crcxdata((uint)data_len,buf);
buf[data_len]=cs>>8;
buf[data_len+1]=cs;
data_len+=2;
send_str(data_len,buf);
}
}
//==========================================================================================
//找滚动前的明细记录如:当前的扇区为1,找的是从第2扇区开始的符合条件的明细
//* startdate,uchar *enddate :起止时间
//*addr开始的地址,返回下一条的地址
//mode 0:从要开始的扇区头开始 1:以*add为地址开始找
//==================================================================================================
uchar LookUp_inv_list_roll(uchar * startdate,uchar *enddate,ulong *addr,uchar mode,struct record_struct *record)
{
struct record_addr_struct RecordAddr;
uchar i,j;
uchar tmp;
uchar sector; //扇区号
uint size;
ulong addr_tmp;
uint crc;
uchar finded,start;//是否找到需要的明细数据
uchar lrc;
uchar datatemp[10];
read_eeprom(RECORD_ADDR1,(uint)sizeof(RecordAddr),&RecordAddr);
crc=crcxdata((uint)sizeof(RecordAddr)-2,&RecordAddr);
if(crc!=RecordAddr.crc)
{
if(read_eeprom(RECORD_ADDR2,(uint)sizeof(RecordAddr),&RecordAddr))
return(READ_EEPROM_FAIL);
crc=crcxdata((uint)sizeof(RecordAddr)-2,&RecordAddr);
if(crc!=RecordAddr.crc)
return(CRC_ERROR);
}
//send_str((uint)sizeof(RecordAddr),&RecordAddr);
if(RecordAddr.record_addr==RECORD_START_ADDR) //没有写数据
return(1);
//从起始扇区顺序读
if(mode==0)
{
if(RecordAddr.start_sector!=RECORD_SECTOR[(uint)sizeof(RECORD_SIZE)-1])
{
size=0;
sector=RecordAddr.start_sector+1;//
//2005.8.14
for(i=RECORD_SECTOR[0],j=0;i<(RecordAddr.record_sector+1);i++,j++)size+=RECORD_SIZE[j]; //KBYTE
addr_tmp=(ulong)size*1024+RECORD_START_ADDR; //起始扇区的起始地址
//send_str(2,&size);
//send_str(4,&addr_tmp);
}
else return SEEK_FAIL;
}
else
addr_tmp=*addr;
start=1;
finded=0;
//send_str(4,&addr_tmp);
while(1) //没到最后写的一笔记录的结束地址或查找完毕
{
//-----先读出该票的项目数---------//
if(!start) addr_tmp++; //同扇区的下一张票的起始地址//去掉一张发票的经营项目数的数据
if(read_flash(addr_tmp,1,&tmp))return(READ_FLASH_FAIL);
if(tmp==0xFF)//没有写数据则换扇区
{
//2005.8.27
//if(mode==0)return SEEK_FAIL;
sector++;
if(sector>RECORD_SECTOR[(uint)sizeof(RECORD_SIZE)-1])
sector=RECORD_SECTOR[0];
//sector扇区的起始地址
size=0;
for(i=0,j=0;i<(uint)sizeof(RECORD_SIZE);i++,j++)
{ size+=RECORD_SIZE[j]; //KBYTE
if(((ulong)size*1024+RECORD_START_ADDR)>addr_tmp)
{ addr_tmp=(ulong)size*1024+RECORD_START_ADDR;break;}
}
if(read_flash(addr_tmp,1,&tmp))
return(READ_FLASH_FAIL);
if(tmp==0xFF)return SEEK_FAIL;
}
if(read_flash(addr_tmp+RECORD_LENGTH-1,1,&tmp))return(READ_FLASH_FAIL);
//读出记录全部信息
if(read_flash(addr_tmp,(uint)(RECORD_LENGTH+INVOICE_ITEM_LEN*tmp+1),record))//明细记录为:定长+变长
return(READ_FLASH_FAIL);
//send_str((uint)(RECORD_LENGTH+INVOICE_ITEM_LEN*tmp+1),record);
//校验
lrc=lrcdata(RECORD_LENGTH+INVOICE_ITEM_LEN*record->item_num,//record.item_num,
1,record);
if(lrc!=((uchar *)record)[RECORD_LENGTH+INVOICE_ITEM_LEN*record->item_num])//record.item_num])
return(LRC_ERROR);
//2005.7.26
memcpy(datatemp,record->date,4);
uzip_date(datatemp,datatemp);
//send_str(3,datatemp);
if(memcmp(datatemp,enddate,3)>0) //大于结束日期
return SEEK_FAIL;
if(memcmp(datatemp,startdate,3)>=0 &&
memcmp(datatemp,enddate,3)<=0) //找到
{
finded=1;
}
/*else //找到 不符合日期
{
if(start_addr_finded)
return OK;//查找完毕
}
*/
//2005.8.13
addr_tmp+=RECORD_LENGTH+(uint)INVOICE_ITEM_LEN*tmp; //该票的结束地址
size=0;
for(i=RECORD_SECTOR[0],j=0;i<RECORD_SECTOR[(uchar)sizeof(RECORD_SECTOR)];i++,j++)
size+=RECORD_SIZE[j]; //KBYTE
if((addr_tmp>=((ulong)size*1024+RECORD_START_ADDR))&&!finded) return SEEK_FAIL;//没找到
else if((addr_tmp>=((ulong)size*1024+RECORD_START_ADDR))&&finded) return OK;//查找完毕到最后一条找
if(addr_tmp==(ulong)size*1024+RECORD_START_ADDR) //该票的结束地址到了最后一个扇区的结束地址
{
addr_tmp=RECORD_START_ADDR;//开始扇区的起始地址
start=1;
}
else
start=0;
if(finded)
{
if(!start) addr_tmp++; //同扇区的下一张票的起始地址
*addr=addr_tmp;
return 0;
}
}
}
//======================================================
//按日期找日记录
uchar query_by_date(uchar *start_date,uchar *end_date,uint *start_num,uchar *day_re_num)
{
struct day_addr_struct da_addr;
struct day_struct da;
uchar error;
uchar num;
uint start;
ulong addr;
uchar head;
//-----读取日记录数据地址-----------//
error=read_eeprom(DAY_ADDR1,DAY_ADDR_LEN,&da_addr);
if(error) return READ_EEPROM_FAIL;
if(da_addr.crc!=crcxdata(DAY_ADDR_LEN-2,&da_addr))
{
error=read_eeprom(DAY_ADDR2,DAY_ADDR_LEN,&da_addr);
if(error) return READ_EEPROM_FAIL;
}
if(da_addr.crc!=crcxdata(DAY_ADDR_LEN-2,&da_addr)) return CRC_ERROR;
num=0;
head=0;
start=0;
*start_num=0;
for(addr=DAY_START_ADDR;addr<da_addr.day_addr;addr+=DAY_LEN_FH)//192
{
if(read_flash(addr,DAY_LEN_EM,da.date)) return READ_FLASH_FAIL;//64
start++;
//if(!((memcmp(da.date,start_date,3)>=0)&&(memcmp(da.date,end_date,3)>=0))) continue;
if(memcmp(da.date,start_date,3)<0) continue;
if(memcmp(da.date,end_date,3)>0) break;
//if(read_flash(addr,DAY_LEN_FH,buffer)) return READ_FLASH_FAIL;//192
if(!head){head=1;*start_num=start-1;}
num++;
}//end for
*day_re_num=num;
if(num>0){return 0; }
return NO_DATA;
}
//===================================================================
//根据开始包号读天记录
uchar read_day_re(uchar pack_num,uchar *buffer)
{
ulong addr;
addr=pack_num;
addr*=DAY_LEN_FH;
addr+=DAY_START_ADDR;
//addr=DAY_START_ADDR+(ulong)(pack_num*DAY_LEN_FH);
if(read_flash(addr,DAY_LEN_FH,buffer)) return READ_FLASH_FAIL;//192
return 0;
}
//==================================================================
/*void long_to_str(ulong lendata,uchar *buf)
{
buf[0]=lendata>>24;
buf[0]=lendata>>16;
buf[0]=lendata>>8;
buf[0]=lendata;
}*/
/*==================================================================
函数功能:数据包串口通讯
入口参数: trans_mode--通讯模式:0:接收1:发送2:其他
comm_func--通讯功能;
data_len--每个包的数据长度
出口参数:
返回值: ==POWER_OFF,则表示断电,返回
==CANCEL,取消操作
==0,通讯成功
==其他,通讯失败
全局变量: g_max_plu_no
编制人: 日期:2003-06-25
==================================================================*/
uchar Data_pack_transport(uchar trans_mode,uchar comm_func,uchar data_len)
{
uchar Hand,pack_tail,Hand_num,key;
uint pack_num,bc_pack_num,pack_crc,pack_length;
xdata uchar buf_tr[16],buff[TOTAL_DATA_LEN+9];// 1024+9,每包数据总长度
uchar per_pack_num;//每包数据的包数
//struct branch_struct xdata branch[MAX_BRANCH_NUM+1];
uint plu_num,i,pack_quotient,pack_remainder,LL,valid_data_len;
uchar j,error;
uchar check,q=0;
uchar buf[128];
ulong addtemp;
struct day_struct da;
struct delare_addr_struct declare_addr;
struct money_add_struct money_add;
//struct invoice_roll_struct *invoice_roll;
//struct record_struct inv_rec;
uchar ord_lenght;// = data_in[4] + 2 ;
uint cs;
uchar csh;
uchar csl;
uchar command_type;
uchar order_mode;
uchar data_index;
ulong start_num,end_num,tt;
#ifdef C6_VER
select_com(0);
#else
select_com(2);
#endif
//modify_rate(6);//57600
clear_rece_buffer();
plu_num=0;
LL=0;
per_pack_num=TOTAL_DATA_LEN/data_len; //一包可打的数据结构的个数如:数据结构为九个字节
//一包就可打113个数据结构
//------------握手------------//
do
{
if(low_pwr) return POWER_OFF;//如果断电了,则exit
openbacklight();
key=get_key();
if((trans_mode==0)||(trans_mode==1))
{
if(!rece(6,buf_tr))
{
if((buf_tr[1]==0x31)&&(buf_tr[5]==0x66))
{
send_ACK_NAK(ANSWER_ACK);
break;
}
else
{
send_ACK_NAK(ANSWER_NAK);
}
}
}
else
{
EA=0;
if(!rece(5,buff))
{
ord_lenght=buff[4]+2;
if(!rece((ord_lenght-5),&buff[5]))
{
cs = crcxdata((ord_lenght-2),&buff[0]);
csh = (cs&0xff00)>>8;
csl = (cs&0x00ff);
if(
(((buff[2]>=0x10) && (buff[2]<=0x19))||(buff[2]==0x01)||(buff[2]==0x56)||(buff[2]==0x60))
//&&((buff[ord_lenght-2] ==csh)&&(buff[ord_lenght -1] ==csl))
)
{
command_type=buff[2];
for(j=0;j<(ord_lenght-7);j++)buf[j]=buff[5+j];//保存命令数据
order_mode=ord_lenght-7; //收到的数据的长度
order_mode&=0x7f; //最高位为标志位
EA=1;
break;
}
else if(buff[2]==0x0)Back_Outorder(1,0,0,buff);//响应写机器编号时的联机回应
else Back_Outorder(0,0,0,buf_tr);
}
else Back_Outorder(0,0,0,buf_tr);
}
EA=1;
/*if(!rece(7,buf_tr))
{
ord_lenght = buf_tr[4] + 2 ;
cs = crcxdata((ord_lenght-2),&buf_tr[0]);
csh = (cs&0xff00)>>8;
csl = (cs&0x00ff);
if((buf_tr[0]==0x1b)&&(buf_tr[1]==0x10)&&(buf_tr[2]==0x1)
&&(buf_tr[3]==0x0)&&(buf_tr[5]==csh)&&(buf_tr[6]==csl)
)
{
buf_tr[0]='O';
buf_tr[1]='K';
buf_tr[2]=0;
buf_tr[3]=4;
cs = crcxdata(4,&buf_tr[0]);
buf_tr[4]=cs>>8;
buf_tr[5]=cs;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -