📄 main.c
字号:
/********************************************************************************************************
** RidenFlowForLED
**
** 版权所有 (c) 2007,罗建
** 保留所有权利
**
** V1.01
**
**
**-------------------------------------------------文件信息----------------------------------------------
**文 件 名: Main.C
**设 计 者: 罗建
**最后修改日期: 2008年03月01日
**描 述: 源程序。
**其 它:MCU采用C8051F020,外部晶振为22.1184MHz,采用两组共12个LED数码管显示测量数据和输入配置信息,
** 并控制电磁阀和比例阀调节充气及测试时的气体压力,以满足测试需要。
**所属项目概述:RIDEN FLOW流量计是用于测试气体流量的装置,其工作原理为:压缩空气经空气过滤器到达比例控制阀,
** 经比例控制阀调压稳定后,通过气路通断控制阀,到达气体流量计,然后进入产品。该装置功能就是测
** 量流过气体的质量流量。
** 各部件的作用如下:
** 1、比例控制阀:其作用是调节前端的高压气体以使其稳定在设置的压力值附近,为测试提供一个稳定的
** 气源。
** 2、气路通断控制阀:在每一个测量周期内,此阀通断一次,即在测试检测过程中打开,测试完成后关闭,
** 直到下一个测试开始。
** 3、气体流量计:用于测量流经该传感器的压缩空气的流量。
**基本技术参数:1、被测介质: 压缩空气,<0.8MPa;
** 2、气体流量范围: 0-99.99L/min;
** 3、流量精度: 0.01L/min;
** 4、采集及显示频率: 3Hz;
** 5、测试压力: 0-999.9KPa(自动调节,稳压);
** 6、测试压力精度: 0.1KPa;
** 7、充气时间: 0-999.9S;
** 8、测试时间: 0-999.9S;
** 9、校准系数: 3段;
** 10、通讯接口(To PC): RS232。
**
**-----------------------------------------------历史版本信息--------------------------------------------
** 设计者: 罗建
** 版 本: V1.00
** 日 期: 2008年02月04日
** 描 述: 原始版本
**
**-----------------------------------------------当前版本修订--------------------------------------------
** 修改者: 罗建
** 版 本: V1.01
** 日 期: 2008年03月01日
** 描 述: 1)为了扩大流量的显示范围(0-150Ln/min和0-200Ln/min),将流量的小数点改为了1位(原来为2位),
** 但流量修正系数仍为2位小数点;
** 2)修改了流量分段修正系数的设置方法,当按下功能键持续时间在5秒以上时,调出流量分段修正参数供厂
** 家修改,此时,左边LED显示当前流量段的流量值,右边显示当前流量段的系数值,按一下设置键,左边
** 值允许修改(闪烁),再按一下保存左边修改的值,同时右边的值允许修改(闪烁),再按一下保存右边
** 修改的值;
** 3)增加了一个工作状态,即测试结束状态(显示“r”)。
**
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#include <c8051f020.h> // SFR declarations
#include <intrins.h>
#include <absacc.h>
#include <string.h>
#include "GlobeDef.h"
//-------------------------------------------------------------------------------------------------------
/* C8051F02x单片机的16位SFR定义 */
sfr16 DP = 0x82; // data pointer
sfr16 TMR3RL = 0x92; // Timer3 reload value
sfr16 TMR3 = 0x94; // Timer3 counter
sfr16 ADC0 = 0xbe; // ADC0 data
sfr16 ADC0GT = 0xc4; // ADC0 greater than window
sfr16 ADC0LT = 0xc6; // ADC0 less than window
sfr16 RCAP2 = 0xca; // Timer2 capture/reload
sfr16 T2 = 0xcc; // Timer2
sfr16 RCAP4 = 0xe4; // Timer4 capture/reload
sfr16 T4 = 0xf4; // Timer4
sfr16 DAC0 = 0xd2; // DAC0 data
sfr16 DAC1 = 0xd5; // DAC1 data
//-------------------------------------------------------------------------------------------------------
/* 本项目对C8051F02x单片机的引脚重定义,其中,XBR0 = 0x1F,XBR1 = 0x14,XBR2 = 0x44,P0MDOUT = 0x15,P1MDOUT = 0x01,P2MDOUT = 0x00,P3MDOUT = 0x80 */
// P0
sbit UART0_TX = P0^0; // XBR0.2 = 1(UART0EN = 1),P0MDOUT.0 = 1,TX0作为推挽方式
sbit UART0_RX = P0^1;
sbit I2C_SDA = P0^2; // XBR0.0 = 1(SMB0EN = 1)
sbit I2C_SCL = P0^3;
sbit UART1_TX = P0^4; // XBR2.2 = 1(UART1EN = 1),P0MDOUT.4 = 1,TX1作为推挽方式
sbit UART1_RX = P0^5;
// P1
sbit KEY_START = P1^0; // P1MDOUT.0 = 0,漏极开路方式,并使KEY_START = 1将其配置为数字输入,低电平有效
sbit KEY_STOP = P1^1; // P1MDOUT.1 = 0,漏极开路方式,并使KEY_STOP = 1将其配置为数字输入,低电平有效
sbit DRV_PASS = P1^2; // P1MDOUT.2 = 0,漏极开路方式,作为数字输出,高电平由外部上拉电阻确定
sbit DRV_FAIL = P1^3; // P1MDOUT.3 = 0,漏极开路方式,作为数字输出,高电平由外部上拉电阻确定
sbit DRV_WARN = P1^4; // P1MDOUT.4 = 0,漏极开路方式,作为数字输出,高电平由外部上拉电阻确定
sbit DRV_VALVE = P1^5; // P1MDOUT.5 = 0,漏极开路方式,作为数字输出,高电平由外部上拉电阻确定
// P2
sbit DIS_RCK = P2^0; // P2MDOUT.0 = 0,漏极开路方式,作为数字输出,高电平由外部上拉电阻确定
sbit DIS_SCK = P2^1; // P2MDOUT.1 = 0,漏极开路方式,作为数字输出,高电平由外部上拉电阻确定
sbit DIS_SER = P2^2; // P2MDOUT.2 = 0,漏极开路方式,作为数字输出,高电平由外部上拉电阻确定
sbit LED_PASS = P2^3; // P2MDOUT.3 = 0,漏极开路方式,作为数字输出,高电平由外部上拉电阻确定
sbit LED_FAIL = P2^4; // P2MDOUT.4 = 0,漏极开路方式,作为数字输出,高电平由外部上拉电阻确定
sbit LED_WARN = P2^5; // P2MDOUT.5 = 0,漏极开路方式,作为数字输出,高电平由外部上拉电阻确定
sbit KEY1 = P2^6; // P2MDOUT.6 = 0,漏极开路方式,作为数字输入,默认为高电平,变低时表示有键按下
sbit KEY2 = P2^7; // P2MDOUT.7 = 1,漏极开路方式,作为数字输入,默认为高电平,变低时表示有键按下
// ------------------------------------------------------------------------------------------------------
/* 定义位变量 */
bit gbReadyWarn=FALSE; // 指示是否进入告警超时检测过程,0~否,1~是
bit gbCanGetKey=TRUE; // 指示是否可以再次检测按键,0~否,1~是
bit gb100msOver=FALSE; // 指示100ms定时间隔时间是否到,0~未到,1~已到
bit gbLogoOver=FALSE; // 指示LOGO画面显示时间是否到,0~未到,1~已到
bit gbTestOver=FALSE; // 指示当前是否已完成或退出了检测状态,0~非检测状态或检测过程未结束,1~检测完成(但未退出检测进程)
bit gbSyncOneOK0=FALSE; // 指示串口0数据帧的第一个同步字节是否接收完毕,0~未收到,1~收到
bit gbSyncTwoOK0=FALSE; // 指示串口0数据帧的第二个同步字节是否接收完毕,0~未收到,1~收到
bit gbSyncOneOK1=FALSE; // 指示串口1数据帧的第一个同步字节是否接收完毕,0~未收到,1~收到
bit gbSyncTwoOK1=FALSE; // 指示串口1数据帧的第二个同步字节是否接收完毕,0~未收到,1~收到
bit gbStarted=FALSE; // 指示<启动键>是否按下,0~未按下,1~按下
bit gbFilling=FALSE; // 指示当前是否工作于充气状态,0~否,1~是
bit gbTesting=FALSE; // 指示当前是否工作于测试状态,0~否,1~是
bit gbBufUsed=FALSE; // 指示LED段选缓冲区当前是否正在被非中断服务程序使用当中,0~未使用,1~正在使用
bit gbParamSel=FALSE; // 指示当前参数是否已处于待修改状态(闪烁),0~否,1~是
bit gbCanFlash=FALSE; // 该标志与gnCntFlash计数器配合实现闪烁间隔定时,0~不允许闪烁,1~允许闪烁
bit gbParamSet=FALSE; // 指示是否进入参数修改状态,0~否,1~是
bit gbLeakOver=FALSE; // 指示是否测量流量超出限制值,0~否,1~是
bit gbPressOver=FALSE; // 指示是否测量压力超出限制值,0~否,1~是
bit gbADC0OK=FALSE; // 指示ADC0转换是否结束,0~否,1~是
bit gbRxdOK0=FALSE; // 指示UART0串口一帧数据是否全部接收完毕,0~否,1~是
bit gbRxdOK1=FALSE; // 指示UART1串口一帧数据是否全部接收完毕,0~否,1~是
bit gbTxdOK1=TRUE;
bit SM_BUSY=FALSE; // SMBUS总线忙碌标志位,0~空闲,1~忙碌
bit gbAdjustOK=FALSE; // 用于控制功能键的5秒钟持续按下延时(V1.01)
bit gbFuncContinue=FALSE; // 用于说明功能键是否持续按下,0~否,1~是
bit gbPressStabled=FALSE; // 指示当前压力是否进入设定的范围,0~否,1~是
/* 定义字节变量 */
VUINT8 data gnWorkState=wsIdle; // 仪表当前工作状态(0=空闲,1=参数设置,2=充气,3=测试)
VUINT8 data gnKeyID=0; // 存放用户按键的键值,取值范围:0~8,0表示无按键
VUINT8 data gnScanID=0; // 按键和LED扫描序号,取值范围:0~5,0表示LED1或Q1
VUINT8 xdata gnCursorID=0; // 代表当前光标位置,由左移键和右移键进行控制,取值0~4
VUINT8 data gnGroupID=0; // 代表用户选择的参数分组索引,取值0~9,共10组
VUINT8 data gnParamID; // 代表当前用户选择的参数在参数组中的序号,取值0~PARAMS_NUMS-1
VUINT8 data gnCntFlash; // 代表当前光标闪烁的频率,实际频率=1/(gnCntFlash*0.1*2)Hz
VUINT8 data gnCntADC0=0; // ADC0采集间隔时间计数器(为了降低LCD的刷新率)
VUINT8 xdata gnCntWarn=0; // 压力告警超时计数器
VUINT8 xdata gnCntLogo=0; // LOGO画面显示延时读数器
VUINT8 data gnCntAdjust=0; // 压力调节时间计数器
VUINT8 data gnCnt2ms=0; // 2ms定时计数器,用于实现100ms定时
VUINT8 data gnCntGetKey=0; // 两次检测按键之间的时间间隔(实际间隔是该值乘以100ms
VUINT8 data gnCntPressDis=0;
VUINT8 data gnTxdID0=0; // 串口UART0发送缓冲区数组索引
VUINT8 data gnTxdID1=0; // 串口UART1发送缓冲区数组索引
VUINT8 data gnRxdID0=0; // 串口UART0接收缓冲区数组索引
VUINT8 data gnRxdID1=0; // 串口UART1接收缓冲区数组索引
VUINT8 data gnTxdNums0; // 串口UART0发送缓冲区数组中的数据个数,即要发送的数据个数
VUINT8 data gnTxdNums1; // 串口UART1发送缓冲区数组中的数据个数,即要发送的数据个数
VUINT8 data gnSlaAddrW; // 保存SMBUS设备从地址+WRITE位
VUINT8 data gnSlaAddrR; // 保存SMBUS设备从地址+READ位
VUINT8 data gnMemData; // 保存被收/发的数据字节
VUINT8 data gnMemAddr; // 保存被收/发的数据地址
VUINT8 data gnSendNums; // 保存被收/发的数据字节的数目
VUINT8 data gnSendMode; // 读/写控制字,为1时表示读操作,为0时表示写操作
VUINT8 data gnRxdBuf0[2]; // 串口UART0接收缓冲区数组
VUINT8 xdata gnRxdBuf1[6]; // 串口UART1接收缓冲区数组
VUINT8 xdata gnTxdBuf1[10]; // 串口UART1发送缓冲区数组
VUINT8 data gnDisBuf[2][6]; // LED显示缓冲区,用于实现双缓冲操作
VUINT8 data gnSegBuf[2][6]; // 两组段选缓冲区在SEG_CODE段选码数组中的数字索引
VUINT8 data gnFuncCnt=0; // 用于控制功能键的5秒钟持续按下延时(V1.01)
VUINT8 data gnOldGroupID=0; // 用于当修改分段流量系数时,临时保存分组索引,在返回待机状态时恢复(V1.01)
VUINT8 data gnSetID=1; // 指示当前正在修改的参数是左边6个LED上(0)还是右边6个LED上(1)
/* 定义字变量 */
VUINT16 data gnPressGet=0; // 测得的气体压力(单位为0.1KPa)
VUINT16 data gnLeakGet=0; // 测得的气体流量(单位为0.1L/min)
VUINT16 data gnPressOut=0; // 输出到比例控制阀的压力信号值(单位为0.1KPa)
VUINT16 data gnCurrTime=0; // 代表当前操作正在进行的时间
VUINT16 data gnFillTime; // 用户设定的充气时间
VUINT16 data gnTestTime; // 用户设定的测试时间
VUINT16 data gnPressSet; // 用户设定的气体压力(单位为0.1KPa)
VUINT16 data gnPressMax; // 用户设定的允许最大气体压力(单位为0.1KPa)
VUINT16 data gnPressMin; // 用户设定的允许最小气体压力(单位为0.1KPa)
VUINT16 data gnLeakMax; // 用户设定的允许最大气体流量(单位为0.1L/min)
VUINT16 data gnLeakMin; // 用户设定的允许最小气体流量(单位为0.1L/min)
VUINT16 xdata gnLeakArea[GROUPS_OF_COEFS]; // 用户设定的10组分段修正流量最大值(单位为0.1L/min),实际只使用了3组
VUINT16 xdata gnLeakCoef[GROUPS_OF_COEFS]; // 用户设定的10组分段修正流量系数,实际只使用了3组
/* 定义双字变量 */
VUINT32 data gnADC0Res=0; // ADC0的转换结果存储器定义及初始化
/************************************************
** 不带小数点的字符的LED段选码(共阳LED,段输出低
** 电平有效) 。在LED数码管上显示的数值直接参与计
** 算或保存到24C02中,或从24C02中读取到内存中,但
** 在送LED显示前,需将这些数值编码为可被LED正确识
** 别的代码,可以直接编码,也可从SEG_CODE[]数组中
** 选取对应的数字或符号编码。
************************************************/
UINT8 code SEG_CODE[] =
{
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90, /* 0..9 */
0x88,0x83,0xC6,0xA1,0x86,0x8E, /* A..F */
0xFF,0x89,0x8B,0xCF,0xC7,0xAB,0xA3,0x8C,0x98,0xAF, /* ..r */
0x92,0x87,0xE3,0x91,0xBF /* S..- */
};
/************************************************
** 不进行闪烁的LED位选码(共阳LED,位输出反相,低
** 电平有效)。扫描时,从低到高顺序进行。
************************************************/
//UINT8 code SCAN_CODE[] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
UINT8 code SCAN_CODE[] = {0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE};
/************************************************
** 固定显示的字符数组的LED段选码在SEG_CODE数组中
** 的索引(共阳LED,段输出低电平有效)。为与实际的
** LED排序相一致,字符索引按反序排列。
************************************************/
UINT8 code FIX_CODE[][5] =
{
{0x14,0x14,0x13,0x0F,0x1E}, // ID:0, -FiLL,即-FILL
{0x1B,0x1A,0x0E,0x1B,0x1E}, // ID:1, -tESt,即-TEST
{0x1B,0x1A,0x19,0x17,0x1E}, // ID:2, -PrSt,即-PRST
{0x17,0x1C,0x19,0x17,0x1E}, // ID:3, -PruP,即-PRUP
{0x15,0x0D,0x19,0x17,0x1E}, // ID:4, -Prdn,即-PRDN
{0x17,0x1C,0x0E,0x14,0x1E}, // ID:5, -LEuP,即-LEUP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -