📄 msp430adc12m.nc
字号:
/* * Copyright (c) 2004, Technische Universitaet Berlin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name of the Technische Universitaet Berlin nor the names * of its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * - Revision ------------------------------------------------------------- * $Revision: 1.18 $ * $Date: 2005/10/26 19:47:42 $ * @author: Jan Hauer <hauer@tkn.tu-berlin.de> * ======================================================================== */includes MSP430ADC12;module MSP430ADC12M { provides { interface StdControl; interface MSP430ADC12Single as ADCSingle[uint8_t id]; interface MSP430ADC12Multiple as ADCMultiple[uint8_t id]; } uses { interface HPLADC12; interface RefVolt; interface MSP430Timer as TimerA; interface MSP430TimerControl as ControlA0; interface MSP430TimerControl as ControlA1; interface MSP430Compare as CompareA0; interface MSP430Compare as CompareA1; }}implementation{ #define CHECKARGS 1 norace uint8_t cmode; /* current conversion mode */ norace uint16_t *bufPtr; /* result buffer */ norace uint16_t bufLength; /* length of buffer */ norace uint16_t bufOffset; /* offset into buffer */ norace uint8_t owner; /* interface instance for current conversion */ norace uint8_t reserved; /* reserve() called successfully */ norace uint8_t vrefWait; /* waiting for voltage generator to become stable */ norace adc12settings_t adc12settings[uniqueCount("MSP430ADC12")]; /* bind settings */ command result_t StdControl.init() { cmode = ADC_IDLE; reserved = ADC_IDLE; vrefWait = FALSE; call HPLADC12.disableConversion(); call HPLADC12.setIEFlags(0x0000); return SUCCESS; } command result_t StdControl.start() { return SUCCESS; } command result_t StdControl.stop() { call HPLADC12.disableConversion(); call HPLADC12.setIEFlags(0x0000); return SUCCESS; } void configureAdcPin( uint8_t inputChannel ) { if( inputChannel <= 7 ){ P6SEL |= (1 << inputChannel); //adc function (instead of general IO) P6DIR &= ~(1 << inputChannel); //input (instead of output) } } command result_t ADCSingle.bind[uint8_t num](MSP430ADC12Settings_t settings) { result_t res = FAIL; adc12memctl_t memctl = { inch: settings.inputChannel, sref: settings.referenceVoltage, eos: 0 }; #if CHECKARGS if (num >= uniqueCount("MSP430ADC12")) return FAIL; #endif atomic { if (cmode == ADC_IDLE || owner != num){ configureAdcPin( settings.inputChannel ); adc12settings[num].refVolt2_5 = settings.refVolt2_5; adc12settings[num].gotRefVolt = 0; adc12settings[num].clockSourceSHT = settings.clockSourceSHT; adc12settings[num].clockSourceSAMPCON = settings.clockSourceSAMPCON; adc12settings[num].clockDivSAMPCON = settings.clockDivSAMPCON; adc12settings[num].clockDivSHT = settings.clockDivSHT; adc12settings[num].sampleHoldTime = settings.sampleHoldTime; adc12settings[num].memctl = memctl; res = SUCCESS; } } return res; } command result_t ADCMultiple.bind[uint8_t num](MSP430ADC12Settings_t settings) { return (call ADCSingle.bind[num](settings)); } msp430ADCresult_t getRefVolt(uint8_t num) { msp430ADCresult_t adcResult = MSP430ADC12_SUCCESS; result_t vrefResult; adc12memctl_t memctl = adc12settings[num].memctl; if (memctl.sref == REFERENCE_VREFplus_AVss || memctl.sref == REFERENCE_VREFplus_VREFnegterm) { if(adc12settings[num].gotRefVolt == 0) { if (adc12settings[num].refVolt2_5) vrefResult = call RefVolt.get(REFERENCE_2_5V); else vrefResult = call RefVolt.get(REFERENCE_1_5V); } else vrefResult = SUCCESS; if (vrefResult != SUCCESS) { adcResult = MSP430ADC12_FAIL; } else { adc12settings[num].gotRefVolt = 1; if (call RefVolt.getState() == REFERENCE_UNSTABLE) adcResult = MSP430ADC12_DELAYED; } } return adcResult; } result_t releaseRefVolt(uint8_t num) { if (adc12settings[num].gotRefVolt == 1){ call RefVolt.release(); adc12settings[num].gotRefVolt = 0; return SUCCESS; } return FAIL; } void prepareTimerA(uint16_t interval, uint16_t csSAMPCON, uint16_t cdSAMPCON) { MSP430CompareControl_t ccResetSHI = { ccifg : 0, cov : 0, out : 0, cci : 0, ccie : 0, outmod : 0, cap : 0, clld : 0, scs : 0, ccis : 0, cm : 0 }; call TimerA.setMode(MSP430TIMER_STOP_MODE); call TimerA.clear(); call TimerA.disableEvents(); call TimerA.setClockSource(csSAMPCON); call TimerA.setInputDivider(cdSAMPCON); call ControlA0.setControl(ccResetSHI); call CompareA0.setEvent(interval-1); call CompareA1.setEvent((interval-1)/2); } void startTimerA() { MSP430CompareControl_t ccSetSHI = { ccifg : 0, cov : 0, out : 1, cci : 0, ccie : 0, outmod : 0, cap : 0, clld : 0, scs : 0, ccis : 0, cm : 0 }; MSP430CompareControl_t ccResetSHI = { ccifg : 0, cov : 0, out : 0, cci : 0, ccie : 0, outmod : 0, cap : 0, clld : 0, scs : 0, ccis : 0, cm : 0 }; MSP430CompareControl_t ccRSOutmod = { ccifg : 0, cov : 0, out : 0, cci : 0, ccie : 0, outmod : 7, cap : 0, clld : 0, scs : 0, ccis : 0, cm : 0 }; // manually trigger first conversion, then switch to Reset/set mode call ControlA1.setControl(ccResetSHI); call ControlA1.setControl(ccSetSHI); //call ControlA1.setControl(ccResetSHI); call ControlA1.setControl(ccRSOutmod); call TimerA.setMode(MSP430TIMER_UP_MODE); // go! } msp430ADCresult_t newRequest(uint8_t req, uint8_t num, void *dataDest, uint16_t length, uint16_t jiffies) { bool access = FALSE; msp430ADCresult_t res = MSP430ADC12_FAIL; // Workaround by Cory Sharp // since msp430 is a 16-bit platform, make num a signed // 16-bit integer to avoid "warning: comparison is always true due to // limited range of data type" if it happens that (num >= 0) is tested. const int16_t num16 = num; #if CHECKARGS if ( num16 >= uniqueCount("MSP430ADC12") || (!reserved && (!length || (req == REPEAT_SEQUENCE_OF_CHANNELS && length > 16)) ) ) return MSP430ADC12_FAIL; // since timerA is used in upmode with OUTMOD=7, i.e. reset/set, // jiffies cannot be 1 (otherwise reset and set is performed simultanously). // it cannot be 2 either - TAR rollover with TACCR1=0 // does reset OUT0 signal. But with timerA running at // 1MHz jiffies < 10 will probably (depending on ADC12CLK) not work // anyway because of too long sample-hold-time. if (jiffies == 1 || jiffies == 2) return MSP430ADC12_FAIL; #endif if (reserved & RESERVED) if (!(reserved & VREF_WAIT) && owner == num16 && cmode == req){ call HPLADC12.startConversion(); if (reserved & TIMER_USED) startTimerA(); // go! reserved = ADC_IDLE; return MSP430ADC12_SUCCESS; } else return MSP430ADC12_FAIL; atomic { if (cmode == ADC_IDLE){ owner = num16; cmode = SEQUENCE_OF_CHANNELS; access = TRUE; } } if (access){ res = MSP430ADC12_SUCCESS; switch (getRefVolt(num16)) { case MSP430ADC12_FAIL: cmode = ADC_IDLE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -