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

📄 pos.c

📁 这是一个基于P89c51单片机的声音与显示C51程序
💻 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 + -