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

📄 main.#3

📁 一个采用C8051F020芯片实现的流量计控制系统源代码
💻 #3
📖 第 1 页 / 共 5 页
字号:
void WriteToEEPROM(INT8U nAddr, INT8U *nData, INT8U nLen);
void ReadFromEEPROM(INT8U nAddr, INT8U *nData, INT8U nLen);
char SMB_Read(char nAddr, char nNumber);
void SMB_Send(char nAddr, char nData, char nNumber);


void EraseEEPROM(void)
{
  INT8U xdata *pWrite;

  FLSCL |= ALLOW_FLASH_WRITE;               // 允许由用户软件写/擦除FLASH
  PSCTL |= ALLOW_TEMP_MEM;                  // 允许擦除临时FLASH存储器
  PSCTL |= ALLOW_ERASE;
  PSCTL |= ALLOW_WRITE;
  pWrite = 0x00;
  *pWrite= 0xFF;                            // 写任意数据到指定地址以擦除该地址处的扇区
  PSCTL &= FORBID_FLASH_WRITE;              // 禁止Flash写擦除操作
  FLSCL &= FORBID_FLASH_OPERATE;            // 禁止由用户软件写/擦除FLASH
}

void WriteToEEPROM(INT8U nAddr, INT8U *nData, INT8U nLen)
{
  INT8U i;
  INT8U xdata *pWrite;

  FLSCL |= ALLOW_FLASH_WRITE;               // 允许由用户软件写/擦除FLASH
  PSCTL |= ALLOW_TEMP_MEM;                  // 允许写临时FLASH存储器
  PSCTL |= ALLOW_WRITE;
  pWrite = (INT8U xdata *)nAddr;            // 准备要写的FLASH首地址
  //pWrite = nAddr;
  for (i=0;i<nLen;i++)
    *pWrite++ = *nData++;                   // 写数据到指定地址
  PSCTL &= FORBID_FLASH_WRITE;              // 禁止Flash写擦除操作
  FLSCL &= FORBID_FLASH_OPERATE;            // 禁止由用户软件写/擦除FLASH
}

void ReadFromEEPROM(INT8U nAddr, INT8U *nData, INT8U nLen)
{
  INT8U i;
  INT8U code *pRead;

  PSCTL |= ALLOW_TEMP_MEM;                  // 允许读临时FLASH存储器
  pRead = (INT8U code *)nAddr;
  //pRead = nAddr;
  for (i=0;i<nLen;i++)
    //*nData++ = CBYTE[i+nAddr];
    *nData++ = *pRead++;
  PSCTL &= FORBID_FLASH_WRITE;              // 禁止Flash写擦除操作
}

// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** 函数名称: main
** 功能描述: 主程序。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:略
** 调用模块:略
** 设 计 者:罗建                                                                日  期:2007年12月09日
** 版    本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void main(void)
{
  INT8U nWData[5]={1,2,3,4,5};
  INT8U nRData[5]={0,0,0,0,0};
  INT8U xdata nData[256];
  INT8U i;

  WDTCN = 0xDE;                             // 禁止看门狗定时器
  WDTCN = 0xAD;
  DeviceInit();                             // 初始化片上系统外围设备   
  SysInit();                                // 初始化系统变量
  /*
  TH4 = 0x00;
  TL4 = 0x00;
  T4CON |= 0x04;
  EraseEEPROM();
  T4CON &= ~0x04;

  TH4 = 0x00;
  TL4 = 0x00;
  T4CON |= 0x04;
  WriteToEEPROM(0x00, nWData, 5);
  T4CON &= ~0x04;
  */
  TH4 = 0x00;
  TL4 = 0x00;
  T4CON |= 0x04;
  ReadFromEEPROM(0x00, nRData, 5);
  T4CON &= ~0x04;

  EA = 1;
  /*
  TH4 = 0x00;
  TL4 = 0x00;
  T4CON |= 0x04;
  for (i=0;i<128;i++)
    SMB_Send(i, i, 1);
  T4CON &= ~0x04;
  */

  TH4 = 0x00;
  TL4 = 0x00;
  T4CON |= 0x04;
  for (i=0;i<128;i++)
    nData[i] = SMB_Read(i, 1);
  T4CON &= ~0x04;


  while (TRUE)                              // 主程序循环
  {
    while (!gbTimeOver);                    // 检查定时间隔是否到(0.1秒)
    gbTimeOver = FALSE;                     // 准备重新延时

    // 
	if (gnCntADC-- == 0)
	{
	  gnCntADC = ADC_WAIT;
      AD0EN = TRUE;
    }
	// 检查压力是否超出设定的最大与最小值,是则警告  
    if ((gnPressGet > gnPressMax) || (gnPressGet < gnPressMin))
	{
	  if (!gbReadyWarn)                     // 当首次检测到压力超出设定值时,开始计时
	  {
	    gbReadyWarn = TRUE;
	    gnCntWarn = WARN_WAIT;
      }
      else if (gnCntWarn-- == 0)            // 当压力超出设定值的时间持续10秒后,输出报警指示
	  {
	    gbReadyWarn = FALSE;
        DRV_WARN = OPEN;        
	  }
    }
	else                                    // 压力在设定值区间内,不用报警
	{
	  gbReadyWarn = FALSE;
      gnCntWarn = 0;
      DRV_WARN = CLOSE;
    }
    AdjustPress();                          // 进行压力调节
    DoneKey();                              // 按键检测处理
    DoneTest();                             // 执行流量测试
    DoneDisplay();                          // 执行数据显示
  }
}

/********************************************************************************************************
** 函数名称: UART0_ISR
** 功能描述: 串行口UART0中断(仅处理数据接收中断)服务程序。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块: 无
** 其它说明: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 UART0_ISR(void) interrupt INT_UART0
{
  INT8U i;
  INT32 nRes;

  if (RI0)
  {
    RI0 = FALSE;                                 // 清除接收中断标志,允许下次接收数据
	if (gbSyncTwoOK1)                            // 检查同步字节是否接收完毕
	{
      if (SBUF0 == 0x7F)                         // 同步字节已接收完毕,但仍接收到了0x7F,说明出现了最糟糕
	    return;                                  // 的情况,即有3个0x7F,因此需将该字节舍弃。
      gnRxdBuf0[gnRxdID0++] = SBUF0;
      if (gnRxdID0 == 2)                         // 检查字节是否接收完毕,接收完则为下次接收做好准备
	  {        
        SetRxd0OK();                             // 重新初始化同步字节检测标志和串口接收缓冲区索引
		if (gbStarted && gbTestOver)             // 当测试进程结束,且用户尚未按下停止键时,不更新流量显示值
		  return;
        nRes = gnRxdBuf0[0];                     // 先计算测量值
		nRes = nRes*256 + gnRxdBuf0[1];
        if (gnRxdBuf0[0] & 0x80)                 // 如果测量值为负,则认为是0
          nRes = 0;
        else
          nRes = nRes * 100 / 128;               // 将从串口接收到的数字量转换为物理量用于显示(单位:0.01L/min)
		for (i=0;i<6;i++)                        // 对流量值采取分段线性修正,如果流量值不在设定的流量范围,
		{                                        // 则保持上一次采集计算的值不变,这样可防止强脉冲干扰
          if (nRes < gnLeakAreaMax[i])

⌨️ 快捷键说明

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