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

📄 main.#2

📁 一个采用C8051F020+CH372实现的带USB功能的流量测控系统
💻 #2
📖 第 1 页 / 共 3 页
字号:
  XBR1 = 0x04;
  XBR2 = 0x44;                              // 允许交叉开关和弱上位

  // ADC和DAC(取默认值)转换初始化
  AMX0CF = 0x00;                            // 配置AIN00-AIN07均为单端输入方式(默认)
  AMX0SL = 0x00;                            // 选择AIN00通道进行AD转换(默认)
  ADC0CF = 0x50;                            // ADC0转换时钟为2MHz,PGA增益为1
  ADC0CN = 0x84;                            // 允许ADC0,正常跟踪模式,Timer3溢出启动ADC0转换,ADC0数据右对齐
  DAC0   = 0x0000;                          // 默认DAC0输出为0
  //DAC1   = 0x0000;                          // 默认DAC1输出为0
  DAC0CN = 0x80;                            // 允许DAC0输出,写DAC0H时DAC0更新输出,DAC0H3-0保存高4位,DAC0L7-0保存低8位(默认)
  //DAC1CN = 0x80;                            // 允许DAC1输出,写DAC1H时DAC1更新输出,DAC1H3-0保存高4位,DAC1L7-0保存低8位(默认)

  // ADC和DAC参考电压初始化
  REF0CN = 0x03;                            // ADC0电压基准取至VREF0,禁止温度传感器,内部偏压发生器和基准电压缓冲器打开

  // 串口UART0和UART1初始化
  SCON0     = 0x50;                         // UART0为8位可变波特率模式,允许接收
  SCON1     = 0x50;                         // UART1为8位可变波特率模式,允许接收

  // 定时器初始化
  CKCON     = 0x10;                         // TIMER1时钟源为SYSCLK,TIMER4、TIMER2、TIMER0时钟源为SYSCLK/12
  TMOD      = 0x21;                         // TIMER1为8位自动重装载模式,TIMER0为16位定时器方式
  TH1       = 0xDC;                         // TIMER1作为UART0和UART1的波特率发生器,波特率均为19200bps
  TCON      = 0x40;                         // 允许TIMER1定时
  RCAP2H    = 0xB8;                         // TIMER2自动重装载值(定时10ms,RCAP2L=0x00)
  TH2       = 0xB8;                         // TIMER2计数寄存器初值(定时10ms,TL2=0x00)
  T2CON     = 0x04;                         // TIMER2作为10ms定时器,16位自动重装载模式,允许定时
  TMR3RLL   = 0x9A;                         // TIMER3自动重装载值(定时1ms)
  TMR3RLH   = 0xA9;
  TMR3L     = 0x9A;                         // TIMER3计数寄存器初值(定时1ms)
  TMR3H     = 0xA9;
  TMR3CN    = 0x06;                         // TIMER3作为1ms定时器,控制ADC,使用SYSCLK,允许定时

  // 中断初始化
  EIE2      = 0x42;                         // 允许UART1和ADC0中断
  IE        = 0xB0;                         // 允许TIMER2、UART0中断,开总中断
}

// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** 函数名称: SysInit
** 功能描述: ADC0转换结束中断服务程序。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:略
** 调用模块:略
** 设 计 者:罗建                                                                日  期:2007年12月09日
** 版    本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void SysInit(void)
{
  gbCanGetKey  = TRUE;
  gnTxdBuf0[0] = 0xFF;
  gnTxdBuf0[1] = 0xFF;
  gnCntAdjust  = ADJUST_WAIT;
}

// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** 函数名称: 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
**           式中,P为待测压力,单位为0.1KPa,D为ADC0测得的对于输入电压的数字量。如果P<0,则应将其置0。
**
** 设 计 者:罗建                                                                日  期:2007年12月09日
** 版    本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void ADC0_ISR(void) interrupt INT_ADC0
{
  static INT8U nADC0Cnt=ADC0_SAMPLE_NUMS;   // ADC0采样次数计数器定义及初始化
  INT32U nPress;

  AD0INT = FALSE;                           // 清除ADC0转换结束标志
  gnADC0Res += ADC0;                        // 累加ADC0转换结果并取平均
  nADC0Cnt--;                               // ADC0连续转换ADC0_SAMPLE_NUMS次,完成后暂停转换(不响应中断)
  if (nADC0Cnt == 0)                        // 同时将结果转换为工程量值(气体压力)
  {
    nADC0Cnt = ADC0_SAMPLE_NUMS;
	AD0EN = FALSE;
    gnADC0Res = gnADC0Res/(ADC0_SAMPLE_NUMS+1);
    nPress = gnADC0Res*VREF0*25/32768;         // 进行工程量转换,如果值小于0,则认为是0
	if (nPress <= 1250)
	  gnPressGet = 0;
    else
	  gnPressGet = nPress - 1250;
  }
}

/********************************************************************************************************
** 函数名称: UART0_ISR
** 功能描述: 串行口UART0中断服务程序。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块:无
** 设 计 者:罗建                                                                日  期:2007年12月09日
** 版    本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_ISR(void) interrupt INT_UART0
{
  if (RI0)                                  // 数据接收中断
  {
    RI0 = FALSE;                            // 清除数据接收中断标志
    if (gbSyncTwoOK0)                       // 检查同步字节是否接收完毕
	{
      if (SBUF0 == 0xFF)                    // 同步字节已接收完毕,但仍接收到了0xFF,说明出现了最糟糕
	    return;                             // 的情况,即有3个0xFF,因此需将该字节舍弃。
      gnRxdBuf0[gnRxdID0++] = SBUF0;
      // 接收设定参数及系数命令(0xFF,0xFF,0x00,0x02,Data,共44个字节,数据按先低后高的顺序发送)
      if (gnRxdID0 >= 32)             // 检查数据是否接收完毕(包括两个命令字节)
      {
        gnPressSet = gnRxdBuf0[1]*256 + gnRxdBuf0[0];     // 预设测试压力值(单位:0.1KPa)
	    gnPressMax = gnRxdBuf0[3]*256 + gnRxdBuf0[2];     // 允许的最高压力值(单位:0.1KPa)
	    gnPressMin = gnRxdBuf0[5]*256 + gnRxdBuf0[4];     // 允许的最低压力值(单位:0.1KPa)
	    gnLeakMax  = gnRxdBuf0[7]*256 + gnRxdBuf0[6];     // 允许的最高流量值(单位:0.01L/min)
	    gnFillTime = gnRxdBuf0[9]*256 + gnRxdBuf0[8];   // 充气时间(单位:0.1S)
	    gnTestTime = gnRxdBuf0[11]*256 + gnRxdBuf0[10];   // 测试时间(单位:0.1S)
		// 由于流量测量的最小值为0,因此其下限始终为0,尽管触摸屏传了值(即gnRxdBuf0[13]*256 + gnRxdBuf0[12]),
        // 但该值始终为0,因此这里并不读取它
		gnLeakAreaMax[0]  = gnRxdBuf0[15]*256 + gnRxdBuf0[14];  // 流量校线阶段1对应的最大流量
        gnLeakAreaCoef[0] = gnRxdBuf0[17]*256 + gnRxdBuf0[16];  // 流量校线阶段1对应的流量修正系数
		gnLeakAreaMax[1]  = gnRxdBuf0[19]*256 + gnRxdBuf0[18];  // 流量校线阶段2对应的最大流量
        gnLeakAreaCoef[1] = gnRxdBuf0[21]*256 + gnRxdBuf0[20];  // 流量校线阶段2对应的流量修正系数
		gnLeakAreaMax[2]  = gnRxdBuf0[23]*256 + gnRxdBuf0[22];  // 流量校线阶段3对应的最大流量
        gnLeakAreaCoef[2] = gnRxdBuf0[25]*256 + gnRxdBuf0[24];  // 流量校线阶段3对应的流量修正系数
		gnLeakAreaMax[3]  = gnRxdBuf0[27]*256 + gnRxdBuf0[26];  // 流量校线阶段4对应的最大流量
        gnLeakAreaCoef[3] = gnRxdBuf0[29]*256 + gnRxdBuf0[28];  // 流量校线阶段4应的流量修正系数
        SetRxd0OK();                    // 重新初始化同步字节检测标志及串口接收缓冲区索引
        gnTxdBuf0[0] = 0xFF;            // 发送测量数据及开关状态至触摸屏命令(0xFF,0xFF,0x00,0x01,共4个字节)
		gnTxdBuf0[1] = 0xFF;
		gnTxdBuf0[2] = 0x01;            // 准备发送命令的低8位字节
        gnTxdBuf0[3] = 0x00;            // 准备发送命令的高8位字节
        gnTxdBuf0[4] = gnPressGet % 256;// 准备发送测试压力的低8位字节
        gnTxdBuf0[5] = gnPressGet / 256;// 准备发送测试压力的高8位字节
        gnTxdBuf0[6] = gnLeakGet % 256; // 准备发送气体流量的低8位字节
        gnTxdBuf0[7] = gnLeakGet / 256;	// 准备发送气体流量的高8位字节
        gnTxdID0 = 0;
        gnTxdNums0 = 7;                 // 指示要向触摸屏发送的数据个数为8个(含帧头,因下面将先发送一个字节,故为7)
		SBUF0 = gnTxdBuf0[0];           // 开始发送数据至触摸屏        
	  }
	}
    else                                    // 同步字节还未接收完毕,继续检测
	{
      if (SBUF0 == 0xFF)                    // 如果是同步字节,则设置相应的同步字节接收到标志
      {
	    if (gbSyncOneOK0)
		  gbSyncTwoOK0 = TRUE;
		else
		  gbSyncOneOK0 = TRUE;
	  }
      else                                  // 接收到的字节既非同步字节又非正常的测量数据,舍弃重来。
		SetRxd0OK();                        // 重新初始化同步字节检测标志及串口接收缓冲区索引
	}
  }
  else                                      // 数据发送中断
  {
    TI0 = FALSE;                            // 清除数据发送中断标志
    if (gnTxdID0 < gnTxdNums0)              // 将发送缓冲区中的gnTxdNums0个数据发送至触摸屏
	{
	  gnTxdID0++;
	  SBUF0 = gnTxdBuf0[gnTxdID0];
    }
  }
}

/********************************************************************************************************
** 函数名称: UART1_ISR
** 功能描述: 串行口UART1中断(仅处理数据接收中断)服务程序。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块: 无
** 其它说明:1、RIDen A50流量传感器的通讯协议
**           1)波特率:19200bps;
**           2)数据位:8位;
**           3)停止位:1位;
**           4)奇偶校验:none;
**           5)协  议:none;
**           6)回 波:传感器保证一个回波。
**           7)数据格式:接收到的数值是一个表示两种含义的有符号的16位整型数。标定后的数据是原始接收数据除
**             以一个常系数而得来的,由此转成小数。对于A50_V型,流量系数为128,温度系数为100。例:接收到
**             的数值为+1234(十进制),在流量模式中表示的相应流量值为9.641Ln/min,在温度模式中表示的温度
**             为12.34℃。
**           8)帧格式:0x7F,0x7F,MSB,LSB
**             由于最大量程为0x7852,高位字节不包含0x7F。因此,最糟糕的情况就是较低位的字节中包含有0x7F。
**             在这种情况下,0x7F在一行中出现3次。例如:
**             值为:7C 7F,则接收数串为:7F 7F 7C 7F 7F 7F 7C 7F。在假码中找出同步的最好方法如下:
**             如果Buf[i]=7F,且Buf[i+1]=7F,且Buf[i+2]<>7F,则Buf[i]和Buf[i+1]就是同步字节。
**           9)对整型数值的解释如下:
**           接收值(16进制)  接收值(10进制)  流量(Ln/min)  温度(℃)
**                    0x7852             30802        overflow        ----
**                    0x7851             30801   peak overflow        ----
**                    0x7850             30800        +240.600     +308.00
**                    ......             .....        ........     .......
**                    ......             .....        ........     .......
**                    0x0001                 1       +0.007813        0.01
**                    0x0000                 0        0.000000        0.00
**                    0xFFFF                -1       -0.007813       -0.01
**                    ......             .....        ........     .......
**                    ......             .....        ........     .......
**                    0x87B0            -30800        -240.600     -380.00
**           *************************************************************
**           负数与正数是对称的,可用以下公式计算负数A对应的正数B:
**           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;
  static INT8U nLeakCnt=LEAK_SAMPLE_NUMS;   // ADC0采样次数计数器定义及初始化

  if (SCON1&0x01)

⌨️ 快捷键说明

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