📄 main14.c
字号:
P2MDOUT = 0x00; // (默认)
P3MDOUT = 0x80; // SPI_CS作为推挽方式
XBR0 = 0x1F; // 允许UART0、SPI、SMBus、PCA0_CEX0、PCA0_CEX1、PCA0_CEX2
XBR1 = 0x14; // 允许INT0_SCK、INT0_CS
XBR2 = 0x44; // 允许交叉开关和弱上位
// ADC和DAC(取默认值)转换初始化
AMX0CF = 0x00; // 配置AIN00-AIN07均为单端输入方式(默认)
AMX0SL = 0x00; // 选择AIN00通道进行AD转换(默认)
ADC0CF = 0x50; // ADC0转换时钟为2MHz,PGA增益为1
ADC0CN = 0x84; // 允许ADC0,正常跟踪模式,Timer3溢出启动ADC0转换,ADC0数据右对齐
DAC0 = 0x0000; // 默认DAC0输出为0
DAC1 = 0x0000; // 默认DAC1输出为0
DAC0CN = 0x80; // 允许DAC0输出,写DAC0H时DAC0更新输出,DAC0H3-0保存高4位,DAC0L7-0保存低8位(默认)
DAC1CN = 0x80; // 允许DAC1输出,写DAC1H时DAC1更新输出,DAC1H3-0保存高4位,DAC1L7-0保存低8位(默认)
// ADC和DAC参考电压初始化
REF0CN = 0x03; // ADC0电压基准取至VREF0,禁止温度传感器,内部偏压发生器和基准电压缓冲器打开
// 串口UART0和UART1初始化
SCON0 = 0x50; // UART0为8位可变波特率模式,允许接收
SCON1 = 0x50; // UART1为8位可变波特率模式,允许接收
// 定时器初始化
CKCON = 0x10; // TIMER1时钟源为SYSCLK,TIMER4、TIMER2、TIMER0时钟源为SYSCLK/12
TMOD = 0x21; // TIMER1为8位自动重装载模式,TIMER0为16位定时器方式
TH1 = 0xDC; // TIMER1作为UART0和UART1的波特率发生器,波特率均为19200bps
//TH1 = 0xEE; // For 11.0592MHz
TCON = 0x40; // 允许TIMER1定时
RCAP2H = 0xB8; // TIMER2自动重装载值(定时10ms,RCAP2L=0x00)
TH2 = 0xB8; // TIMER2计数寄存器初值(定时10ms,TL2=0x00)
//RCAP2H = 0xDC; // For 11.0592MHz
//TH2 = 0xDC; // For 11.0592MHz
T2CON = 0x04; // TIMER2作为10ms定时器,16位自动重装载模式,允许定时
TMR3RLL = 0x9A; // TIMER3自动重装载值(定时1ms)
TMR3RLH = 0xA9;
TMR3L = 0x9A; // TIMER3计数寄存器初值(定时1ms)
TMR3H = 0xA9;
TMR3CN = 0x06; // TIMER3作为1ms定时器,控制ADC,使用SYSCLK,允许定时
// 中断初始化
EIE2 = 0x42; // 允许UART1和ADC0中断
IE = 0xB0; // 允许TIMER2、UART0中断,开总中断
}
// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** 函数名称: SysInit
** 功能描述: ADC0转换结束中断服务程序。
** 输 入: 无
** 输 出: 无
** 全局变量: 略
** 全局常量:略
** 调用模块:略
** 设 计 者:罗建 日 期:2007年12月09日
** 版 本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void SysInit(void)
{
gbCanGetKey = TRUE;
gnTxdBuf0[0] = 0xFF;
gnTxdBuf0[1] = 0xFF;
gnCntAdjust = ADJUST_WAIT;
}
// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** 函数名称: 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
** 式中,P为待测压力,单位为0.1KPa,D为ADC0测得的对于输入电压的数字量。如果P<0,则应将其置0。
**
** 设 计 者:罗建 日 期:2007年12月09日
** 版 本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void ADC0_ISR(void) interrupt INT_ADC0
{
static INT8U nADC0Cnt=ADC0_SAMPLE_NUMS; // ADC0采样次数计数器定义及初始化
INT32U nPress;
AD0INT = FALSE; // 清除ADC0转换结束标志
gnADC0Res += ADC0; // 累加ADC0转换结果并取平均
gnADC0Res /= 2;
nADC0Cnt--; // ADC0连续转换ADC0_SAMPLE_NUMS次,完成后暂停转换(不响应中断)
if (nADC0Cnt == 0) // 同时将结果转换为工程量值(气体压力)
{
nADC0Cnt = ADC0_SAMPLE_NUMS;
AD0EN = FALSE;
nPress = gnADC0Res; // 转换为32位无符号数
nPress = nPress*VREF0*25/32768; // 进行工程量转换,如果值小于0,则认为是0
if (nPress <= 1250)
gnPressGet = 0;
else
gnPressGet = nPress - 1250;
}
}
/********************************************************************************************************
** 函数名称: UART0_ISR
** 功能描述: 串行口UART0中断服务程序。
** 输 入: 无
** 输 出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块:无
** 设 计 者:罗建 日 期:2007年12月09日
** 版 本:V1.00,原始版本
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_ISR(void) interrupt INT_UART0
{
if (RI0) // 数据接收中断
{
RI0 = FALSE; // 清除数据接收中断标志
if (gbSyncTwoOK0) // 检查同步字节是否接收完毕
{
if (SBUF0 == 0xFF) // 同步字节已接收完毕,但仍接收到了0xFF,说明出现了最糟糕
return; // 的情况,即有3个0xFF,因此需将该字节舍弃。
gnRxdBuf0[gnRxdID0++] = SBUF0;
if (gnRxdID0 >= 2) // 检查命令字节是否接收完毕,接收完则根据命令决定要接收的数据个数
{
switch (gnRxdBuf0[1])
{
case 0x01: // 发送测量数据及开关状态至触摸屏命令(0xFF,0xFF,0x00,0x01,共4个字节)
SetRxd0OK(); // 重新初始化同步字节检测标志及串口接收缓冲区索引
gnTxdBuf0[0] = 0xFF;
gnTxdBuf0[1] = 0xFF;
gnTxdBuf0[2] = 0x01; // 准备发送命令的低8位字节
gnTxdBuf0[3] = 0x00; // 准备发送命令的高8位字节
gnTxdBuf0[4] = gnPressGet % 256;// 准备发送测试压力的低8位字节
gnTxdBuf0[5] = gnPressGet / 256;// 准备发送测试压力的高8位字节
gnTxdBuf0[6] = gnLeakGet % 256; // 准备发送气体流量的低8位字节
gnTxdBuf0[7] = gnLeakGet / 256; // 准备发送气体流量的高8位字节
gnTxdID0 = 0;
gnTxdNums0 = 7; // 指示要向触摸屏发送的数据个数为8个(含帧头,因下面将先发送一个字节,故为7)
SBUF0 = gnTxdBuf0[0]; // 开始发送数据至触摸屏
break;
case 0x02: // 接收设定参数及系数命令(0xFF,0xFF,0x00,0x02,Data,共44个字节,数据按先低后高的顺序发送)
if (gnRxdID0 == 42) // 检查数据是否接收完毕(包括两个命令字节)
{
gnPressSet = gnRxdBuf0[3]*256 + gnRxdBuf0[2]; // 预设测试压力值(单位:0.1KPa)
gnPressMax = gnRxdBuf0[5]*256 + gnRxdBuf0[4]; // 允许的最高压力值(单位:0.1KPa)
gnPressMin = gnRxdBuf0[7]*256 + gnRxdBuf0[6]; // 允许的最低压力值(单位:0.1KPa)
gnLeakMax = gnRxdBuf0[9]*256 + gnRxdBuf0[8]; // 允许的最高流量值(单位:0.01L/min)
gnLeakMin = gnRxdBuf0[11]*256 + gnRxdBuf0[10]; // 允许的最低流量值(单位:0.01L/min)
gnFillTime = gnRxdBuf0[13]*256 + gnRxdBuf0[12]; // 充气时间(单位:0.1S)
gnTestTime = gnRxdBuf0[15]*256 + gnRxdBuf0[14]; // 测试时间(单位:0.1S)
// 由于流量测量的最小值为0,因此其下限始终为0,尽管触摸屏传了值(即gnRxdBuf0[17]*256 + gnRxdBuf0[16]),
// 但该值始终为0,因此这里并不读取它
gnLeakAreaMax[0] = gnRxdBuf0[19]*256 + gnRxdBuf0[18]; // 流量校线阶段1对应的最大流量
gnLeakAreaCoef[0] = gnRxdBuf0[21]*256 + gnRxdBuf0[20]; // 流量校线阶段1对应的流量修正系数
gnLeakAreaMax[1] = gnRxdBuf0[23]*256 + gnRxdBuf0[22]; // 流量校线阶段2对应的最大流量
gnLeakAreaCoef[1] = gnRxdBuf0[25]*256 + gnRxdBuf0[24]; // 流量校线阶段2对应的流量修正系数
gnLeakAreaMax[2] = gnRxdBuf0[27]*256 + gnRxdBuf0[26]; // 流量校线阶段3对应的最大流量
gnLeakAreaCoef[2] = gnRxdBuf0[29]*256 + gnRxdBuf0[28]; // 流量校线阶段3对应的流量修正系数
gnLeakAreaMax[3] = gnRxdBuf0[31]*256 + gnRxdBuf0[30]; // 流量校线阶段4对应的最大流量
gnLeakAreaCoef[3] = gnRxdBuf0[33]*256 + gnRxdBuf0[32]; // 流量校线阶段4应的流量修正系数
gnLeakAreaMax[4] = gnRxdBuf0[35]*256 + gnRxdBuf0[34]; // 流量校线阶段5对应的最大流量
gnLeakAreaCoef[4] = gnRxdBuf0[37]*256 + gnRxdBuf0[36]; // 流量校线阶段5对应的流量修正系数
gnLeakAreaMax[5] = gnRxdBuf0[39]*256 + gnRxdBuf0[38]; // 流量校线阶段6对应的最大流量
gnLeakAreaCoef[5] = gnRxdBuf0[41]*256 + gnRxdBuf0[40]; // 流量校线阶段6对应的流量修正系数
SetRxd0OK(); // 重新初始化同步字节检测标志及串口接收缓冲区索引
}
break;
}
}
}
else // 同步字节还未接收完毕,继续检测
{
if (SBUF0 == 0xFF) // 如果是同步字节,则设置相应的同步字节接收到标志
{
if (gbSyncOneOK0)
gbSyncTwoOK0 = TRUE;
else
gbSyncOneOK0 = TRUE;
}
else // 接收到的字节既非同步字节又非正常的测量数据,舍弃重来。
SetRxd0OK(); // 重新初始化同步字节检测标志及串口接收缓冲区索引
}
}
else // 数据发送中断
{
TI0 = FALSE; // 清除数据发送中断标志
if (gnTxdID0 < gnTxdNums0) // 将发送缓冲区中的gnTxdNums0个数据发送至触摸屏
{
gnTxdID0++;
SBUF0 = gnTxdBuf0[gnTxdID0];
}
}
}
/********************************************************************************************************
** 函数名称: UART1_ISR
** 功能描述: 串行口UART1中断(仅处理数据接收中断)服务程序。
** 输 入: 无
** 输 出: 无
** 全局变量: 略
** 全局常量:无
** 调用模块: 无
** 其它说明: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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -