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

📄 pc_comm.c

📁 单片机和上位机通讯源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#include <absacc.h>
#include <file.h>
#include <w77516.h>

#define StartAddOfRFPC	0x1000		//接收PC数据的缓存区首地址
#define StartAddOfSTPC	0x2000		//向PC发送数据的缓存区首地址1
#define StartAddOfSTPC1	0x3000		//向PC发送数据的缓存区首地址2

//黑名单、白名单按以下方式存放在28SF040中
//第一个扇区存储名单版本号、生效日期、有效截止日期、有效区域、名单数量、校验和
//其后每扇区第一字节为该扇区内实际存储的数据的长度n(最大240字节、15段,24条名单)
//第2至第(n+1)字节为实际存储的数据、第(n+2)和(n+3)字节存储CRC校验和
//白名单位于扇区10-19、新增黑名单位于扇区20-29、新删黑名单位于30-39
//黑名单位于扇区40-874,200条灰记录位于扇区900-999、2000笔脱机数据位于1000-1999扇区

#define PriceFS				6	//油品油价表在6、7扇区各存一份
#define StationFS			8	//油站通用信息在扇区8 存一份
#define WhiteFS				10	//白名单存储的第一个扇区号
#define AddBlackFS			20	//新增黑名单存储的第一个扇区号
#define DelBlackFS			30	//新删黑名单存储的第一个扇区号
#define BlackFS				40	//基础黑名单存储的第一个扇区号
#define GrayRecordDataFS		900	//灰记录数据存储的第一个扇区号
#define TransactionDataFS		1000	//成交数据存储的第一个扇区号
#define NumberOfTransactionRecord	2000	//脱机数据的最大数目
#define NumberOfGrayDataRecord	        100	//灰记录数据的最大数目

#define LengthOfPriceVerInfo		203	//油品油价信息的长度
#define LengthOfStationVerInfo		19	//油站通用信息的长度
#define AddressOfStationVerInfo		48	//油站通用信息在2402中的存储地址
#define LengthOfBlackVerInfo		18	//基础黑名单数据的长度
#define AddressOfBlackVerInfo		72	//基础黑名单数据在2402中的存储地址
#define LengthOfAddBlackVerInfo		4	//新增黑名单数据的长度
#define AddressOfAddBlackVerInfo	92	//新增黑名单数据在2402中的存储地址
#define LengthOfDelBlackVerInfo		4	//新删黑名单数据的长度
#define AddressOfDelBlackVerInfo	96	//新删黑名单数据在2402中的存储地址
#define LengthOfWhiteVerInfo		4	//白名单数据的长度
#define AddressOfWhiteVerInfo		100	//白名单数据在2402中的存储地址
#define LengthOfTransactionRecord	32	//成交记录的长度
#define AddressOfTransactionRecord1	128	//成交记录存储地址1
#define AddressOfTransactionRecord2	160	//成交记录存储地址2
#define LengthOfTransactionData		97      //成交数据(灰记录)的长度

byte bdata PCCOMM;
sbit ReceivedFlagOfPC=PCCOMM^0;		//是否已经接收到来自PC的一帧数据
sbit ReceivedFlag1OfPC=PCCOMM^1;	//是否已经接收到来自PC的一帧数据
sbit Received0xfa=PCCOMM^2;		//是否已接收到0xfa的标志
sbit Sent0xfa=PCCOMM^3;			//是否已发送0xfa的标志
sbit PCOffLine=PCCOMM^4;		//与PC通讯脱机的标志
sbit CheckDLDataFlag=PCCOMM^6;		//需要检测下载数据
sbit RequestDownLoad=PCCOMM^7;		//请求下载基础黑名单数据

byte xdata SendPCTransactionData;	//向PC发送交易数据的标志

byte bdata PCCOMM1;
sbit ErrorInfo=PCCOMM1^1;               //需要向PC发送错误信息
sbit SendBufferFlag=PCCOMM1^2;          //向PC发送数据使用的缓存区的标志
sbit CardInsert=PCCOMM1^3;		//卡是否已插入的标志位
sbit TMACError=PCCOMM1^7;		//为1 则需要重新计算T_MAC

byte xdata EmpCardFlag;
word xdata TimerOfOnDuty;
byte xdata CheckBlackWhite;		//需要向PC查询黑/白名单
byte xdata TypeOfCheckBW;		//0-使用后台黑/白名单、1-使用油机内部黑/白名单
byte xdata CheckGrayRecord;		//需要向PC查询灰记录
byte xdata SendTimes;			//送卡状态的次数
byte xdata TimerOfInit;
byte xdata BufferOfReceiveFromPC[256] _at_ StartAddOfRFPC;//已接收到的PC数据的存储缓冲区
word xdata ReadAddressOfRFPC;		//接收到的PC数据在接收缓冲区中的读出地址
byte xdata ReceivedLengthOfPC;		//正在接收的数据帧中已经接收到的数据长度
byte xdata ReceivedLength1OfPC;		//正在接收的数据帧中已经接收到的数据长度
byte xdata TimerOfRFPC;			//接收PC数据的帧间定时(接收到一字节后10毫秒内再没有接收到数据则准备重新接收)
byte xdata TimerOfPCOffLine;		//用于检测与PC通讯是否中断(5秒没有接收到PC数据则认为通讯断)
byte xdata ReceivedDestAddress;		//接收到的目的地址
byte xdata ReceivedSrcAddress;		//接收到的源地址
byte xdata ReceivedPCTTL;		//接收到的PC帧号
byte xdata ValidLengthOfRFPC;		//接收到的有效长度
byte xdata TimerOfSTPC;			//向PC送数的时间间隔为0.5秒
byte xdata SendPCTTL;			//发送到PC的帧号
byte xdata TimesOfSendTraction;		//上送成交数据的次数

byte xdata BufferOfSendToPC[128] _at_ StartAddOfSTPC;//待发送到PC的数据的存储缓冲区
byte xdata BufferOfSendToPC1[128] _at_ StartAddOfSTPC1;//待发送到PC的数据的存储缓冲区
word xdata ReadAddressOfSTPC;		//待发送到PC的数据在发送缓冲区中的读出地址
byte xdata LengthOfSTPC;		//还需要发送到PC的数据的长度
//byte xdata Sent0xfa;			//是否已发送0xfa的标志
byte xdata ApplyDL;
byte xdata ApplyDownLoad;		//申请下载(1-已申请下载基础黑名单、2-已申请下载新增黑名单
//						    3-已申请下载新删黑名单、4-已申请下载白名单
//						    5-已申请下载油品油价、6-已申请下载通用信息
//						    7-已申请下载私有数据、8-已申请下载新的程序)
byte xdata DownLoadFlag;		//下载数据标志(1-正在下载基础黑名单、2-正在下载新增黑名单
//							3-正在下载新删黑名单、4-正在下载白名单
//							5-正在下载油品油价、6-正在下载通用信息
//							7-正在下载私有数据、8-正在下载新的程序)
dword xdata DLTotalLength;		//要下载的数据的总长度
word xdata DLSegOffset;			//本次要下载的段偏移
byte xdata DLLength;			//本次要下载的长度
word xdata DLSector;			//本次下载的扇区号

union Hex_2 xdata Hex2;			//2字节16进制数
union Hex_4 xdata Hex4;		        //4字节16进制数

byte xdata CheckDLData;			//检查下载数据的标志
//1-正在检查基础黑名单、2-正在检查新增黑名单
//3-正在检查新删黑名单、4-正在检查白名单
//5-正在检查油品油价、  6-正在检查油站通用信息
byte xdata TimerOfDownLoad;
word xdata TotalSectorNum;		//正在检测名单占有的扇区数
word xdata SectorNum;			//正在检查的扇区号

byte xdata InfoList[16];		//下载黑白名单时存储名单信息
byte xdata Buffer[256] _at_ 0x1200;	//存储临时数据

byte xdata TimerOfCheckOffLineData;
byte xdata OilNumber[2];

byte xdata TimerOfOnLamp1s; 		//1秒钟刷新一次

byte xdata ErrorInformation[128];       //暂存加油机出错信息
byte xdata ErrorLen;

struct BlackInfo xdata BlackVerInfo,BlackVerInfo1;//基础黑名单版本信息
struct BlackWhiteInfo xdata AddBlackVerInfo,AddBlackVerInfo1;//新增黑名单版本信息
struct BlackWhiteInfo xdata DelBlackVerInfo,DelBlackVerInfo1;//新删黑名单版本信息
struct BlackWhiteInfo xdata WhiteVerInfo,WhiteVerInfo1;//白名单版本信息
struct PriceInfo xdata PriceVerInfo _at_ 0x1800;
struct PriceInfo xdata PriceVerInfo1;//油品油价版本信息
struct StationInfo xdata StationVerInfo,StationVerInfo1;//油站通用信息
struct TransactionRecordInfo xdata TransactionRecord;
struct TransactionRecordInfo xdata TransactionRecord1;//成交记录信息

struct TransactionDataInfo xdata TransactionData;
struct TransactionDataInfo xdata TransactionData1;//成交数据

struct GrayDataInfo xdata GrayData;	//灰记录匹配数据

struct TotalDataInfo xdata TotalData[4];//存储读取的累计数

extern struct IcCardData1 xdata IcCardData;//IC卡相关数据
extern byte xdata PopIcCardFlagof2s;//弹卡后等待2秒钟
extern byte xdata CardStatus;	//上次的卡状态
extern byte xdata TimerOfJLOffLine;//与计量脱机的时间

extern struct SaveData xdata DataOfSave;
extern struct NozzleData xdata DataOfNozzle;
extern byte idata TimerOfSpeaker;
extern byte idata TimerOfReceivePC;
extern byte xdata IO_Temp[];

//检测是否与PC通讯断,返回值为1 则已断
byte Test_OffLine()
{
  if (PCOffLine==0)
    return (0);
  return (1);
}

dword HexToLong(byte xdata *px,byte i)
{
  byte j;
  if (i==3)
  {
    Hex4.c[0]=0;
    for (j=0;j<i;j++)
      Hex4.c[j+1]=px[j];
  }
  else
  {
    for (j=0;j<i;j++)
      Hex4.c[j]=px[j];
  }
  return (Hex4.i);
}

LongToHex(dword i,byte xdata *px,byte j)
{
  byte k;
  Hex4.i=i;
  if (j==4)
  {
    for (k=0;k<j;k++)
      *px++=Hex4.c[k];
  }
  if (j==3)
  {
    for (k=0;k<j;k++)
      *px++=Hex4.c[k+1];
  }
}

//计算CRC 校验和
word CRC_16(byte *buf,word len)
{
  word crc=0x0000;
  byte c,i,f1;
  Clear_WatchDog();
  f1=1;
  while(len!=0)
  {
    c=*buf;
    if (c!=0xff)
      f1=0;
    for(i=0;i<8;i++)
    {
      if ((crc ^ c) & 1)
        crc=(crc>>1)^0xa001;
      else
        crc>>=1;
      c>>=1;
    }
    len--;
    buf++;
  }
  Clear_WatchDog();
  if (f1==1)
    return (0);
  return (crc);
}

//将下载的名单数据保存到28SF040中
//Num-要保存的数据长度、i-要存储到的扇区号
Save_BLackWhite_List(byte Num,word i)
{
  byte j;
  dword xdata k;
  byte xdata *px;
  k=i;
  k<<=8;				//要存储到的地址
  j=Num%10;				//最后一次下载
  Num-=j;
  px=StartAddOfRFPC+10;
  *px=Num;				//暂存数据长度
  i=CRC_16(px+1,Num);
  px[Num+1]=i>>8;			//CRC高字节
  px[Num+2]=i;				//CRC低字节
  write_28sf040(k,Num+3,px);		//向28SF040地址k 处写入px地址开始的(Num+3)字节数据
}

//保存基础黑名单的版本信息
Save_BlackVerInfo()
{
  word i;
  Clear_WatchDog();
  BlackVerInfo.CRC=CRC_16((byte *)&BlackVerInfo,LengthOfBlackVerInfo-2);//基础黑名单的CRC校验和
  i=BlackFS;				//要存储到的扇区号
  i<<=8;				//要存储到的地址
  write_28sf040(i,LengthOfBlackVerInfo,(byte *)&BlackVerInfo);//向28SF040写入基础黑名单
  Clear_WatchDog();
  Write_2402(AddressOfBlackVerInfo,(byte *)&BlackVerInfo,LengthOfBlackVerInfo);//保存基础黑名单信息
}

//清除基础黑名单的版本信息
Clear_BlackVerInfo()
{
  BlackVerInfo.Ver[0]=0;		//版本号为0
  BlackVerInfo.Ver[1]=0;
  BlackVerInfo.Number=0;		//名单数量为0
  Save_BlackVerInfo();			//存储基础黑名单
}

//获得基础黑名单的版本信息
Load_BlackVerInfo()
{
  word i;
  i=BlackFS;				//要读取的扇区号
  i<<=8;				//要读取的地址
  read_28sf040(i,LengthOfBlackVerInfo,(byte *)&BlackVerInfo1);//从28SF040中读出基础黑名单信息
  if (BlackVerInfo1.CRC!=CRC_16((byte *)&BlackVerInfo1,LengthOfBlackVerInfo-2))
  {					//28SF040中的基础黑名单信息不正确
    Read_2402(AddressOfBlackVerInfo,(byte *)&BlackVerInfo1,LengthOfBlackVerInfo);//从2402中读取基础黑名单信息
    if (BlackVerInfo1.CRC!=CRC_16((byte *)&BlackVerInfo1,LengthOfBlackVerInfo-2))
    {					//2402中的基础黑名单信息也不正确
      if (BlackVerInfo.CRC==CRC_16((byte *)&BlackVerInfo,LengthOfBlackVerInfo-2))
      {					//SRAM中信息正确
        write_28sf040(i,LengthOfBlackVerInfo,(byte *)&BlackVerInfo);//向28SF040写入基础黑名单
        Write_2402(AddressOfBlackVerInfo,(byte *)&BlackVerInfo,LengthOfBlackVerInfo);//保存基础黑名单信息
      }
      else
      {
        Clear_BlackVerInfo();		//没有基础黑名单信息,清除信息
        Send_Error_Information("基础黑名单初始化!");
      }
    }
    else
      write_28sf040(i,LengthOfBlackVerInfo,(byte *)&BlackVerInfo1);//向28SF040写入基础黑名单
  }
  read_28sf040(i,LengthOfBlackVerInfo,(byte *)&BlackVerInfo);//从28SF040中读出基础黑名单信息
}

//保存基础黑名单信息
Save_BlackList_Info()
{
  DownLoadFlag=0;			//清除正在下载基础黑名单的标志
  BlackVerInfo.Ver[0]=InfoList[0];	//版本号高字节
  BlackVerInfo.Ver[1]=InfoList[1];	//版本号低字节
  BlackVerInfo.ValidDate[0]=InfoList[2];//有效日期中年的高位字节
  BlackVerInfo.ValidDate[1]=InfoList[3];//有效日期中年的低位字节
  BlackVerInfo.ValidDate[2]=InfoList[4];//有效日期中月份
  BlackVerInfo.ValidDate[3]=InfoList[5];//有效日期中日期
  BlackVerInfo.StopDate[0]=InfoList[6];	//截止日期中年的高位字节
  BlackVerInfo.StopDate[1]=InfoList[7];	//截止日期中年的低位字节
  BlackVerInfo.StopDate[2]=InfoList[8];	//截止日期中月份
  BlackVerInfo.StopDate[3]=InfoList[9];	//截止日期中日期
  BlackVerInfo.ValidRegion[0]=InfoList[10];//有效区域高字节
  BlackVerInfo.ValidRegion[1]=InfoList[11];//有效区域低字节
  BlackVerInfo.Number=HexToLong(InfoList+12,4);//名单数量
  Save_BlackVerInfo();			//保存基础黑名单版本信息
}

//存储基础黑名单
Save_BlackList()
{
  byte i;
  dword xdata j;
  Clear_WatchDog();
  if (ApplyDownLoad==1)
  {					//下载数据为基础黑名单信息
    for (i=0;i<16;i++)
      InfoList[i]=XBYTE[StartAddOfRFPC+11+i];//暂存基础黑名单信息
    if (DLTotalLength==16)
      Save_BlackList_Info();		//数据全部下载完毕
    else
    {
      Clear_BlackVerInfo();		//清除基础黑名单版本号
      DLSector=1;			//继续下载的数据存储在第二个扇区中
    }
  }
  else
  {					//下载的是基础黑名单数据
    i=ValidLengthOfRFPC-5;		//下载数据的实际长度
    Save_BLackWhite_List(i,DLSector+BlackFS);//存储到28SF040中
    if (RequestDownLoad==0)
    {					//不是检测中下载数据
      j=DLSector-1;
      j*=240;
      j+=i+16;				//得到实际已经下载的数据的长度
      if (j>=DLTotalLength)
        Save_BlackList_Info();		//数据全部下载完毕
      else
        DLSector++;			//要写入的扇区号加一,继续下载
    }
    else
      RequestDownLoad=0;		//清除请求下载的标志位
  }
}

//保存新增黑名单的版本信息
Save_AddBlackVerInfo()
{
  word i;
  AddBlackVerInfo.CRC=CRC_16((byte *)&AddBlackVerInfo,LengthOfAddBlackVerInfo-2);//新增黑名单的CRC校验和
  i=AddBlackFS;				//要存储到的扇区号
  i<<=8;				//要存储到的地址
  write_28sf040(i,LengthOfAddBlackVerInfo,(byte *)&AddBlackVerInfo);//向28SF040写入新增黑名单
  Write_2402(AddressOfAddBlackVerInfo,(byte *)&AddBlackVerInfo,LengthOfAddBlackVerInfo);//保存新增黑名单信息
}

//清除新增黑名单的版本信息
Clear_AddBlackVerInfo()
{
  AddBlackVerInfo.Ver=0;		//版本号为0
  AddBlackVerInfo.Number=0;		//名单数量为0
  Save_AddBlackVerInfo();		//存储新增黑名单
}

//获得新增黑名单的版本信息
Load_AddBlackVerInfo()
{
  word i;
  i=AddBlackFS;				//要读取的扇区号
  i<<=8;				//要读取的地址

⌨️ 快捷键说明

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