📄 main.c
字号:
{
if (RI0)
{
RI0 = FALSE; // 清除接收中断标志,允许下次接收数据
if (gbRxdOK0) // 如果主程序还没有处理完数据,则不接收当前帧数据
return;
if (gbSyncTwoOK0) // 检查同步字节是否接收完毕
{
if (SBUF0 == 0x7F) // 同步字节已接收完毕,但仍接收到了0x7F,说明出现了最糟糕
return; // 的情况,即有3个0x7F,因此需将该字节舍弃。
gnRxdBuf0[gnRxdID0++] = SBUF0;
if (gnRxdID0 == 2) // 检查字节是否接收完毕,接收完则为下次接收做好准备
{
SetRxd0OK(); // 重新初始化同步字节检测标志和串口接收缓冲区索引
if (gbStarted && gbTestOver) // 当测试进程结束,且用户尚未按下停止键时,不更新流量显示值
return;
gbRxdOK0 = TRUE; // 数据接收完毕,通知主程序可以处理数据了
}
}
else // 同步字节还未接收完毕,继续检测
{
if (SBUF0 == 0x7F) // 如果是同步字节,则设置相应的同步字节接收到标志
{
if (gbSyncOneOK0)
gbSyncTwoOK0 = TRUE;
else
gbSyncOneOK0 = TRUE;
}
else // 接收到的字节既非同步字节又非正常的测量数据,舍弃重来。
SetRxd0OK(); // 重新初始化同步字节检测标志和串口接收缓冲区索引
}
}
else
TI0 = FALSE; // 清除发送中断标志,允许下次发送数据
}
/********************************************************************************************************
** 函数名称: TIMER2_ISR
** 功能描述: TIMER2定时中断服务程序(2ms定时)。
** 输 入: 无
** 输 出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块: 无
** 其它说明:
** 设 计 者:罗 建 日 期:2008年02月16日
** 版 本:V1.00,原始版本
** 修 改 者:罗 建 日 期:2008年03月17日
** 版 本:V1.01,将原来gnScanID>=6的代码作了调整,使得6个LED是连续扫描的。
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void TIMER2_ISR (void) interrupt INT_TIMER2
{
UINT8 i;
TF2 = FALSE; // 清除TIMER2定时中断标志
if (gnScanID > 5) // 6个LED是否扫描完?
{
gnScanID = 0; // 准备从头开始扫描
EA = FALSE; // 暂时禁止CPU响应中断
if (!gbBufUsed)
{
for (i=0;i<4;i++)
{
gnDisBuf[0][i] = gnSegBuf[0][i];
gnDisBuf[1][i] = gnSegBuf[1][i];
}
// 参数设置或流量系数设置时不允许消隐无效0(因要允许用户修改参数)
if ((gnWorkState != wsParamSet) && (gnWorkState != wsCoefSet) && gbLogoOver)
{
for (i=3;i>1;i--)
{
if (gnSegBuf[0][i] == 0)
gnDisBuf[0][i] = NONE;
else if (gnSegBuf[0][i] != NONE)
break;
}
for (i=3;i>1;i--)
{
if (gnSegBuf[1][i] == 0)
gnDisBuf[1][i] = NONE;
else if (gnSegBuf[1][i] != NONE)
break;
}
}
}
if (!gbLogoOver) // 正在显示LOGO字符
{
gnDisBuf[0][5] = NONE;
gnDisBuf[0][4] = 0x19;
gnDisBuf[1][5] = 0x0A;
#if METER_RANGE == A150CN
gnDisBuf[1][4] = 0x01;
#else
gnDisBuf[1][4] = 0x02;
#endif
}
else // 显示数据或参数
{
gnDisBuf[0][5] = gnGroupID; // 左边第6位LED显示分组号
gnDisBuf[1][5] = gnWorkState; // 右边第6位LED显示工作状态字符(D,P,F,t,r)
}
EA = TRUE; // 重新开中断
}
DoneDisplay(); // 显示当前扫描到的LED数码管及指示灯
GetKey(); // 读取按键
gnScanID++; // 准备扫描下一个按键和LED
// 实现100ms定时
gnCnt2ms++;
if (gnCnt2ms >= 50) // 定时100ms
{
gb100msOver = TRUE;
gnCnt2ms = 0;
}
}
/********************************************************************************************************
** 函数名称: SMBUS_ISR
** 功能描述: SMBUS接收中断服务程序。
** 输 入: 无
** 输 出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块: 无
** 其它说明:
** 设 计 者:罗 建 日 期:2008年01月29日
** 版 本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void SMBUS_ISR (void) interrupt INT_I2C
{
switch (SMB0STA) // 根据中断状态码跳转,SMB0STA 是中断状态寄存器
{
case SMB_START: // 0x08, (MT & MR) 起始条件已发出,将(从地址+R/W)装入到SMB0DAT,并清零STA
SMB0DAT = gnSlaAddrW ; // 装入被访问的从芯片的写地址
STA = CLR_BIT; // 人工清除 STA 位
break;
case SMB_RP_START: // 0x10,(MT & MR) 重复起始条件已发出,将(从地址+R/W)装入到SMB0DAT,并清零STA
SMB0DAT = gnSlaAddrR; // 装入被访问的从芯片的读地址
STA = CLR_BIT; // 人工清除 STA 位
break;
case SMB_MTADDACK: // 0x18,(MT) (从地址+W)已发出,收到ACK,将要发送的数据装入SMB0DAT
SMB0DAT = gnMemAddr;
break;
case SMB_MTADDNACK: // 0x20,(MT) (从地址+W)已发出,收到NACK,确认查询重试,置位STO+STA
STO = SET_BIT;
STA = SET_BIT;
break;
case SMB_MTDBACK: // 0x28,(MT) 数据字节已发出,收到ACK,将下一字节装入到SMB0DAT,或置位STO,或置位STO然后置位STA以重复起始条件
switch (gnSendMode)
{
case 0:
gnSendNums--;
if (gnSendNums)
SMB0DAT = gnMemData;
else
{
STO=1;
SM_BUSY=0;
}
break;
case 1:
STO = 0;
STA = 1;
break;
default:
STO = 1;
SM_BUSY = 0;
break;
}
break;
case SMB_MTDBNACK: // 0x30,(MT) 数据字节已发出,收到NACK,重试传输或置位STO
STO = SET_BIT;
STA = SET_BIT;
break;
case SMB_MRADDACK: // 0x40,(MR) (从地址+R)已发出,收到ACK,如果只收到一个字节,清AA位(收到字节后发NACK),等待接收数据
AA = CLR_BIT;
break;
case SMB_MRADDNACK: // 0x48,(MR) (从地址+R)已发出,收到NACK,确认查询重试,置位STO+STA
STO = CLR_BIT;
STA = SET_BIT;
break;
case SMB_MRDBNACK: // 0x58,(MR) 收到数据字节,NACK已发出,读操作已完成,读数据寄存器后发送停止条件
gnMemData = SMB0DAT;
STO = SET_BIT;
SM_BUSY = CLR_BIT;
AA = SET_BIT;
break;
default: // 在本应用中,所有其它状态码均没有意义,通信复位
STO = SET_BIT;
SM_BUSY = CLR_BIT;
break;
}
SI = CLR_BIT; // 清除中断标志
}
// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** 函数名称: 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -