?? main.#1
字號:
XBR1 = 0x04;
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
TCON = 0x40; // 允許TIMER1定時
RCAP2H = 0xB8; // TIMER2自動重裝載值(定時10ms,RCAP2L=0x00)
TH2 = 0xB8; // TIMER2計數寄存器初值(定時10ms,TL2=0x00)
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轉換結果并取平均
nADC0Cnt--; // ADC0連續轉換ADC0_SAMPLE_NUMS次,完成后暫停轉換(不響應中斷)
if (nADC0Cnt == 0) // 同時將結果轉換為工程量值(氣體壓力)
{
nADC0Cnt = ADC0_SAMPLE_NUMS;
AD0EN = FALSE;
gnADC0Res = gnADC0Res/(ADC0_SAMPLE_NUMS+1);
nPress = gnADC0Res*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;
// 接收設定參數及系數命令(0xFF,0xFF,0x00,0x02,Data,共44個字節,數據按先低后高的順序發送)
if (gnRxdID0 >= 32) // 檢查數據是否接收完畢(包括兩個命令字節)
{
gnPressSet = gnRxdBuf0[1]*256 + gnRxdBuf0[0]; // 預設測試壓力值(單位:0.1KPa)
gnPressMax = gnRxdBuf0[3]*256 + gnRxdBuf0[2]; // 允許的最高壓力值(單位:0.1KPa)
gnPressMin = gnRxdBuf0[5]*256 + gnRxdBuf0[4]; // 允許的最低壓力值(單位:0.1KPa)
gnLeakMax = gnRxdBuf0[7]*256 + gnRxdBuf0[6]; // 允許的最高流量值(單位:0.01L/min)
gnFillTime = gnRxdBuf0[9]*256 + gnRxdBuf0[8]; // 充氣時間(單位:0.1S)
gnTestTime = gnRxdBuf0[11]*256 + gnRxdBuf0[10]; // 測試時間(單位:0.1S)
// 由于流量測量的最小值為0,因此其下限始終為0,盡管觸摸屏傳了值(即gnRxdBuf0[13]*256 + gnRxdBuf0[12]),
// 但該值始終為0,因此這里并不讀取它
gnLeakAreaMax[0] = gnRxdBuf0[15]*256 + gnRxdBuf0[14]; // 流量校線階段1對應的最大流量
gnLeakAreaCoef[0] = gnRxdBuf0[17]*256 + gnRxdBuf0[16]; // 流量校線階段1對應的流量修正系數
gnLeakAreaMax[1] = gnRxdBuf0[19]*256 + gnRxdBuf0[18]; // 流量校線階段2對應的最大流量
gnLeakAreaCoef[1] = gnRxdBuf0[21]*256 + gnRxdBuf0[20]; // 流量校線階段2對應的流量修正系數
gnLeakAreaMax[2] = gnRxdBuf0[23]*256 + gnRxdBuf0[22]; // 流量校線階段3對應的最大流量
gnLeakAreaCoef[2] = gnRxdBuf0[25]*256 + gnRxdBuf0[24]; // 流量校線階段3對應的流量修正系數
gnLeakAreaMax[3] = gnRxdBuf0[27]*256 + gnRxdBuf0[26]; // 流量校線階段4對應的最大流量
gnLeakAreaCoef[3] = gnRxdBuf0[29]*256 + gnRxdBuf0[28]; // 流量校線階段4應的流量修正系數
SetRxd0OK(); // 重新初始化同步字節檢測標志及串口接收緩沖區索引
gnTxdBuf0[0] = 0xFF; // 發送測量數據及開關狀態至觸摸屏命令(0xFF,0xFF,0x00,0x01,共4個字節)
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]; // 開始發送數據至觸摸屏
}
}
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:
** 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 UART1_ISR(void) interrupt INT_UART1
{
INT8U i;
INT32U nRes;
static INT8U nLeakCnt=LEAK_SAMPLE_NUMS; // ADC0采樣次數計數器定義及初始化
if (SCON1&0x01)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -