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

📄 general.c

📁 本代码为电子式单相多费率电能表的源程序
💻 C
字号:
#include <Reg936.h>
#define _GENERAL_DEFINE
#include <General.h>

#define GENERATE_STOP        0x54      // 置位 STO, 复位 STA 、 SI 
#define RELEASE_BUS_ACK      0x44      // 复位 STO,STA,SI 并置位 AA (ack)
#define RELEASE_BUS_NOACK    0x40      // 复位 STO,STA,SI 并清除 AA (noack)
#define RELEASE_BUS_STA      0x64      // 起动总线/重新起动总线, 置位 STA

bit   AckBus(void);
bit   GetBus(void);  
bit   SendByte(uchar value);

//**********************************************************
//                  总线响应
//功能:
//入口参数:无
//**********************************************************
bit AckBus(void)
{
  uchar TimeOut;
  
  TimeOut = 0xFF;
  
  while(SI==0)
  {	 
    TimeOut--; 
    if( TimeOut==0x00 )  //100uS无响应,超时退出
    {
      I2CON = GENERATE_STOP;
      return(0);
    }
  }
  
  return(1);  //有响应,即SI==1,返回值1
}

//**********************************************************
//                  总线申请
//功    能:进行I2C总线的初始化:包括时钟选择,I2C使能,发送起
//         始信号等等;I2EN为1,设置为主机;CRSEL位为0,使用内
//         部SCL发生器.
//入口参数:无
//**********************************************************
bit GetBus(void)       
{	                   // CCLK为7.3728MHz,参数0x14 实际总线频率为 92KHz
  I2SCLH = 0x14;	   // 设置SCL高电平的PCLK周期数
  I2SCLL = 0x14;           // 设置SCL低电平的PCLK周期数
  I2CON  = RELEASE_BUS_STA;// 申请成为主机,起动总线。使用内部SCL发生器,I2EN和AA置位  	
//while( SI==0 );          // 等待起始位的发送
  return(AckBus());
}

//**********************************************************
//                    发送数据函数
//功    能:用于向总线发送数据 
//入口参数:value 待发送的数据                   
//**********************************************************
bit SendByte(uchar value)
{ 
  I2DAT = value;
  I2CON = RELEASE_BUS_ACK; //清除SI位等等   
//while( SI==0 );          //等待数据的发送 
  return(AckBus());
}

//**********************************************************
//             向有子地址器件发送多字节数据函数                 
//功    能:从启动总线到发送器件地址,子地址,数据,结束总线的全过程。
//入口参数:AddrPtr	地址指针
//         DataPrt    	数据指针
//         Ptr_length	地址、数据长度
//出口参数:返回1表示操作成功,否则操作有误。
//**********************************************************
bit ISendStr(uchar idata *AddrPtr,uchar idata *DataPrt,uchar idata *Ptr_length)
{ 
  uchar i;
  uchar Addr_len;
  uchar Data_len;
  
  Addr_len = *Ptr_length; //地址长度
  Ptr_length++;	        //数据长度
  Data_len = *Ptr_length;
  
  if(GetBus()==0)  return(0); //启动总线
  
  if(SendByte(*AddrPtr)==0)  return(0); //发送器件地址
  
  if( I2STAT!=0x18 )
  { 
    I2CON = GENERATE_STOP;
    return(0);
  } 
  
  for(i=1;i<Addr_len;i++)
  {
    AddrPtr++; 
  
    if(SendByte(*AddrPtr)==0) return(0); //发送器件子地址
  
    if(I2STAT!=0x28)
    {	 
      I2CON = GENERATE_STOP;
      return(0);
    } 
  }   
  
  for(i=0; i<Data_len; i++)
  { 
    if(SendByte(*DataPrt)==0) return(0); //发送数据 
  
    if( I2STAT!=0x28 )
    {
      I2CON = GENERATE_STOP;
      return(0);
    }    	
    DataPrt++;
  } 
  
  I2CON = GENERATE_STOP; //结束总线  
  return(1);
}

//**********************************************************
//                    向有子地址器件读取多字节数据函数                
//功    能:从启动总线到发送地址,子地址,读数据,结束总线的全过程。
//入口参数:AddrPtr	地址指针
//         DataPrt    	数据指针
//         Ptr_length	地址、数据长度
//出口参数:函数返回1表示操作成功,否则操作有误。
//**********************************************************
bit IRcvStr(uchar idata *AddrPtr,uchar idata *DataPrt,uchar idata *Ptr_length)
{ 
  uchar i;
  uchar Addr_len;
  uchar Data_len;
  uchar read;
  
  read     = *AddrPtr+1; //取从器件地址  
  Addr_len = *Ptr_length; //地址长度
  Ptr_length++;           //数据长度
  Data_len = *Ptr_length;  
  
  if(GetBus()==0) return(0); // 启动总线
    
  if(SendByte(*AddrPtr)==0) return(0); //发送器件地址
  	
  if( I2STAT!=0x18 )
  { 
    I2CON = GENERATE_STOP;
    return(0);
  }
 
  for(i=1;i<Addr_len;i++) //发送器件子地址
  {
    AddrPtr++; 

    if(SendByte(*AddrPtr)==0) return(0);           

    if( I2STAT!=0x28 )
    { 
      I2CON = GENERATE_STOP;
      return(0);
    } 
  }
  	
  I2CON = RELEASE_BUS_STA; //重新启动总线
//while( SI==0 );
  if(AckBus()==0)  return(0);

  if(SendByte(read)==0)  return(0);  

  if( I2STAT!=0x40 )
  { 
    I2CON = GENERATE_STOP;
    return(0);
  } 
  
  for(i=0; i<Data_len-1; i++)
  { 
    I2CON = RELEASE_BUS_ACK; //接收一字节数据并发送应答位(预置应答位)
  //while( SI==0 );          //等待接收数据
    if(AckBus()==0)  return(0);
  
    if(I2STAT!=0x50)
    { 
      I2CON = GENERATE_STOP;
      return(0);
    }
  
    *DataPrt = I2DAT; //读取数据
    DataPrt++;
  } 
  
  I2CON = RELEASE_BUS_NOACK; //接收最后一字节数据并发送非应答位
//while( SI==0 );
  if(AckBus()==0)  return(0);  
	    
  *DataPrt = I2DAT; //读取最后一个数据
  I2CON    = GENERATE_STOP; //结束总线
  	  	
  return(1);
}

//**********************************************************
//名称:DelayNmS()
//功能:
//说明:
//**********************************************************
void DelayNms(uchar value)
{
  uchar i;
  uchar j;
  
  while(value--)
  {	
    //1ms=10*100us
    for(i=0;i<10;i++)
    {		
      //100us
      j=184;
      while(--j);
    } 
  }
}

//**********************************************************
//名称:ArrayInit()
//功能:
//说明:数组清零
//**********************************************************
void  ArrayInit(uchar *ptr,uchar len)
{
  uchar i;

  i= 0x00;
  do
  {
    *ptr = 0x00;
    ptr++;
    i++;
  }while(i<len);
}

//**********************************************************
//名称:BCDCHK()
//功能:
//说明:BCD检查
//**********************************************************
bit BCDCHK(uchar idata *ptr,uchar len)
{	
  uchar i;
  uchar Temp;		
  
  i=0x00;
  do
  {		
    Temp = *ptr;		
    if( (Temp&0x0F)>0x09 || (Temp&0xF0)>0x90 ) return(0);		
    ptr++;
    i++;		
  }while(i<len);
  
  return(1);
}

//**********************************************************
//名称:BCD2HEX()
//功能:
//说明:BCD转HEX
//**********************************************************
uchar BCD2HEX(uchar BCDdata)
{
  uchar Temp;
  
  Temp  = (BCDdata>>4)*10;
  Temp +=  BCDdata&0x0F;
  
  return Temp;
}

//**********************************************************
//名称:HEX2BCD()
//功能:
//说明:HEX转BCD
//**********************************************************
uchar HEX2BCD(uchar HEXdata)
{
  uchar Temp,tHEXdata;
  
  tHEXdata = HEXdata;
  if(tHEXdata>99)  tHEXdata = 99;
  Temp = (tHEXdata/10)<<4;
  Temp  += tHEXdata%10;
  
  return Temp;
}

//**********************************************************
//名称: BCDINC()
//功能: 多字节BCD码加1子程序
//说明: 要求BCD数组低字节在前,高字节在后
//      pSbuf1--->数组首地址, Svar1--->数组长度
//      返回值: 1-->有进位, 0-->无进位
//**********************************************************
uchar BCDINC(uchar idata *pSbuf1,uchar Svar1)
{
  //if(Svar1==0) return 0;
  while (Svar1!=0)
  {   
    (*pSbuf1)++;
    if((*pSbuf1&0x0F)>=10)
    {
      *pSbuf1 += 6;
      if(*pSbuf1>=0xA0)
      {
        *pSbuf1=0;
        pSbuf1++;
        Svar1--;
      }
      else
        return 0;
    }
    else
      return 0;
  }
  return 1;
}

//**********************************************************
//名称: BCDAdd() 
//功能: 多字节BCD码加法子程序
//说明: pSbuf1,pSbuf2为2个加数的首地址,低字节在前,2个数组的
//      长度必须相等,为Svar2。                                                                                                          
//      返回值: 1-->有进位, 0-->无进位                                                                         
//**********************************************************
#ifdef BCDADD1
uchar BCDAdd(uchar idata *pSbuf1,uchar idata *pSbuf2,uchar Svar2)
{   
  uchar Svar4,Svar5;
  uint  iSvar1;
  
  Svar4=0;
  while (Svar2!=0)
  {
    Svar2--;
    Svar5=(*pSbuf1&0x0F)+(*pSbuf2&0x0F)+Svar4;
    if(Svar5>=10)
    {
      *pSbuf1 += 0x10;
      Svar5 -= 10;
    }
    iSvar1=(uint)(*pSbuf1&0xF0)+(*pSbuf2&0xF0)+Svar5;
    if(iSvar1>=0xA0)
    {
      iSvar1-=0xA0;
      Svar4=1;
    }
    else
      Svar4=0;
    *pSbuf1=(uchar)iSvar1;
    pSbuf1++;pSbuf2++;
  }

  if(Svar4)  return 1;
  else  return 0;
}
#endif

//**********************************************************
//名称: BCDAdd() 
//功能: 多字节BCD码加法子程序
//说明: pSbuf1,pSbuf2为2个加数的首地址,低字节在前,
//      Svar1,Svar2为2数的长度字数,必须Svar1>=Svar2                                                                                                            
//      返回值: 1-->有进位, 0-->无进位                                                                         
//**********************************************************
#ifdef BCDADD2
uchar BCDAdd(uchar idata *pSbuf1,uchar idata *pSbuf2,uchar Svar1,uchar Svar2)
{   
  uchar Svar4,Svar5,*rAddr,rLen;
  uint  iSvar1;
  
  //if((Svar2>Svar1)||(Svar1==0)||(Svar2==0))  return 0;
  rAddr = pSbuf1+Svar2; //剩余字节首址
  rLen  = Svar1-Svar2; //剩余长度
  
  Svar4=0;
  while (Svar2!=0)
  {
    Svar2--;
    //Svar1--;
    Svar5=(*pSbuf1&0x0F)+(*pSbuf2&0x0F)+Svar4;
    if(Svar5>=10)
    {
      *pSbuf1 += 0x10;
      Svar5 -= 10;
    }
    iSvar1=(uint)(*pSbuf1&0xF0)+(*pSbuf2&0xF0)+Svar5;
    if(iSvar1>=0xA0)
    {
      iSvar1-=0xA0;
      Svar4=1;
    }
    else
      Svar4=0;
    *pSbuf1=(uchar)iSvar1;
    pSbuf1++;pSbuf2++;
  }
  /*
  if(Svar4)
  {
    if(rLen==0) 
      return 1;
    else 
      return BCDINC(rAddr,rLen);
  }
  */
  if(Svar4)
    return BCDINC(rAddr,rLen);
  else
    return 0;
}
#endif

//**********************************************************
//名称:SumCHK()
//功能:返回数据校验和
//说明:
//**********************************************************
uchar SumCHK(uchar idata *ptr, uchar len)
{
  uchar i;
  uchar TmpData;
  uchar SumData;
  
  TmpData = 0x00;
  SumData = 0x00; 	
  i       = 0x00;
  do
  {
    TmpData  = *ptr;
    SumData += TmpData; 				
    ptr++;
    i++;
  } while(i<len);
  
  return SumData;
}

⌨️ 快捷键说明

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