Input Capture. STMicroelectronics STM32 F1
જાહેરાત
જાહેરાત
CHAPTER 10. TIMERS
10.2 Input Capture
In generating PWM output signals we use the “compare” feature of the capture/compare register. In this section we discuss “capture”. The capture registers provide a mechanism to monitor an input pin and, based upon a programmed edge, capture the current value of the corresponding timer counter.
The main purpose of the capture registers is to enable measuring, relative to a time reference, when events happen. It is possible to tie multiple capture registers to a single input, capturing the times of both rising and falling edges, to measure pulse widths. It is possible to use input events to reset the timer counter, to use input values to enable a timer counter, and to synchronize multiple timers. In this section we will show how input capture can be used in conjunction with PWM output to control commonly available ultrasonic
ranging devices such as that illustrated in Figure 10.7.
Figure 10.7: Ultrasonic Sensor
The HC-SR04 ultrasonic ranging module is capable of 3mm resolution in the range 20-500mm. It requires a 5V supply. In operation, the module is triggered by delivering it a 10µs pulse. Some time later an “echo” pulse is generated whose length is proportional to the measured distance as illustrated
in Figure 10.8 and defined by the following formula where pw is the echo pulse.
distance = pw
∗ cm
58µs
If the distance is less than 20mm or greater than 500 mm, a 38ms pulse is returned. Internally, the ultrasonic controller circuit generates an 8 pulse 40 kHz signal which drives the transducer.
In the remainder of this section we will describe to use two timers – one for output and one for input to control such an ultrasonic ranger completely autonomously. Meaning that after setting up the timers, an application need
146
Revision: 1396a85 (2013-01-07)
10.2. INPUT CAPTURE
10µs
Trigger
150 − 2500µs
Echo
Figure 10.8: Ultrasonic Sensor Protocol only read a capture register to learn the most recent distance measurement.
With the addition of interrupts (see Chapter 11, it is possible to notify the
application whenever a new measurement is available. Here we use a continuous measurement process. Note that when using multiple ranger modules, it is advisable that they not be active continuously. With a small amount of external hardware and a few GPIO pins, it is possible to multiplex the timing hardware to control an arbitrary number of ranging modules with a just two timers.
As mentioned, we use two timers – one to generate the trigger pulse and one to measure the echo pulse. We discussed how to generate a pwm output
in Section 10.1 and now we leave it as an exercise to the reader to utilize timer
TIM4 and Pin PB9 to generate trigger pulses at a 10Hz rate.
To measure the echo pulse, we will use timer TIM1 connected to PA8.
The architecture of the various timers is quite complex. We exploit two key concepts:
1. Pairs of capture registers (1,2) and (3,4) can be “coupled” to enable capture at opposite edges of a single input.
2. Timer counters can be configured as slaves to capture inputs 1 and 2, for example, to reset the counter on a specified input event.
Revision: 1396a85 (2013-01-07)
147
CHAPTER 10. TIMERS
The details of setting up capture registers can be quite complex, in the
following, we refer to the simplified model illustrated in Figure 10.9. In this
figure two capture registers are illustrated along with the functional path from inputs (t1 and t2). The inputs are (optionally) filtered and signals generated on rising and falling edges. Any of the four edge signals can be selected and, after (optionally) dividing, used to trigger the capture event. Thus, capture register (channel) 1 or 2 can be loaded on rising or falling edges on either input t1 or t2. In addition two signals TI1FP1 and TI2FP2 can be used to control the timer counter, for example, causing it to be reset on the select input edge.
TI1FP1 t1 filter edge detector
TI1F Rising
TI1F Falling
÷ capture 1 t2 filter
÷ edge detector
TI2F Rising
TI2F Falling
Figure 10.9: Capture Circuit
TI2FP2 capture 2
To configure a TIM1 to measure the ultrasonic echo pulse we must do the following (in addition to pin and configuration and clock distribution !):
1. Configure TIM1 prescaler and period.
2. Configure channel 1 to latch the timer on a rising input on t1.
3. Configure channel 2 to latch the timer on a falling input on t2.
4. Configure TIM1 in slave mode to reset on the capture 1 event.
Task (1) is identical to that for the trigger generation; although you may wish to use a longer period. Configuration for channel 1 follows:
TIM_ICInitStructure . TIM_Channel = TIM_Channel_1 ;
TIM_ICInitStructure . TIM_ICPolarity = TIM_ICPolarity_Rising ;
148
Revision: 1396a85 (2013-01-07)
10.2. INPUT CAPTURE
TIM_ICInitStructure . TIM_ICSelection = TIM_ICSelection_DirectTI ;
TIM_ICInitStructure . TIM_ICPrescaler = 0;
TIM_ICInitStructure . TIM_ICFilter = 0;
TIM_ICInit (TIM1 , & TIM_ICInitStructure );
We require no filtering or prescaling (dividing) of the input signal. We want to capture on rising edges, using the T1 input. Configuring channel 2 has the following differences:
TIM_ICInitStructure . TIM_ICPolarity = TIM_ICPolarity_Falling ;
TIM_ICInitStructure . TIM_ICSelection = TIM_ICSelection_IndirectTI ; signal:
Finally we must configure the timer slave mode with TI1FP1 as reset
TIM_SelectInputTrigger (TIM1 , TIM_TS_TI1FP1 );
TIM_SelectSlaveMode (TIM1 , TIM_SlaveMode_Reset );
TIM_SelectMasterSlaveMode (TIM1 , TIM_MasterSlaveMode_Enable );
Exercise 10.3
Ultrasonic Sensor
Write an application which tracks, by printing over the USART, the distance, in centimeters, measured by an ultrasonic sensor every 100ms.
Revision: 1396a85 (2013-01-07)
149
Chapter 11
Interrupts
Interrupts are a fundamental hardware mechanism to enable peripherals to notify software of critical events.
For example, we may wish to generate an analog output signal at precise intervals in order to play an audio file. One way to achieve this is to configure a timer to generate interrupts at precise intervals. When the configured interrupt occurs, the processor switches execution from the application program to a special interrupt handler which can then “service” the interrupt event by transferring a data sample to the analog output. Once the interrupt handler has completed its task, the processor resumes execution of the application program. Interrupts are also important in communication – for example, notifying the processor when a character has arrived at a UART. In this chapter we discuss how interrupts work in the
STM32 (more generally in the Cortex-M3) micro-controller family and present several concrete examples to demonstrate their use.
We’ve actually been using interrupts throughout this book to implement
our delay function as illustrated by the code fragment in Listing 11.1. Within
main, we configure the Cortex-M3 “SysTick” to trigger an interrupt every milli-second. Furthermore, we define an interrupt handler,
SysTick_Handler, to be executed when the SysTick interrupt occurs. This handler decrements the variable TimingDelay and then returns control to the application program. The application program may wait for a precise period by calling the procedure Delay with an interval and then waiting for this interval to elapse (literally be counted down by the handler).
Interrupts may be triggered by many possible events including the sys-
1
Interrupts are a special case of exceptions, which may include internal events such as access violations.
Revision: 1396a85 (2013-01-07)
151
CHAPTER 11. INTERRUPTS main (){
...
if ( SysTick_Config ( SystemCoreClock / 1000)) while (1);
...
} static __IO uint32_t TimingDelay ; void Delay( uint32_t nTime){
TimingDelay = nTime;�� while ( TimingDelay != 0);
} void SysTick_Handler (void){ if ( TimingDelay != 0x00)
TimingDelay --;
}
Listing 11.1: SysTick Interrupt tem timer, memory access faults, external resets, and by all of the various peripherals provided on the STM32 processor. It is easiest to view each possible interrupt source as a separate signal that is monitored by the processor core during program execution. If the core detects a valid interrupt signal and is configured to accept interrupt requests, it reacts by saving the state of the currently executing program on the program stack and executing a handler
(sometimes called an interrupt service routine) corresponding to the accepted interrupt. When the handler terminates, the saved program state is restored and normal program execution is resumed.
The concept of interrupts, and more generally, exceptions can be relatively difficult to grasp. Recall that programs in a language such as C are compiled into assembly code (the symbolic representation of machine instructions) from which machine code is generated. In the STM32, this machine code is copied into flash memory when programming the device (we do this through gdb) and executed when the processor is reset. The basic execution model is: while (1){ inst = *pc ++; eval(inst);
}
152
Revision: 1396a85 (2013-01-07)
The processor can be viewed as a machine code interpreter which reads instructions from memory and evaluates them. The program counter, pc, holds the address of the next instruction to execute. Consider the following
’C’ statement from the SysTick handler:
TimingDelay --;
The compiler translates this statement into three assembly language steps which load (ldr) the value of TimingDelay, decrement the value (subs) and write the decremented value back (str). This listing includes the 6 bytes of machine code (0x68a1, 0x3a01, 0x601a) generated by the assembler. While outside the scope of this book, it’s important to realize that assembly language is fundamentally a human readable form of the binary machine code. The process of linking assigns these instructions to fixed memory addresses.
681a ldr r2 , [r3 , #0]
3a01 subs r2 , #1
601a str r2 , [r3 , #0]
Implementing interrupts in the processor requires extending this model slightly: while (1) { if ( interrupt_pending ()) { save_state (); pc = find_handler ();
} else { inst = *pc ++; eval(inst);
}
}
On every “cycle” a test is made to determine if an interrupt is pending
– this literally corresponds to checking if a hardware input is 1 or 0. If so, the current program state (including the program counter) is saved, an interrupt handler address is found, and execution continues with the handler. When the handler completes execution, the preempted state is restored and execution of the application continues from the point of interruption. Note for example, that interrupts occur at machine instruction boundaries and not a “C” statement boundaries. As we shall see, understanding this is fundamental to writing reliable interrupt code.
In the case of the SysTick notice that the handler only modifies the shared data (TimingDelay) when it is non-zero and the application only modifies the shared data when it is zero. Guarantees like this are important because
Revision: 1396a85 (2013-01-07)
153
CHAPTER 11. INTERRUPTS interrupt handlers cause application code to be suspended at unpredictable locations and therefore the data structures that are used to communicate between handlers and application code must be very carefully constructed to ensure that they work correctly. Consider the chaos that might result if an application program and interrupt handler both access a linked list – interrupt handlers had better not access links that are in the process of being moved by the application code. This kind of conflict is called a “race condition.” We present an example of using an interrupt handler to service a UART where the application and handler share two data queues – the code is carefully crafted to avoid potential data races.
The SysTick example demonstrates some typical interactions between interrupt handlers and applications. The handler executes very briefly – just a few machine instructions – in order to update some information shared with the application program. To achieve reliability interrupt handlers must satisfy three properties:
1. They must execute briefly.
2. Their execution time must be predictable (e.g. they must never wait)
3. Their use of “shared data” must be carefully managed.
This model is of course an over-simplification. However, for the subsequent discussion of interrupts, it is a sufficient model. Key questions that we will address are – how do we enable peripherals to generate pending interrupts, how do we ensure that our handlers are executed, and how do we write reliable handlers ? Not illustrated in this model is the concept of interrupt priority – when more than two interrupts are requested, how is the selection made. Neither is interrupt preemption addressed – if an interrupt handler is executing, is it possible for other handlers to be called recursively ?
The remainder of this chapter is organized as follows. We begin with a discussion of the Cortex-M3 interrupt (exception) model including the various exception types, stacks, and privileges. We then discuss the interrupt vector table – the mechanism by which the Cortex-M3 core associates handlers with specific interrupt causes, and the Nested Vector Interrupt Controller (NVIC) which the Cortex-M3 uses to select among competing interrupt requests.
154
Revision: 1396a85 (2013-01-07)
ડાઉનલોડ કરો
જાહેરાત