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

📄 main14.c

📁 一个采用C8051F020+CH372实现的带USB功能的流量测控系统
💻 C
📖 第 1 页 / 共 3 页
字号:
**           B = ~(A-1)
**
**           2、工程量(流量)转换问题
**           对于A50_V型,流量系数为128。为了不使用浮点数进行计算,且又希望保留2位小数精度,因此可采用将
**           串口接收值先乘以100,再除以128(用右移7位实现)的方法来实现。这样,如果接收到的数值为十进制
**           的+1234,则在流量模式中利用上述方法计算的流量值为9.64Ln/min,所得的测量精度为±0.01Ln/min,
**           可以满足使用要求。
**
**           3、显示与储存冲突防治
**           由于串口接收数据是随机的,且数据有多字节(至少为2字节),在显示过程中,如果主程序刚访问了第1
**           个字节,这时发生了串口中断,并且更新了要显示的数据,当串口中断返回时,主程序继续显示第2个字
**           节,这时显示结果将可能是不正确的。
**           为防止上述冲突现象的发生,可采用Win32 API中的“临界区”思想来实现,即在主程序中读取数据前,
**           先关闭串口中断允许标志ES,在读取完数据后再打开串口中断允许标志ES的方法。
**
** 设 计 者:罗建                                                                日  期:2007年12月09日
** 修 改 者:罗建                                                                日  期:2007年03月23日
** 修 改 者:罗建                                                                日  期:2007年12月09日
** 历史版本:V1.00,原始版本
**           V1.01,修改了流量计算方式
** 版    本:V1.02,适应C8051F020单片机的串口UART1
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART1_ISR(void) interrupt INT_UART1
{
  //INT8U  i;
  INT32U nRes;

  if (SCON1&0x01)
  {
    SCON1 &= ~0x01;                              // 清除接收中断标志,允许下次接收数据
	if (gbSyncTwoOK1)                            // 检查同步字节是否接收完毕
	{
      if (SBUF1 == 0x7F)                         // 同步字节已接收完毕,但仍接收到了0x7F,说明出现了最糟糕
	    return;                                  // 的情况,即有3个0x7F,因此需将该字节舍弃。
      gnRxdBuf1[gnRxdID1++] = SBUF1;
	  if (gnRxdID1 == 2)                         // 检查字节是否接收完毕,接收完则为下次接收做好准备
	  {        
        SetRxd1OK();                             // 重新初始化同步字节检测标志和串口接收缓冲区索引
		if (gbStarted && gbTestOver)             // 当测试进程结束,且用户尚未按下停止键时,不更新流量显示值
		  return;
        nRes = gnRxdBuf1[0];                     // 先计算测量值
		nRes = nRes*256 + gnRxdBuf1[1];
        if (gnRxdBuf1[0] & 0x80)                 // 如果测量值为负,则乘以-1转换为正数
          nRes = 0;
		//for (i=0;i<1;i++)                        // 对流量值采取分段线性修正,如果流量值不在设定的流量范围,
		//{                                        // 则保持上一次采集计算的值不变,这样可防止强脉冲干扰
          /*if (nRes < gnLeakAreaMax[i])*/
		  /*{*/
		  //nRes *= gnLeakAreaCoef[i] ; 
		  //nRes /= 128;
		  EA=0;
          gnLeakGet = nRes;
         EA =1;
 		//	break;
          /*}*/
        //}
	  }
	}
	else                                         // 同步字节还未接收完毕,继续检测
	{
      if (SBUF1 == 0x7F)                         // 如果是同步字节,则设置相应的同步字节接收到标志
      {
	    if (gbSyncOneOK1)
		  gbSyncTwoOK1 = TRUE;
		else
		  gbSyncOneOK1 = TRUE;
	  }
	  else                                       // 接收到的字节既非同步字节又非正常的测量数据,舍弃重来。
		SetRxd1OK();                             // 重新初始化同步字节检测标志和串口接收缓冲区索引
	}
  }
  else
    SCON1 &= ~0x02;                              // 清除发送中断标志,允许下次接收数据    
}

/********************************************************************************************************
** 函数名称: TIMER2_ISR
** 功能描述: TIMER2定时中断服务程序。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块: 无
** 设 计 者:罗建                                                                日  期:2007年12月09日
** 版    本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void TIMER2_ISR(void) interrupt INT_TIMER2
{
  TF2 = FALSE;
  gnCnt10ms++;
  if (gnCnt10ms >= 10)                 // 定时100ms
  {
    gbTimeOver = TRUE;
	gnCnt10ms = 0;
  }
}

// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** 函数名称: SetRxd0OK和SetRxd1OK
** 功能描述: UART0或UART1数据接收完毕,重新初始化同步字节检测标志及接收缓冲区索引。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块: 无
** 设 计 者:罗建                                                                日  期:2007年12月09日
** 版    本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void SetRxd0OK(void)
{
  gbSyncOneOK0 = FALSE;
  gbSyncTwoOK0 = FALSE;
  gnRxdID0 = 0;
}

void SetRxd1OK(void)
{
  gbSyncOneOK1 = FALSE;
  gbSyncTwoOK1 = FALSE;
  gnRxdID1 = 0;
}

// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** 函数名称: AdjustPress
** 功能描述: 判断当前测试压力值是否超过设定范围,是则调节。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块: 无
** 设 计 者:罗建                                                                日  期:2007年12月09日
** 版    本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void AdjustPress(void)
{
  INT16 nErr;

  // 仅当进入测试画面后才进行压力调节
  if (gnCntAdjust-- != 0)
    return;
  gnCntAdjust = ADJUST_WAIT;

  // 调节比例阀的输出,使其等于用户设定值
  nErr = gnPressSet - gnPressGet;           // 计算设定值与实测值之间的差值
  if ((nErr > -20) && (nErr < 20));
      return; 
  gnPressOut = gnPressOut + nErr;
  DAC0L = gnPressOut % 256;                 // 最后将输出值通过DAC0输出给压力调节阀
  DAC0H = gnPressOut / 256;
  /*DAC0  = 0x0FFF;*/
}


// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** 函数名称: DoneKey
** 功能描述: 检测哪个键有按下,如有键按下则进行相应的处理。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块: 无
** 设 计 者:罗建                                                                日  期:2007年12月09日
** 版    本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void DoneKey(void)
{
  if (!gbCanGetKey)                         // 检测用户按键情况
  {
    if (gnCntGetKey-- == 0)                 // 实现按键检测延时
      gbCanGetKey = TRUE;
  }
  else                                      // 可以检测按键
  {
    if (!KEY_START)                         // 启动键按下
	{
	  if (!gbStarted)                       // 仅在启动按键尚未按下时才响应启动键操作
      {
        gnCurrTime= gnFillTime;             // 准备充气时间
        DRV_PASS  = CLOSE;                  // 先将PASS和FAIL指示灯关闭
        DRV_FAIL  = CLOSE;
        DRV_VALVE = OPEN;                   // 打开控制阀
        gbTestOver= FALSE;                  // 假定测试状态未结束
        gbStarted = TRUE;                   // 进入启动测试状态
        gbFilling = TRUE;                   // 进入充气时间倒计数状态
      }
	}
    else if (!KEY_STOP)                     // 停止键按下
	{
      DRV_VALVE = CLOSE;                    // 关闭电磁阀
      gbFilling = FALSE;                    // 退出充气时间倒计数状态
      gbTesting = FALSE;                    // 退出测试时间倒计数状态
      gbStarted = FALSE;                    // 退出启动测试状态
      gbTestOver= FALSE;                    // 已经退出测试状态
	  DRV_PASS  = CLOSE;                    // 关闭PASS和FAIL指示灯
      DRV_FAIL  = CLOSE;
	}
    gnCntGetKey = KEY_WAIT;                 // 准备进行按键检测延时
    gbCanGetKey = FALSE;                    // 暂停下一次键检测
  }
}

// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** 函数名称: DoneTest
** 功能描述: 执行充气和测试操作。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块: 无
** 设 计 者:罗建                                                                日  期:2007年12月09日
** 版    本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void DoneTest(void)
{
  if (gbFilling)                          // 如果正在执行充气操作,则对充气时间进行递减
  {
    if (--gnCurrTime == 0)                // 如果充气时间减为全0,则进入测试状态
    {
      gbFilling = FALSE;
      gbTesting = TRUE;
      gnCurrTime = gnTestTime;            // 准备测试时间
    }
  }
  else if (gbTesting)                     // 如果正在执行测试操作,则对测试时间进行递减
  {
    if (--gnCurrTime == 0)                // 如果测试时间减为全0,则测试结束,关闭电磁阀并保持当前显示状态不变
    {
      gbTesting = FALSE;
      gbTestOver= TRUE;                   // 指示检测已完成
      DRV_VALVE = CLOSE;                  // 关闭电磁阀
	  if ((gnLeakGet > gnLeakMax) || (gnLeakGet < gnLeakMin))
	  {                                   // 测试结束后,如果气体流量超过了设定的流量范围,则FAIL灯亮,否则PASS灯亮
	    DRV_FAIL = OPEN;
	    DRV_PASS = CLOSE;
      }
	  else
	  {
        DRV_PASS = OPEN;
        DRV_FAIL = CLOSE;
	  }
    }
  }
}

⌨️ 快捷键说明

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