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

📄 main.c

📁 一个采用C8051F020芯片实现的流量计控制系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  {0x15,0x0D,0x0E,0x14,0x1E},                    // ID:6, -LEdn,即-LEDN
  {0x0A,0x0C,0x0E,0x14,0x1E},                    // ID:7, -LECa,即-LECA(在V1.01版本中未用)
  {0x16,0x0C,0x0E,0x14,0x1E},                    // ID:8, -LECo,即-LECO(在V1.01版本中未用)
  {0x19,0x0E,0x1C,0x16,0x1E},                    // ID:9, -ouEr,即-OVER
  {0x15,0x0E,0x0D,0x13,0x19},                    // ID:10,ridEn,即RIDEN
#if METER_RANGE == A150CN
  {0x15,0x0C,0x00,0x05,0x01}                     // ID:11,150Cn,即150Cn
#else
  {0x15,0x0C,0x00,0x00,0x02}                     // ID:11,200Cn,即200Cn
#endif
};

/************************************************
** 为了加快Decode算法的计算速度,在存储器中生成一
** 个0~10000、按10倍递增的数组序列。
************************************************/
UINT16 code TAB_COEF[] = {0, 10, 100, 1000, 10000};

/************************************************
** 各分组参数在EEPROM中的地址
** 共10组参数,每组包含9个参数,每组的最后两个参
** 数分别是流量分段最大值和流量分段系数,因软件中
** 只使用了3组流量校准系数,因此其余7组实际上并没
** 有利用上,这里仍列出以作将来扩展使用。
************************************************/
UINT16 code PARAM_ADDR[][9] = 
{
  {  0,  4,  8, 12, 16, 20, 24, 28, 32},         // GroupID:0,ParamID:0-8
  { 36, 40, 44, 48, 52, 56, 60, 64, 68},         // GroupID:1,ParamID:0-8
  { 72, 76, 80, 84, 88, 92, 96,100,104},         // GroupID:2,ParamID:0-8
  {108,112,116,120,124,128,132,136,140},         // GroupID:3,ParamID:0-8
  {144,148,152,156,160,164,168,172,176},         // GroupID:4,ParamID:0-8
  {180,184,188,192,196,200,204,208,212},         // GroupID:5,ParamID:0-8
  {216,220,224,228,232,236,240,244,248},         // GroupID:6,ParamID:0-8
  {252,256,260,264,268,272,276,280,284},         // GroupID:7,ParamID:0-8
  {288,292,296,300,304,308,312,316,320},         // GroupID:8,ParamID:0-8
  {324,328,332,336,340,344,348,352,356}          // GroupID:9,ParamID:0-8
};

// ------------------------------------------------------------------------------------------------------
/* 函数声明 */
void DeviceInit(void);
void SysInit(void);
void SetRxd0OK(void);
void SetRxd1OK(void);
void CheckPress(void);
void AdjustPress(void);
void GetKey(void);
void DoneRxd0(void);
void DoneRxd1(void);
void DoneTest(void);
void DoneDisplay(void);
void DoneKey(void);
void DoneFuncKey(void);
void DoneSetKey(void);
void DoneLeftKey(void);
void DoneRightKey(void);
void DoneUpKey(void);
void DoneDownKey(void);
void DoneStartKey(void);
void DoneStopKey(void);
void Decode(UINT16 nData, UINT8 nBuf[]);
void Encode(UINT16 *nData, UINT8 nBuf[]);
void LoadGroup(void);
void LoadParam(void);
void LoadLeakCoef(void);  // V1.01
bit  DecBuf(UINT8 nBuf[], UINT8 nStartID);
bit  GetMemAddr(UINT16 nAddr);
void SMB_Read(UINT16 nAddr, UINT8 *nData);
void SMB_Write(UINT16 nAddr, UINT8 nData);
void ReadParams(UINT16 nAddr, UINT8 nNums, UINT8 *nData);
void WriteParams(UINT16 nAddr, UINT8 nNums, UINT8 *nData);

// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** 函数名称: main
** 功能描述: 主程序。
** 输  入: 无
** 输  出: 无
** 全局变量: 略
** 全局常量:略
** 调用模块:略
** 其它说明:
** 设 计 者:罗建                                                                日  期:2008年02月16日
** 版    本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void main(void)
{
  UINT8 i;

  WDTCN = 0xDE;                                  // 禁止看门狗定时器
  WDTCN = 0xAD;
  DeviceInit();                                  // 初始化片上系统外围设备
  SysInit();                                     // 初始化系统变量
  LED_PASS = OPEN;                               // 打开LED指示灯进行自检
  LED_FAIL = OPEN;
  LED_WARN = OPEN;
  for (i=0;i<5;i++)                              // 准备LOGO字符
  {
    gnSegBuf[0][i] = FIX_CODE[10][i];
    gnSegBuf[1][i] = FIX_CODE[11][i];
  }
  while (!gbLogoOver)                            // 显示LOGO画面4秒
  {
    if (gb100msOver)
    {
      gb100msOver = FALSE;
      if (gnCntLogo++ == LOGO_WAIT)
        gbLogoOver = TRUE;
    }
  }
  for (i=0;i<5;i++)                              // 清除LOGO字符
  {
    gnSegBuf[0][i] = 0x00;
    gnSegBuf[1][i] = 0x00;
  }
  gnDisBuf[0][4] = NONE;                         // 左边第5位不显示字符
  gnDisBuf[1][4] = NONE;                         // 右边第5位不显示字符
  LED_PASS = CLOSE;                              // 自检完毕
  LED_FAIL = CLOSE;
  LED_WARN = CLOSE;
  while (TRUE)                                   // 主程序循环
  {
    DoneRxd0();                                  // 处理UART0接收数据事件
    DoneRxd1();                                  // 处理UART1接收数据事件
    if (gb100msOver)                             // 检查定时间隔是否到(0.1秒)
    {
      gb100msOver = FALSE;                       // 准备重新延时
      if (gbADC0OK)                              // 检查ADC0转换是否完成,完成则重新启动下一轮转换
      {
        gnADC0Res = gnADC0Res/ADC0_SAMPLE_NUMS;  // 计算平均值
        gnADC0Res = gnADC0Res*VREF0*25/32768;    // 进行工程量转换,如果值小于0,则认为是0
        if (gnADC0Res <= 1250)
          gnPressGet = 0;
        else
          gnPressGet = gnADC0Res - 1250;
        if (gnCntPressDis++ == PRESS_DIS_WAIT)   // 压力显示刷新时间到,刷新压力显示值
        {
          gnCntPressDis = 0;
          if ((gnWorkState != wsParamSet) && (gnWorkState != wsCoefSet))  // 如果不是在参数修改状态,则分解并显示压力值
          {
            if (gbPressStabled)                  // 压力稳定时只显示压力设计值
              Decode(gnPressSet, gnSegBuf[0]);   // 分解压力值
            else                                 // 压力波动时显示实测压力值
              Decode(gnPressGet, gnSegBuf[0]);   // 分解压力值
          }
        }
        CheckPress();                            // 检查是否超压
        AdjustPress();                           // 进行压力调节
        gbADC0OK = FALSE;                        // 复位ADC0转换结束标志
        AD0EN = TRUE;                            // 重新启动下一轮AD转换
      }
      if (gnCntFlash++ == FLASH_WAIT)            // 实现闪烁控制
      {
        gnCntFlash = 0;
        gbCanFlash = !gbCanFlash;
      }
      DoneKey();                                 // 处理按键事件
      DoneTest();                                // 执行流量测试
    }
  }
}

/********************************************************************************************************
** 函数名称: 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的方法。
**
** 设 计 者:罗建                                                                日  期:2008年02月03日
** 版    本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_ISR(void) interrupt INT_UART0

⌨️ 快捷键说明

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