Beruflich Dokumente
Kultur Dokumente
Example code
Review all since exam 1
Due MONDAY 9/28/2015
Sign-off Bonus Today (by 5 pm)
Report due 9/29 --> In class
Using ADC12 Interrupts ->> Examples so far have used software setting of ADC12SC bit to start conversion and
then we've been polling ADC12BUSY bit to see when conversion is complete
//Enable and start (single) conversion
ADC12CTL0 |= ADC12SC + ADC12ENC;
// Poll busy bit waiting for conversion to complete
while (ADC12CTL1 & ADC12BUSY)
__no_operation();
>> This, like the swDelay() function is demo.c, is example of Busy Waiting
>> The main purpose of on-chip peripherals like the Timer and ADC is to remove
burdens from and provide services to the CPU
--> Having the CPU wait in a polling loop for a peripheral to complete is
something like the having the Queen waiting on the maid!
>>Interrupts=ExternalsignalsrequestingCPUaction
>>RequestareinitiatedoutsideofCPUandtendtooccurasynchronously
>>CanbeacceptedandservicedbyappropriateInterruptServiceRoutine(ISR)
NonMaskableInterrupts(NMI)=Cannotbedisabled
Mustbeserviced(highestpriorities)
Maskableinterruptscanbedisabled
Mustbeindividuallyenabledinordertoberecognizedand
serviced
>>ISRarelikefunctions(labeledsubblocksofcodethatexecuteandreturn)
>> Sources of interrupts are HARDWIRED in the MSP430
--> Only certain devices can generate interrupts
--> Interrupts have a fixed priority ranking that is SET during processor design
>> Fixed Addresses (and names in msp430f5529.h) are associated with each interrupt
source
--> INTERRUPT VECTOR TABLE Resides in Highest Addresses of FLASH
Interruptsareanexampleofdoubleindirection
>>InhighlevellanguageslikeCthisisequivalenttoapointertoapointer
>>TheCPUknowswhatINTERRUPTVECTORaddressbetween0xFF80and
0xFFFEisassociatedwitheachinterruptsource(seetableabove)
>>IntheMSP430,whenaninterruptisreceivedfromaparticularsource(and
interruptsareenabled)theCPUgetstheaddressoftheInterruptService
Routine(ISR)storedintheInterruptVectortableautomaticallyandgoestotheISR
>>Butfirst,thecompilermustplaceaddressofISRinInterruptVectorTable!
--> You do not HAVE to re-enable interrupts and should do so only when
necessary!
-- There's a reason that the default behavior is to disable them
>> Servicing ANY interrupt automatically places address and data information on the
Stack
--> The Stack is an area of RAM used for temporary storage by the CPU during
program execution
--> The Stack has a fixed size!
--> Having multiple layers of nested ISRs aside from being exceedingly difficult
to debug may cause stack overrun which is usually fatal to programs
//Start conversion
. . .
// Else where in the code define ISR
#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR(void)
{
// Interrupt is generated when conversion (or last
// conversion if multi-channel) is complete so just
// read the results
adc_inTemp = ADC12MEM1;
// Move results to global
// variable adc_inTemp
}
TA2CCTL0 = CCIE;
// Start conversion
Your main() might look like this -- Assuming ADC12 measurements are being initiated
in TimerA2 ISR and ADC12 interrupts are enabled ...
void main()
{
// variable declarations
. . .
// stop watch dog
. . .
// do other initializations
_BIS_SR(GIE);
adc12_config();
run_timerA2();
. . .
while (1)
{
. . .
if (timer == displayTime)
{
display_current_ADC_readings();
timer = 0;
. . .
}
. . .
}
}