📄 main.#3
字号:
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 + -