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

📄 main.c

📁 一个采用C8051F020芯片实现的流量计控制系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{
  if (RI0)
  {
    RI0 = FALSE;                                 // 清除接收中断标志,允许下次接收数据
    if (gbRxdOK0)                                // 如果主程序还没有处理完数据,则不接收当前帧数据
      return;
    if (gbSyncTwoOK0)                            // 检查同步字节是否接收完毕
    {
      if (SBUF0 == 0x7F)                         // 同步字节已接收完毕,但仍接收到了0x7F,说明出现了最糟糕
        return;                                  // 的情况,即有3个0x7F,因此需将该字节舍弃。
      gnRxdBuf0[gnRxdID0++] = SBUF0;
      if (gnRxdID0 == 2)                         // 检查字节是否接收完毕,接收完则为下次接收做好准备
      {        
        SetRxd0OK();                             // 重新初始化同步字节检测标志和串口接收缓冲区索引
        if (gbStarted && gbTestOver)             // 当测试进程结束,且用户尚未按下停止键时,不更新流量显示值
          return;
        gbRxdOK0 = TRUE;                         // 数据接收完毕,通知主程序可以处理数据了
      }
    }
    else                                         // 同步字节还未接收完毕,继续检测
    {
      if (SBUF0 == 0x7F)                         // 如果是同步字节,则设置相应的同步字节接收到标志
      {
        if (gbSyncOneOK0)
          gbSyncTwoOK0 = TRUE;
        else
          gbSyncOneOK0 = TRUE;
      }
      else                                       // 接收到的字节既非同步字节又非正常的测量数据,舍弃重来。
        SetRxd0OK();                             // 重新初始化同步字节检测标志和串口接收缓冲区索引
    }
  }
  else
    TI0 = FALSE;                                 // 清除发送中断标志,允许下次发送数据    
}

/********************************************************************************************************
** 函数名称: TIMER2_ISR
** 功能描述: TIMER2定时中断服务程序(2ms定时)。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块: 无
** 其它说明:
** 设 计 者:罗  建                                                              日  期:2008年02月16日
** 版    本:V1.00,原始版本
** 修 改 者:罗  建                                                              日    期:2008年03月17日
** 版    本:V1.01,将原来gnScanID>=6的代码作了调整,使得6个LED是连续扫描的。
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void TIMER2_ISR (void) interrupt INT_TIMER2
{
  UINT8 i;

  TF2 = FALSE;                                   // 清除TIMER2定时中断标志
  if (gnScanID > 5)                              // 6个LED是否扫描完?
  {
    gnScanID = 0;                                // 准备从头开始扫描
    EA = FALSE;                                  // 暂时禁止CPU响应中断
    if (!gbBufUsed)
    {
      for (i=0;i<4;i++)
      {
        gnDisBuf[0][i] = gnSegBuf[0][i];
        gnDisBuf[1][i] = gnSegBuf[1][i];
      }
      // 参数设置或流量系数设置时不允许消隐无效0(因要允许用户修改参数)
      if ((gnWorkState != wsParamSet) && (gnWorkState != wsCoefSet) && gbLogoOver)
      {
        for (i=3;i>1;i--)
        {
          if (gnSegBuf[0][i] == 0)
            gnDisBuf[0][i] = NONE;
          else if (gnSegBuf[0][i] != NONE)
            break;
        }
        for (i=3;i>1;i--)
        {
          if (gnSegBuf[1][i] == 0)
            gnDisBuf[1][i] = NONE;
          else if (gnSegBuf[1][i] != NONE)
            break;
        }
      }
    }
    if (!gbLogoOver)                             // 正在显示LOGO字符
    {
      gnDisBuf[0][5] = NONE;
      gnDisBuf[0][4] = 0x19;
      gnDisBuf[1][5] = 0x0A;
#if METER_RANGE == A150CN
      gnDisBuf[1][4] = 0x01;
#else
      gnDisBuf[1][4] = 0x02;
#endif
    }
    else                                         // 显示数据或参数
    {
      gnDisBuf[0][5] = gnGroupID;                // 左边第6位LED显示分组号
      gnDisBuf[1][5] = gnWorkState;              // 右边第6位LED显示工作状态字符(D,P,F,t,r)
    }
    EA = TRUE;                                   // 重新开中断
  }
  DoneDisplay();                                 // 显示当前扫描到的LED数码管及指示灯
  GetKey();                                      // 读取按键
  gnScanID++;                                    // 准备扫描下一个按键和LED
  // 实现100ms定时
  gnCnt2ms++;
  if (gnCnt2ms >= 50)                            // 定时100ms
  {
    gb100msOver = TRUE;
    gnCnt2ms = 0;
  }
}

/********************************************************************************************************
** 函数名称: SMBUS_ISR
** 功能描述: SMBUS接收中断服务程序。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块: 无
** 其它说明:
** 设 计 者:罗  建                                                              日  期:2008年01月29日
** 版    本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void SMBUS_ISR (void) interrupt INT_I2C
{
  switch (SMB0STA)                               // 根据中断状态码跳转,SMB0STA 是中断状态寄存器
  {
    case SMB_START:	                             // 0x08, (MT & MR) 起始条件已发出,将(从地址+R/W)装入到SMB0DAT,并清零STA
      SMB0DAT = gnSlaAddrW ;                     // 装入被访问的从芯片的写地址
      STA = CLR_BIT;                             // 人工清除 STA 位
      break;
    case SMB_RP_START:	                         // 0x10,(MT & MR) 重复起始条件已发出,将(从地址+R/W)装入到SMB0DAT,并清零STA
      SMB0DAT = gnSlaAddrR;                      // 装入被访问的从芯片的读地址
      STA = CLR_BIT;                             // 人工清除 STA 位
      break;
    case SMB_MTADDACK:                           // 0x18,(MT) (从地址+W)已发出,收到ACK,将要发送的数据装入SMB0DAT
      SMB0DAT = gnMemAddr;
      break;
    case SMB_MTADDNACK:     	                 // 0x20,(MT) (从地址+W)已发出,收到NACK,确认查询重试,置位STO+STA
      STO = SET_BIT;
      STA = SET_BIT;
      break;
    case SMB_MTDBACK:		                     // 0x28,(MT) 数据字节已发出,收到ACK,将下一字节装入到SMB0DAT,或置位STO,或置位STO然后置位STA以重复起始条件
      switch (gnSendMode)
      {
        case 0:
          gnSendNums--;
          if (gnSendNums)
            SMB0DAT = gnMemData;
          else
          {
            STO=1;
            SM_BUSY=0;
          }
          break;             
        case 1:
          STO = 0;
          STA = 1;
          break;            
        default:              
          STO = 1;
          SM_BUSY = 0;
          break;
      }
      break;
    case SMB_MTDBNACK:	                         // 0x30,(MT) 数据字节已发出,收到NACK,重试传输或置位STO
      STO = SET_BIT;
      STA = SET_BIT;
      break;
    case SMB_MRADDACK:	                         // 0x40,(MR) (从地址+R)已发出,收到ACK,如果只收到一个字节,清AA位(收到字节后发NACK),等待接收数据
      AA = CLR_BIT;
      break;
   	case SMB_MRADDNACK:	                         // 0x48,(MR) (从地址+R)已发出,收到NACK,确认查询重试,置位STO+STA
      STO = CLR_BIT;
      STA = SET_BIT;
      break;
    case SMB_MRDBNACK:	                         // 0x58,(MR) 收到数据字节,NACK已发出,读操作已完成,读数据寄存器后发送停止条件
      gnMemData = SMB0DAT;
      STO = SET_BIT;
      SM_BUSY = CLR_BIT;
      AA = SET_BIT;
      break;
    default:                                     // 在本应用中,所有其它状态码均没有意义,通信复位
      STO = SET_BIT;
      SM_BUSY = CLR_BIT;
      break;
  }
  SI = CLR_BIT;                                  // 清除中断标志
}

// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** 函数名称: ADC0_ISR
** 功能描述: ADC0转换结束中断服务程序。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:略
** 调用模块: 略
** 其它说明:ADC0转换结果与工程量(气体压力)之间的转换原理如下:
**           由于电气比例阀ITV2000的信号输出与压力之间的对应关系为:1-5V对应于0-0.5MPa,假设1-5V信号经
**           2.5倍分压后(即0.4-2V)进入单片机,其对应的ADC0数字量(即mADC0Res变量的值)为:
**               0.4V===0.4*4096/VREF0,2V===2*4096/VREF0,
**           其中,4096为ADC0的转换位数(12位),VREF0为ADC0的参考电压(典型值为2.43V)。
**           将压力信号扩大10000倍,则0-0.5MPa对应数字0-5000(单位为0.1KPa)。为了便于计算,这里采用直线
**           方程来得到压力与电压数字量之间的关系:
**               P1 = 0 = COEF0*0.4*4096/VREF0 + COEF1
**               P2 = 5000 = COEF0*2*4096/VREF0 + COEF1
**           因VREF0可以测得,因此可以解上述方程组。为便于进行整数运算,将VREF0扩大1000倍,则上述方程组可
**           表述为:
**               P1 = 0 = COEF0*400*4096/VREF0 + COEF1
**               P2 = 5000 = COEF0*2000*4096/VREF0 + COEF1
**           解方程组得系数COEF0和COEF1分别为:
**               COEF0 = VREF0*25/32768
**               COEF1 = -1250
**           故压力方程为:
**               P = D*VREF0*25/32768 - 1250

⌨️ 快捷键说明

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