📄 pos.c
字号:
/*########################################
POS(电子收费系统)开发
2005.03.22
P89C51RAXX,8KFlase,256B RAM 256B XRAM
6clock,20MHz
*/
//头文件已经过修改,启动代码经过修改
//***************************************************************
//#pragma SRC
#include "reg51f.h"
#include "pos.h"
#include <Intrins.h>
//***************************************************************
void main(void)
{
SFRInit();
CommInit();
WDT();
while(1)
{
WDT(); // 喂狗
ScreenCs=1;
GetRight_B=0;
GetErr_1B =0;
GetErr_B =0;
BuyBegin_B=0;
BuyOk_B=0;
BuyErr_B=0;
yzd_memset(SoundBuf,0x00,17);
while(1)
{
WDT(); // 喂狗
EA=1;
ES =1;nop;nop;nop;nop;ES =0;
ET1=1;nop;nop;nop;nop;ET1=0;
ET0=1;nop;nop;nop;nop;ET0=0;
EA=0;
if(GetRight_B) {GetRight_B=0;break;}
}
Transact();
}
}
//*************************************************************
//*************************************************************
void Transact(void)
{
uchar i,tempc;
if(Command==0x09)
{
switch(GetBuf[8])
{
case 0x00:
case 0x01:
case 0x02:
case 0x04:
break;
default:
GetErr_1B=1;
}
}
GetErr_B=GetErr_1B;
if(CommSend()!=16)CommSend(); //应答
switch(Command)
{
case 0x01: //一次售电开始
BuyBegin_B=1;
BuyOk_B=0;
BuyErr_B=0;
break;
case 0x02: //一次售电成功结束
BuyOk_B=1;
BuyErr_B=0;
BuyBegin_B=0;
SoundBufCon();
Speak();
break;
case 0x03: //一次售电异常结束
BuyErr_B=1;
BuyOk_B=0;
BuyBegin_B=0;
SoundBufCon();
Speak();
break;
case 0x04:
case 0x05: //金额相关
case 0x06:
RMBBufCon();
DisBufCon(); //显示缓冲区处理
SetState(); //状态LED处理
break;
case 0x07: //禁止/激活语音功能
if (GetBuf[0]==0x11)ScreenSound_B=1;
else if(GetBuf[0]==0x00)ScreenSound_B=0;
break;
case 0x08: //清屏
yzd_memset(DisBuf,0x00,8); //不显示
break;
case 0x09: //直接显示
SetState(); //状态LED处理
for(i=0;i<8;i++)
{
tempc=GetBuf[i];
tempc=(tempc/0x10)*10+(tempc%0x10);
DisBuf[7-i]=*(DisSum+tempc); //直接处理
}
break;
case 0x0a://直接发音
SoundBufCon(); //语音缓冲区处理
Speak();
break;
}
}
//*************************************************************
//将接收到的金额数据转存到对应空间,
//在接收的时候已经 -33H 处理.
//如果金额在100万以上,则置位 RmbHundred_B
//如果金额在1000万以上,则置位RmbThousand_B
void RMBBufCon(void)
{
uchar i,j;
WDT(); // 喂狗
for(i=0,j=0;i<5;i++,j=j+2)
{
RMBBuf[j]= GetBuf[i] / 0x10;
RMBBuf[j+1]=GetBuf[i] % 0x10;
}
for(i=0;i<10;i++)
{
if (Command==0x04)LastBuyBuf[i]=RMBBuf[i];
else if(Command==0x05) NowBuyBuf[i]=RMBBuf[i];
else if(Command==0x06) AllBuyBuf[i]=RMBBuf[i];
}
RmbHundred_B=0;
RmbThousand_B=0;
if(RMBBuf[0]>0) RmbThousand_B=1;
else if(RMBBuf[1]>0) RmbHundred_B=1;
}
//*************************************************************
//显示缓冲区处理:根据全局变量RMB 处理显示缓冲区
//如果金额在100万以下, 则显示2位小数
//如果金额在100万以上, 则显示1位小数
//如果金额在1000万以上,则不显示小数
void DisBufCon(void)
{
uchar i,j,x;
WDT(); // 喂狗
if(RmbThousand_B) x=0;
else if(RmbHundred_B) x=1;
else x=2;
for(i=x,j=0;j<8;i++,j++)
{
if (Command==0x04) DisBuf[j]=*(DisSum+LastBuyBuf[i]);
else if(Command==0x05) DisBuf[j]=*(DisSum+ NowBuyBuf[i]);
else if(Command==0x05) DisBuf[j]=*(DisSum+ AllBuyBuf[i]);
}
//小数点
//零字消隐注意到当金额少于一元时的情况
if(RmbThousand_B) DisBuf[7]+=0x80;
else if(RmbHundred_B) DisBuf[6]+=0x80;
else DisBuf[5]+=0x80;
for(i=0;i<8;i++)
{
if(DisBuf[i]==0x3f) DisBuf[i]=0x00;
else break;
}
}
//*************************************************************
//语音缓冲区处理:
//只有当Command==0x0a 或 BuyOk_B==1 或 BuyErr_B==1 才能调用此函数,
//否则将导致错误!!!
void SoundBufCon(void)
{
uchar i,j;
WDT(); // 喂狗
if(Command==0x0a)
{
if(GetBuf[5]==0x10)
{
for(i=0,j=3;i<4;i++,j--)
{
GetBuf[i]=(GetBuf[i]/0x10)*10+(GetBuf[i]%0x10);
if(GetBuf[i]>22)SoundBuf[j]=0xaa;
else SoundBuf[j]=*(SoundSum+GetBuf[i]);
}
SoundBuf[4]=0x00;
return;
}
else if(GetBuf[5]==0x01){SoundBuf[0]=0xaa;SoundBuf[1]=0xf8;SoundBuf[2]=0x3c;}//上次剩余、金额
else if(GetBuf[5]==0x02){SoundBuf[0]=0xaa;SoundBuf[1]=0xf1;SoundBuf[2]=0x3c;}//本次购电、金额
else if(GetBuf[5]==0x04){SoundBuf[0]=0xaa;SoundBuf[1]=0xe3;SoundBuf[2]=0xaa;}//当前总金额、跳过
for(i=0,j=0;i<5;i++,j=j+2) //将接收到的直接发音金额化成单个字存入tempbuf[];
{
tempbuf[j]= GetBuf[i] / 0x10;
tempbuf[j+1]=GetBuf[i] % 0x10;
}
}
else if(BuyOk_B)
{
SoundBuf[0]=0x3e; //售电成功
SoundBuf[1]=0xf1; //本次购电
SoundBuf[2]=0x3c; //金额
for(i=0;i<10;i++) {tempbuf[i]=NowBuyBuf[i];} //将NowBuyBuf[]存入tempbuf[];
}
else if(BuyErr_B)
{
SoundBuf[0]=0x7c;//售电失败
SoundBuf[1]=0x00;//停止
return;
}
//以下金额相关"零"发音消隐程序段
WDT(); // 喂狗
for(i=0,j=3;i<7;i++,j=j+2)
{
if(tempbuf[i]==0){SoundBuf[j]=0xfe;SoundBuf[j+1]=0xaa;}
else {SoundBuf[j]=*(SoundSum+tempbuf[i]);SoundBuf[j+1]=*(SoundData_1+i);}
}
if(tempbuf[7]==0) SoundBuf[17]=0xfe;
else SoundBuf[17]=*(SoundSum+tempbuf[7]);
if((tempbuf[8]==0)&&(tempbuf[9]==0)) {SoundBuf[18]=0xaa;SoundBuf[19]=0xaa;SoundBuf[20]=0xaa;}
else {SoundBuf[18]=0xe7;SoundBuf[19]=*(SoundSum+tempbuf[8]);SoundBuf[20]=*(SoundSum+tempbuf[9]);}
for(i=3;i<17;i=i+2) //避免"0"音重复
{
if((SoundBuf[i]==0xfe)&&(SoundBuf[i+2]==0xfe)) SoundBuf[i]=0xaa;
}
if(SoundBuf[17]==0xfe) SoundBuf[17]=0xaa;
for(i=15;i>1;i=i-2) //避免发时的最高位是"0"
{
if(SoundBuf[i]==0xfe)
{
for(j=3;j<i;j++)//
{
if(SoundBuf[j]!=0xaa)break;
}
if(j==i) SoundBuf[i]=0xaa;
}
}
for(i=0;i<3;i++) //确保"万"字
{
if(tempbuf[i]>0) break;
}
if(i<3) SoundBuf[10]=0x3f;
for(i=0;i<8;i++) //至少在小数点前保持1个"0"
{
if(tempbuf[i]!=0) break;
}
if(i==8) SoundBuf[17]=0xfe;
SoundBuf[21]=0x7e; //"元"
SoundBuf[22]=0x00;
}
//*************************************************************
//发音函数,正常发音返回0,异常返加1.
uchar Speak(void)
{
static uchar i;
WDT(); // 喂狗
if(ScreenSound_B==1)return(0);
i=0;
while(1)
{
INT0=1;
if(SoundBuf[i]==0x00) return(0);
else if(SoundBuf[i]==0xaa){i++;continue; }
else if(SoundBuf[i]==0xff){nop;nop;}
SOUND=SoundBuf[i];
nop;
SoundTime=0;
while(1)
{
WDT(); // 喂狗
EA=1;
ET1=1;nop;nop;nop;nop;ET1=0;
ET0=1;nop;nop;nop;nop;ET0=0;
EA=0;
if(SoundTime>5)break; //触发脉冲宽度25ms
}
SOUND=0xff;
nop;
STP_B=0;
SoundTime=0;
while(1)
{
WDT(); // 喂狗
EA=1;
ET1=1;nop;nop;nop;nop;ET1=0;
ET0=1;nop;nop;nop;nop;ET0=0;
EX0=1;nop;nop;nop;nop;EX0=0;
EA=0;
if(STP_B){STP_B=0;break;}
if(SoundTime>2000) return(1); //10秒没有收到语音芯片的停止脉冲,认为异常,退出
}
SoundTime=0;
while(1)
{
WDT(); // 喂狗
EA=1;
ET1=1;nop;nop;nop;nop;ET1=0;
ET0=1;nop;nop;nop;nop;ET0=0;
EA=0;
if(INT0==1) break;
if(SoundTime>200)return(1); //1秒钟内语音芯片的停止脉冲还没有过,认为异常,退出
}
i++;
if(i==22)return(0);
}
WDT(); // 喂狗
}
//*************************************************************
//设置 "剩余"、"本次"、"总剩余"、状态LED
//为了节约代码,没有保护,只有在需要改变的时候才能调用此函数,
//具体来说,只有Command== 4,5,6,9,时才能调用,否则会导致错误!!!
void SetState(void)
{
WDT(); // 喂狗
LastLed=1;NowLed=1;AllLed=1;
if(Command==0x09)
{
if(GetBuf[8]==0x01) LastLed=0;
else if(GetBuf[8]==0x02) NowLed=0;
else if(GetBuf[8]==0x04) AllLed=0;
}
else if(Command==0x04) LastLed=0;
else if(Command==0x05) NowLed=0;
else if(Command==0x06) AllLed=0;
}
//*************************************************************
void yzd_memset(uchar data *buf,uchar c,uchar len)
{
uchar i;
uchar data *p;
WDT(); // 喂狗
p=buf;
for(i=0;i<len;i++) *(p+i)=c;
}
//*************************************************************
//*************************************************************
uchar CommSend(void)
{
uchar i,tempc;
uint j;
TI=0;
for(i=0;i<16;i++)
{
if((i==12)||(i==14))
{
tempc=Command;
if(GetErr_B)tempc+=0xc0;
else tempc+=0x80;
}
else tempc=*(CommSendSum+i);
for(j=130;j>0;j--){nop;nop;nop;nop;}
SBUF=tempc;
nop;
SendTime=0;
WDT(); // 喂狗
while(1)
{
EA=1;
ET0=1;nop;nop;nop;nop;nop;ET0=0;
ET1=1;nop;nop;nop;nop;nop;ET1=0;
EA=0;
WDT(); // 喂狗
if(TI) break;
if(SendTime>2){SendTime=0;break;} //在约10ms之内退出
}
TI=0;
if(SendTime>2)break;
WDT(); // 喂狗
}
return(i);
}
//*************************************************************
//串口中断服务程序
#pragma disable
void CommGet(void) interrupt 4
{
static uchar DataCs=0,Flag=0,L;
uchar tempc;
if(RI)
{
RI=0;
tempc=SBUF;
if(GetTime>1)Flag=0;
switch(Flag)
{
case 0:
if(tempc==0x68) Flag=1;
break;
case 1:
if(tempc==0x88) Flag=2;
else Flag=0;
break;
case 2:
if(tempc==0x88) Flag=3;
else Flag=0;
break;
case 3:
if(tempc==0x88) Flag=4;
else Flag=0;
break;
case 4:
if(tempc==0x88) Flag=5;
else Flag=0;
break;
case 5:
if(tempc==0x88) Flag=6;
else Flag=0;
break;
case 6:
if(tempc==0x88) Flag=10;
else Flag=0;
break;
case 10:
if(tempc==0x68) Flag=11;
else Flag=0;
break;
case 11: //控制码
Command=tempc;
DataCs=tempc;
if((tempc==0)||(tempc>0x0a))GetErr_1B=1;
Flag=12;
break;
case 12: //长度码
if(tempc==0)Flag=30;
else if(tempc<10)
{
DataLen=tempc;L=tempc;DataCs+=tempc;Flag=20;
}
else Flag=0;
break;
//Data:
case 20:
if(L==1){Flag=30;}
if((tempc>0xcc)||(tempc<0x33)) GetErr_1B=1;
L--;
DataCs+=tempc;
GetBuf[L]=tempc-0x33;
break;
//CS
case 30:
if(ScreenCs)
{
if(DataCs!=tempc){Flag=0;}
else Flag=40;
}
else if(tempc==0x00)Flag=40;
else Flag=0;
break;
//END
case 40:
if(tempc==0x16)GetRight_B=1;
Flag=0;
break;
}
GetTime=0;
}
}
//*************************************************************
void STP_EX0 (void) interrupt 0
{
STP_B=1;
IE0=0;
}
//*************************************************************
void Dis_Init_T1(void) interrupt 3
{
static uchar data Dis_i=0,tempc=0x7f;
TR1=0;
DIG=tempc;
DIS=DisBuf[Dis_i];
tempc=_cror_(tempc,1);
if(++Dis_i==8) {Dis_i=0;tempc=0x7f;}
TH1=0xf3;
TL1=0X00;
TR1=1;
}
//*************************************************************
//5ms
void Time_Init_T0(void) interrupt 1
{
//CommGet:
GetTime++;
//CommSend:
SendTime++;
//Speak:
SoundTime++;
TH0=0xbe;
TL0=0x00;
}
//#############################################################
//################# END #######################################
//#############################################################
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -