?? scanner.c
字號:
//********************采集機程序**************************************
//name: scanner.c
//******************************************************************************
//輸出管腳說明:
// P3.6 tx_en 當開始發(fā)送一幀時使能,當一幀發(fā)送完畢后禁止。軟件上,在SendByte子函使能,在發(fā)送中斷$的處理部分進行
//******************************************************************************
#include <msp430x13x.h>
#include "scanner.h"
void main(void)
{
unsigned int k=0;
unsigned int i=0;
unsigned char tmp,tmp1;
P4OUT = 0X00;
P4DIR = 0XFF; //強制輸出低電平,防止繼電器閉合
P5OUT = 0X00;
P5DIR = 0XFF;
//上電后給運放一個輸入,防止輸出過高。
P1DIR = 0XFF;
P2DIR = 0X0F;
P3DIR = 0xDB; // P3.5,P3.2為輸入
P1OUT = 0X00;
P2OUT = 0X00;
P3OUT = 0X18; //同時禁止發(fā)送,防止個別沒有復位的單板拉死總線,防止繼電器閉合,點燈
WDTCTL = WDTPW + WDTCNTCL; //clear wdt WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
for(i=0;i<10;i++)
{
P3OUT ^= 0x02;
DelayAMoment();
}
//-----系統(tǒng)基礎時鐘初始化--------
//從內部振蕩器切換到外部8M的晶振,切換不成功時靠硬件狗復位
BCSCTL1 &= ~XT2OFF;
do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (i = 0xFF; i > 0; i--); // Time for flag to set
} while ((IFG1 & OFIFG) == OFIFG); // OSCFault flag still set?
BCSCTL2|= SELM1 + SELS; //選擇外部晶振,MCLK=8Mhz SMCLK=8Mh
//------初始化TimerA--------------
//該定時器用于在自檢中的超時定時,保證自檢中某些操作在硬件不正常時能夠超時返回
TACTL = TASSEL1 + TACLR +ID0+ID1; // SMCLK, 8DIV =1M;clear TAR, UP TO CCR0 MODE
//
CCTL0 = CCIE; // CCR0 interrupt enabled
CCR0 = 50000; // 50ms 中斷一次
TACTL |= MC0; // Start Timer_A in up mode
//-----系統(tǒng)自檢,覆蓋到大部分硬件的可用性-------------
// if(SelfTest()== 0) //系統(tǒng)自檢測試
// SelfTest();
//------系統(tǒng)軟硬件資源初始化---------------
InitSys(); //初始化系統(tǒng)硬件資源和軟件資源
//------讀取本板ID號,若沒有則置為00------
ptrFlashData = (char *)IDADDRESS;
if((*ptrFlashData) == 0x55)
{
ptrFlashData--;
m_IDL = *ptrFlashData;
ptrFlashData--;
m_IDH = *ptrFlashData;
}
else
{
m_IDH = 00;
m_IDL =0x0;
}
//
WDTCTL = WDTPW + WDTCNTCL; //clear wdt
//------主循環(huán)----------
for (;;) //主循環(huán)
{
//這部分代碼的作用是,對18路電池電壓分別采集1024次,取均值,
//假設一次AD轉換需要15us,則大約需要15*18*1024=276ms完成一次掃描。計工頻周期,干擾很小
//*****************************************************************
if(ScanInitRes)
{
ScanInitRes = FALSE; //清楚初始化采集請求
//bypass 發(fā)送的命令采集:m_ResID = 0x99;
//bypass 處于bypass采集狀態(tài):scanres = 1, m_resid =0, m_residbuf = 0x99;
//其他發(fā)送的采集命令:m_ResID!=0x99
//處于其他發(fā)送的采集狀態(tài):scanres =1,m_resid=0,m_residbuf!=0x99
//現(xiàn)在暫時不區(qū)分采集狀態(tài),僅判斷采集命令的發(fā)出者和目的,設定一個低優(yōu)先級,m_ResID=0x99,其他
// 優(yōu)先級的采集命令都可以中斷當前的采集任務,處于主動采集的查詢狀態(tài)時,m_residBuf = 0x88,這一點暫僅用于上傳數(shù)據響應中。
if(ScanRes&&(m_ResID==0x99)) //當bypass功能發(fā)送采集請求,但已經處于采集狀態(tài)時
{
//已經清除采集請求,直接退出
}
else if(OwnScanReady) //若有主動采集的數(shù)據時,等待一秒再開始下一次采集
{
if(OwnScanReady == 0x55)
{
OwnScanReady = FALSE;
}
else
{
OwnScanReady = 0x55;
}
}
else
{
if(ScanRes&&(m_ResID!=0x99)) //當是其他模塊發(fā)送的采集請求,但此時已經采集狀態(tài)時
{
while(!(ADC12IFG & ADC12BUSY)); //等待轉換完成后,不理睬數(shù)據,直接重新置變量
// ADC12CTL0 &= &ENC; //停止當前的采集,丟棄數(shù)據
}
//上述語句中不甚嚴謹,應再判斷是否是bypass的狀態(tài),若不是則不應中斷,但當前考慮不會有此情況,故以下語句也先省略
// if(m_ResID==0x99)
// {
// m_ResIDbuf = 0x99; //當是bypass發(fā)送的采集請求時,將Buf也置為99,標志進入bypas采集狀態(tài)
// }
m_ResID = 0x00; //將m_ResID置0
// ta =0; //使時鐘同步,這樣單板看起來比較整齊,步調一致
k = 0;
ChAdder = 0;
// m_TotalChannelCur = 0; //通道電壓之和
ChNum = 0;
ADC12CTL0 |= ENC; // Enable conversions
ScanRes = TRUE; //要求進行一次電池電壓采集
ptrFlashData = (char *)P1DATAADDRESS; //存儲P1OUTDATA的地址
P1OUT = *ptrFlashData; //P1OUTDATA[0]; //設置4051通道
ptrFlashData = (char *)P2DATAADDRESS+ChNum; //存儲p2outdata的地址
P2OUT = *ptrFlashData;
//讀取CH1的采集增益
ChTimes = DEFAULTTIMES; //讀取設定的增益
if(ReadPara(2))
{
ChTimes = FlashPara;
}
ptrFlashData +=35; //指向本通道的零點存儲位置;
tmp = *ptrFlashData; //times的值放在FLASH中,地址從TIMESADDRESS開始
ptrFlashData++;
tmp1 = *ptrFlashData;
if((tmp == 0xff) &&(tmp1 == 0xff)) //當無效時
{
ChZero = 0x00; //DEFAULTTIMES; //默認值
}
else
{
ChZero = (unsigned int)(tmp&0x0f)*100+tmp1;
if(tmp&0xe0) //若高位為1,則為負數(shù),這是自定義的負數(shù)格式,盡量遵守了常用方法
{
ChZero = -ChZero;
}
ChZero = ChZero*100; //對于2048次的和,此值需要放大100倍,否則沒有效果
}
ADC12CTL0 |= ADC12SC; // Start conversion
for(tmp=0;tmp<18;tmp++) //保存上一次采集到的電壓值
{
m_ChannelHis2[tmp] = m_ChannelCur[tmp];
}
}
}
//**************************
if(k>4000)k = 1; //此處限定K值不大于4000,大于4000可能造成異常。
if(ScanRes == TRUE&&((ADC12IFG & ADC12BUSY)== 1)) //當使能了一次采集 且轉換已經完成后
{
if(k<= ChTimes) //當尚未達到本通道采集數(shù)目時
{
ChAdder += ADC12MEM0; //累加 CHNUM 從0~17對應第1~18通道
ADC12CTL0 |= ADC12SC; // Start conversion ,同時啟動采樣,
k++;
}
else
{
ChAdder = ChAdder+ChZero; //調整零點
ChAdder += 512; //四舍五入
ChAdder = ChAdder/1024; //為了僅使用兩字節(jié)通訊,犧牲了部分精度,最完美的做法是將1024次采集的結果全部讀出
if(ChAdder>0xfe00){ChAdder = 0;}; //當無電壓輸入時,消除負零點電壓的影響
m_ChannelCur[ChNum] = ChAdder;
// m_TotalChannelCur += ChAdder; //計算總電壓,當前僅有主動采集功能使用,但我認為會有其他功能使用,故放在此處
ChNum++; //采集下一個通道
k = 0;
if(ChNum < 18)
{
ptrFlashData = (char *)P1DATAADDRESS+ChNum; //存儲P1OUTDATA的地址
P1OUT = *ptrFlashData; //P1OUTDATA[0]; //設置4051通道
ptrFlashData = (char *)P2DATAADDRESS+ChNum; //存儲p2outdata的地址
P2OUT = *ptrFlashData;
ChTimes = DEFAULTTIMES; //讀取設定的增益
if(ReadPara(2*(ChNum+1)))
{
ChTimes = FlashPara;
}
ptrFlashData +=35; //指向本通道的零點存儲位置;
tmp = *ptrFlashData; //times的值放在FLASH中,地址從TIMESADDRESS開始
ptrFlashData++;
tmp1 = *ptrFlashData;
if((tmp == 0xff) &&(tmp1 == 0xff)) //當無效時
{
ChZero = 0x00; //DEFAULTTIMES; //默認值
}
else
{
ChZero = (unsigned int)(tmp&0x0f)*100+tmp1;
if(tmp&0xe0) //若高位為1,則為負數(shù),這是自定義的負數(shù)格式,盡量遵守了常用方法
{
ChZero = -ChZero;
}
ChZero = ChZero*100;
}
//debug03041
P3OUT ^= 0x02;
Delay1ms(); //用于避免通道間的干擾,使4051的輸出可靠建立
ADC12CTL0 |= ADC12SC; // Start conversion
}
else //當完成全部18個通道的采集時
{
ScanRes = FALSE;
ADC12CTL0 &= ~ENC; // Disable conversions
m_ResID = m_ResIDbuf; //刷新命令ID,以使上位機確認是最新的數(shù)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -