Vous êtes sur la page 1sur 29

AN2283

Application note
uPSD3400 PWM API
with R/C Servo Motor Control Example (PCM)

Introduction
The µPSD3400 combines a high-performance 8051-based microcontroller with peripherals
to facilitate the design of complex applications.
One such peripheral is the PCA (Programmable Counter Array). There are two PCAs in the
uPSD3400 that operate independently of each other and in various modes that include
capture, timer, toggle output, and PWM (8-, 10-, or 16-bit PWM mode with a fixed frequency
or 8-bit mode with a variable frequency). Each PCA has three TCM (Timer Counter
Modules) that can provide up to six PWM outputs. PWM is used in many applications that
include LED brightness control, servo motor control, and AC/ DC motor speed control.
This application note describes how to use the µPSD3400 Programmable Counter Array
(PCA) logic in Pulse Width Modulation (PWM) mode for Radio Control (R/C) servo motor
control. We provide an introductory background for understanding servo motor control and
PWM, and show how PWM is easily implemented using the µPSD 3400. Note that all future
references to servo motors in this document are of Radio Control (R/C) type.
Servo motors are widely used in motion control applications that require a motor drive to
position a mechanical device. One common way to control the servo motor is by using
PWM, where the duration of the PWM pulse encodes the angular position of the servo
motor shaft. The PCA subsystem in the uPSD3400 provides 11-bits of pulse encoded
resolution (measured).
Additionally, we describe an Application Programming Interface (API) that provides a high-
level interface to the PCA subsystem. API routines are provided specifically for servo motor
control, considering typical servo motor design.
We demonstrate that the µPSD3400 PCA hardware and the PWM API offer a wide range of
flexibility and ease-of-use for PWM programming.

June 2006 Rev 1 1/29


www.st.com
Contents AN2283

Contents

1 Functional overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1 Servo motor control (PWM for digital output applications) . . . . . . . . . . . . . 4
1.2 Pulse width modulation (PWM for analog output applications) . . . . . . . . . 4

2 Description of PWM using the PCA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6


2.1 PCA architecture for PWM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.1.1 PCA clock source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.1.2 Clock source control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1.3 Timer/counter, overflow, and interrupt . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1.4 Timer/counter modules and output pins . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1.5 TCM mode control register . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.1.6 Compare, timer registers, and comparator . . . . . . . . . . . . . . . . . . . . . . . 8
2.2 Programming the PCA for PWM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.1 Timer clock source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.2 Mode of operation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.3 Duty cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.4 Starting the PCA to generate a PWM output signal . . . . . . . . . . . . . . . . 10

3 PWM software API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11


3.1 Init_PWM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.2 Init_Servo_PWM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.3 Update_PWM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.4 Disable_PWM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

4 Servo motor control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15


4.1 Duty cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.2 API application example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Appendix A upsd_pwm.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

Appendix B upsd_type.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2/29
AN2283 Contents

Appendix C upsd_pwm.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

6 Revision history . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

3/29
Functional overview AN2283

1 Functional overview

PWM is a digital mechanism for representing an analog scale, and is used in control (PWM
out) and measurement (PWM in) applications. In this application note, we illustrate a control
application using the µPSD3400, although, the same hardware can also be used for
measuring analog signals.
We first give an introduction to servo motor control, a positioning application, followed by a
tutorial on PWM and its application to servo motor control.

1.1 Servo motor control (PWM for digital output applications)


A servo motor has an output shaft that can be positioned by an encoded control signal. The
motor drives the angular position of the controlled device.
Servo motors have three wires:
● +5V
● GND
● control
The control signal is used to control the angular position of the output shaft. This signal is
encoded using PWM. The pulse duration determines the position of the shaft and as long as
the code is present on the signal, the shaft position is maintained.
The motor rotates the shaft in the shortest direction to the position indicated by the encoded
signal then stops shaft rotation. Servo motor control signals typically have a 20 msec period.
The duty cycle (Pulse width modulation (PWM for analog output applications)) of the pulse
within the period encodes the shaft position:
● -45° rotation is achieved with a 1 msec pulse; a duty cycle of 5%
● 0° rotation (the neutral position) is achieved with a 1.5 msec pulse; a duty cycle of 7.5%
● +45° rotation is achieved with a 2 msec pulse; a duty cycle of 10%
This is also known as PCM (Pulse Coded Modulation). With servo motor control, the width
of the pulse is a code representing a desired shaft position.

1.2 Pulse width modulation (PWM for analog output


applications)
PWM is a modulation technique whereby the width of a pulse over the period of a signal,
known as the duty cycle, is varied to represent the amplitude of an analog signal. Digital
logic that implements PWM can vary the pulse width to achieve various amplitudes, varying
the period to suit the application hardware requirements.
PWM approximates an analog signal by averaging voltage over time. Averaging the duty
cycle over time is equivalent to an average analog voltage. The duty cycle is the percentage
of time the signal is high for the given period. Figure 1 shows the relationship of duty cycle to
period for a PWM signal.

4/29
AN2283 Functional overview

Figure 1. PWM signal

VCC

GND
tdutycycle
tperiod

Duty Cycle is expressed as the percentage of time the signal is high for the given period.
duty cycle = 100 x (tdutycycle) / (tperiod)
For example, a 10% duty cycle applied to a 5Vcc signal approximates an analog voltage of
0.5V once this signal is averaged by an integrator/filter circuit.

5/29
Description of PWM using the PCA AN2283

2 Description of PWM using the PCA

This section shows how PWM is implemented using the µPSD3400 PCA.

2.1 PCA architecture for PWM


PWM is one of four PCA modes and can be configured for 8-, 10-, or 16-bit fixed frequency
resolution, or for 8-bit programmable frequency. A number of clock input sources are also
available, depending on application requirements.
Programmable PCA registers are used to configure the operation of the PCA, to monitor
status and to handle PCA events, such as interrupts on timer overflow. Figure 2 shows the
PCA logic and programmable registers. The µPSD3400 has two PCA blocks, PCA0 and
PCA1. Each PCA block controls three output signals. This allow the designer to
simultaneously control or monitor six independent channels.

Figure 2. PCA0 block diagram

The uPSD34xx has two PCAs called PCA0 and PCA1. The block diagram for PCA0 is
shown in Figure 2 and the different parts are discussed in the following paragraphs. Note
that since PCA0 and PCA1 function in the same way, the description for PCA0 also applies
to PCA1.

2.1.1 PCA clock source


There are three sources of clock input available for the PCA, two internal clock sources and
one external. In this application note, we use PCA0CLK to drive the PCA. PCA0CLK is
derived from the CPU clock with a 4-bit selectable divider that includes division rates of 1, 2,
4, 8 on up to 32768 by powers of 2. The other available internal clock source is the Timer 0
overflow. The external clock source is available through port pin P4.3/ECI (External Clock
Input). CLKSEL0/1 are used to select the clock source.

6/29
AN2283 Description of PWM using the PCA

2.1.2 Clock source control


There are three control bits that determine whether the clock source is passed on to the 16-
bit up timer/counter. EN_ALL (Enable All) is a signal that simultaneously turns on the clock
source to PCA0 and PCA1. It is especially useful, for example, when you need 4 to 6 PWM
outputs that must have synchronized periods.
EN_PCA is used to individually enable the clock source to the PCA and PCAIDLE
determines whether or not the clock source is provided to the PCA when the MCU is in the
idle mode.

2.1.3 Timer/counter, overflow, and interrupt


In the 16-bit PWM mode, PCACH0 and PCACL0 are used as the high and low bytes of the
16-bit timer. When the timer overflows, the OVF0 bit is set and the timer continues counting.
If this interrupt is enabled (EOVFI), the PCA interrupt is generated. In this application note
we don't use the PCA interrupt.

2.1.4 Timer/counter modules and output pins


There are three Timer/Counter Modules (TCM) per PCA. Each TCM is 16 bits wide and has
an optional output available on a port 4 pin (CEX0, CEX1, or CEX2). The port 4 pins are
multifunctional and the function of each pin is selected using the port 4 special function
registers (P4SFS0 and P4SFS1).
When the count in the timer matches the value in the TCM register, the output is switched
from low to a high. When the 16-bit timer overflows, the output switches from high to low. So,
the value written to the TCM register determines the pulse width for the respective PWM
output (CEXn).
Figure 3 shows the registers that implement the PWM mode of operation. (We show the 16-
bit mode of operation, since that is what is used for the servo motor control application).

Figure 3. PWM mode, 16-bit, fixed frequency

7/29
Description of PWM using the PCA AN2283

2.1.5 TCM mode control register


Each TCM has a mode control register (TCMCODEn) that is used to determine how the
TCM functions. For a 16-bit fixed frequency PWM mode, bits E_COMP and PWM1 and
PWM0 are set to a 1 while the other bits are left at 0. The E_COMP bit enables the
comparator so that when there is a match between the 16-bit timer and the 16-bit compare
registers, the CEXn pin is set (logic one). When the 16-bit timer overflows, the output is
reset (logic zero). The PWM1 and PWM0 bits are used to enable the PWM mode with fixed
frequency and the output going to the CEXn pin.

2.1.6 Compare, timer registers, and comparator


The capture compare registers (CAPCOMHn and CAPCOMLn) are part of the TCM and
form a 16-bit register pair that is used to store a compare value. When the 16-bit comparator
detects a match between the timer count (PCACHm/PCACLm) and the value in the
compare registers (CAPCOMHn/CAPCOMLn), the CEXn pin is set (logic one). When the
timer overflows, CEXn is reset (logic zero). Once the CAPCOM registers are written with a
value, the resulting pulse width out on CEXn will continue to be the same cycle after cycle
until a new value is written.

2.2 Programming the PCA for PWM


Programming the PCA for PWM requires selecting the clock source for the timer, setting the
duty cycle for the pulse, and selecting the mode of operation.

2.2.1 Timer clock source


As was mentioned in Section 2.1, there are three options for the clock source. Either the
internal clock (PCACLK0) divided down by a selectable divisor, Timer 0 overflow, or an
external clock. Once it is determined which clock is necessary to provide the desired
frequency, the clock select bits (CLKSEL1 and CLKSEL0) in the PCACON0 register should
be programmed appropriately to select the desired clock source. If the internal clock is used,
the prescaler bits (PCA0PS[3:0]) in the CCON2 register should be programmed
appropriately.

2.2.2 Mode of operation


The PCA supports various modes of PWM operation, including 8-, 10-, and 16-bit fixed
frequency. Additionally, there is an 8-bit mode with variable frequency (see data sheet for
more details as this document focuses on the fixed frequency mode). The fixed frequency
mode selected depends on the amount of resolution required for the duty cycle, the more
bits, the higher the resolution.
The 10B_PWM bit in the PCACON0 register (10B_PWM) selects either the 10-bit or 16-bit
PWM mode. Additionally, there are mode bits in the TCMMODEx register that determine
how the respective TCM functions. The E_COMP bit in the TCMMODEx register enables
the comparator that must be set for PWM operation. Also, the PWM[1:0] bits enable the 8-,
or 10-/16-bit PWM mode of operation.
The MCU port 4 I/O pins are multifunctional and can be configured for a variety of functions.
These I/O pins default to MCU I/O mode and must be configured using the special function
registers (P4SFS0/1) for PWM output. The pin signal names, when used as PCA function,

8/29
AN2283 Description of PWM using the PCA

are called CEXx internally and TCMx externally. The output of a CEXn signal to a TCMx pin
is configured on an individual basis as needed.

2.2.3 Duty cycle


The duty cycle is the time that the pulse is high with respect to the time that it is low. Before
setting the duty cycle, it is important to understand how the hardware functions. Figure 4
shows a typical PWM waveform. When the timer count is 0 (as is when the timer is first
started or after an overflow), the PWM output is a low. When the timer count matches the
value in the CAPCOM register, the PWM output changes state to a high level. Then, when
the timer overflows, it starts counting again from 0 and the PWM output changes state to a
low level. By using different values in the CAPCOM register, the duty cycle is varied from 0%
to 100%.

Figure 4. PWM mode of operation


Match
(Timer and Timer Overflow
CAPCOM)

VCC

GND
duty
cycle

period

So, to set the duty cycle, the appropriate value must be written to the CAPCOM register. In
10- and 16-bit mode, the CAPCOM register consists of two 8-bit registers (CAPCOMH0 and
CAPCOML0) with the value being LSB justified for 10-bit mode (and the upper 6 bits in
CAPCOMH0 not used). In 8-bit mode, just the CAPCOML0 register is used and
CAPCOMH0 is ignored.
The value to write to CAPCOM register can be determined in the following way:
[1 - (desired duty cycle) ] * (total timer count) = (CAPCOM value)
So, if we want a 20% duty cycle in 16-bit PWM mode, substituting numbers in the equation,
we have:
[1 - (0.20)] * (65536) = (CAPCOM value) ≈ (52429)
For a 20% duty cycle in 10-bit mode, we have:
[1 - (0.20)] * (1024) = (CAPCOM value) ≈ (819)
And for a 20% duty cycle in 8-bit mode:
[1 - (0.20)] * (256) = (CAPCOM value) ≈ (205)
Note: The PWM output only changes states when there is a match of the timer count and the
CAPCOM register. If the MCU writes a value to the CAPCOM register after the timer count

9/29
Description of PWM using the PCA AN2283

has passed that value, the PWM output will remain low for the entire current period. In the
next period, the PWM output will go high when there is a match. To ensure there is no dead
cycle, the CAPCOM register should be written with a new value either on a match or
overflow. There are flags in the PCA status register (PCASTATA) that indicate when such
events occur. For duty cycles near 0%, it is best to use the overflow flag. For duty cycles
near 100%, the match flag is the best to use.

2.2.4 Starting the PCA to generate a PWM output signal


After the clock source has been selected, the mode bits set appropriately, the CAPCOM
register written, and the I/O pins configured, the only thing left to do is to enable the PCA. To
turn on, or enable the PCA requires setting the EN_PCA bit in the PCACON0 register. To
turn off the PCA, just clear the EN_PCA bit.
If it is desired to have 4 to 6 PWM outputs with the periods in sync, then the EN_ALL bit in
the PCACON0 register should be used to start PCA0 and PCA1 at the same time. This
ensures that clock to each PCA is turned on at the same time so that they are in sync with
each other.

10/29
AN2283 PWM software API

3 PWM software API

This describes a high-level C interface for basic PWM control and servo motor control in
particular.
These API procedures support the six PCA I/O ports, allowing independent PWM operation
on each of the ports. In addition, the API supports 8-, 10-, and 16-bit resolution for up to 16
PWM frequencies.

Init_PWM() Initialize and start PWM operation for a particular channel.


Init_Servo_PWM() Initialize and start PWM operation for a particular channel that is
used for servo motor control.
Update_PWM() Update the duty cycle for a channel already operating in PWM
mode.
Disable_PWM() Disable PWM output for a particular channel.

The constants, data types, prototypes and data structures needed by the application to use
the API are declared in the following header files.

upsd_pwm.h Appendix A: upsd_pwm.h PWM API declarations and prototypes


upsd_type.h Appendix B: upsd_type.h PWM API data types

The API also uses the upsd3400.h and upsd3400_hardware.h header files to reference the
DK3400 hardware registers. These header files is provided with both Keil and Raisonance
development toolkits.
An application program using the API would typically have the following include statements.
#include “upsd3400.h”
#include “upsd3400_hardware.h”
#include “upsd_type.h”
#include “upsd_pwm.h”
The following sections describe each API procedure in detail.

3.1 Init_PWM

Synopsis _returned_error_code Init_PWM (


CHANNEL_ID channel,
PWM_MODE mode,
u8 frequency,
u16 dutyCycle);

11/29
PWM software API AN2283

Description This initializes and starts PWM operation for the requested channel. The
channel is set to the PWM mode resolution (8-, 10-, or 16-bit) at the
frequency prescaler divisor index value (1-16), and the dutyCycle
consistent with the specified mode. (The dutyCycle is a raw value with
either 8-, 10-, or 16-bit significance).
When the PCA counter is equal to dutyCycle, the output pin for the
channel transitions to high. The signal transitions to low when the PCA
counter overflows.

Parameters channel - PCA I/O port corresponding to Timer Counter Module output
pin.
Enumerated literal:
CHANNEL_1 - PCA0, TCM0
CHANNEL_2 - PCA0, TCM1
CHANNEL_3 - PCA0, TCM2
CHANNEL_4 - PCA1, TCM3
CHANNEL_5 - PCA1, TCM4
CHANNEL_6 - PCA1, TCM5
mode - PWM mode counter resolution.
Enumerated literal:
RES_8_BIT - 8-bit counter
RES_10_BIT -10-bit counter
RES_16_BIT - 16-bit counter
frequency - prescaler value.
fPCA0CLK = fOSC / (2^frequency)
dutyCycle - 8, 10, or 16-bit counter compare value.
When counter equals dutyCycle, output signal transitions to high.

Return SUCCESS - Channel initialized and PWM operation successfully


started.
FAILURE - Unable to initialize the requested specified channel; PWM
not started.

3.2 Init_Servo_PWM

Synopsis _returned_error_code Init_Servo_PWM (


CHANNEL_ID channel);

12/29
AN2283 PWM software API

Description This initializes and starts PWM operation for the requested channel. The
PCA is configured for servo motor PWM operation. The channel is set to
16-bit counter resolution, a frequency of about 26msec and a duty cycle
of 1.5msec.
Use Update_PWM() to change the duty cycle.
See also: 3.1: Init_PWM()

Parameters channel - PCA I/O port corresponding to Timer Counter Module output
pin.
Enumerated literal:
CHANNEL_1 - PCA0, TCM0
CHANNEL_2 - PCA0, TCM1
CHANNEL_3 - PCA0, TCM2
CHANNEL_4 - PCA1, TCM3
CHANNEL_5 - PCA1, TCM4
CHANNEL_6 - PCA1, TCM5

Return SUCCESS - Channel initialized and PWM operation successfully started


for servo motor PWM operation.
FAILURE - Unable to initialize the requested channel; PWM not started.

3.3 Update_PWM

Synopsis _returned_error_code update_PWM (


CHANNEL_ID channel,
u16 dutyCycle);

Description This updates the duty cycle for the requested channel. The dutyCycle is
a raw value with either 8-, 10-, or 16-bit significance, depending on the
current channel PWM mode resolution.
NOTE: A call to this procedure is not effective until the PCA counter
overflows. Depending on the current PCA counter value, the dutycycle
of the current period, only, may be longer or shorter than requested.

13/29
PWM software API AN2283

Parameters channel - PCA I/O port corresponding to Timer Counter Module output
pin.
Enumerated literal:
CHANNEL_1 - PCA0, TCM0
CHANNEL_2 - PCA0, TCM1
CHANNEL_3 - PCA0, TCM2
CHANNEL_4 - PCA1, TCM3
CHANNEL_5 - PCA1, TCM4
CHANNEL_6 - PCA1, TCM5
dutyCycle - 8, 10, or 16-bit counter compare value.
When counter equals dutyCycle, output signal transitions to high.

Return SUCCESS - Channel duty cycle successfully updated.


FAILURE - Unable to update duty cycle for requested channel; the
current duty cycle is not changed.

3.4 Disable_PWM

Synopsis _returned_error_code Disable_PWM (


CHANNEL_ID channel);

Description This disables PWM output on the I/O pin associated with the channel.
PCA registers are modified and PWM operation may be resumed by
calling either Init_PWM() or Init_Servo_PWM().

Parameters channel - PCA I/O port corresponding to Timer Counter Module output
pin.
Enumerated literal:
CHANNEL_1 - PCA0, TCM0
CHANNEL_2 - PCA0, TCM1
CHANNEL_3 - PCA0, TCM2
CHANNEL_4 - PCA1, TCM3
CHANNEL_5 - PCA1, TCM4
CHANNEL_6 - PCA1, TCM5

Return SUCCESS - Channel disabled and PWM output stopped.


NOTE: PCA hardware registers are not reset.
FAILURE - Unable to disable requested channel.

14/29
AN2283 Servo motor control

4 Servo motor control

The servo used in this example requires a control signal with a pulse width from 1.0 ms to
2.0 ms with 1.5 ms being the center (or neutral) position. The period of the control signal is
not critical and is typically around 20 ms.
Since the uPSD3400 runs at a maximum frequency of 40 MHz, we will use this as our main
clock for this discussion. Additionally, we will use the PCA in 16-bit PWM mode and use the
internal clock, PCA0CLK, as the input clock to the PCA.
PCA0CLK is the main oscillator clock divided down by a firmware selectable value of 1
through 32,768 (by powers of two). Doing some calculations, we determine that selecting a
divisor of 16 results in a 26.2 ms period. Even though the period is around 6 ms longer than
what is typically used, the servo responds appropriately.
The equation used to calculate the period is:
(PWM period) = (total timer count) * (1 / ((main clock frequency) / (clock divisor)))
Substituting numbers, (40MHz clock and a clock divisor of 16), we get a period of:
(65536) * (1 / ((40 MHz) / 16)) = 26.2 ms
The PWM API includes a function that makes it easy to use the PCA for servo applications.
This function is called Init_Servo_PWM() and it initializes the PCA for 16-bit, fixed frequency
PWM with a period of 26.2 ms and also centers the servo at 0° by setting the duty cycle for
a pulse width of 1.5 ms. In addition, it sets the respective port 4 pin to the PWM output mode
based on the channel input parameter passed to the function.

4.1 Duty cycle


Since we need to provide the servo with a control signal that has a pulse width between 1.0
ms and 2.0 ms, we need to determine the range of values to be written to the compare
registers (CAPCOMH0 and CAPCOML0). Rather than make calculations based on duty
cycle in percent, we will use actual time that we want the pulse width to be since that is the
specification that we have. The equation to determine the CAPCOM value for a specific
pulse width, as was presented earlier, is:
(CAPCOM value) = [1 - ((pulse width time) / (period))] * (total timer count)
For a 1.0 ms pulse width, substituting in the numbers, we get:
[1 - ((1.0 ms) / (26.2 ms))] * (65536) ≈ 63035
For a 2.0 ms pulse width, substituting in the numbers, we get:
[1 - ((2.0 ms) / (26.2 ms))] * (65536) ≈ 60533
For a 1.5 ms pulse width, substituting in the numbers, we get:
[1 - ((1.5 ms) / (26.2 ms))] * (65536) ≈ 61784
So, to drive the servo motor to a -45° deflection, we provide a control signal with a pulse
width of 1.0 ms by writing 63035 to the CAPCOM registers. To drive the servo motor to the
+45° deflection, we write a value of 60533 to the CAPCOM registers resulting in a pulse
width of 2.0 ms. To center the servo motor at 0°, we write a value of 61784.

15/29
Servo motor control AN2283

Once the PCA has been initialized with a call to the Init_Servo_PWM() function, the duty
cycle is changed by calling the Update_PWM() function. Passed to this function is the
channel number and the raw 16-bit value to write to the CAPCOM register.
If it is desired to disable PWM on a particular channel, the Disable_PWM() function will
disable PWM specified channel.

4.2 API application example


The example provided with the API first initializes the servo setting it to the center position
(1.5 ms pulse width). After a short delay, the servo is driven to the -45° position (1.0 ms
pulse width), to the center (1.5 ms pulse width), to +45° (2.0 ms pulse width) and then back
to the center. This cycle is repeated continuously. Listed below is a copy of the example
code.

//Define some deflection points


#define minus45deg 63035
#define centerpos 61784
#define plus45deg 60533

main()
{
_returned_error_code status;

// setup operating environment


init ();

status = Init_Servo_PWM(CHANNEL_1); // Initialize the PWM for


servo control

// do forever ...
while (1)
{
mydelay (2);
status = Update_PWM(CHANNEL_1, minus45deg); //-45 degree deflection (1.0 ms
pulse width)

mydelay (2);
status = Update_PWM(CHANNEL_1, centerpos); //Center (1.5 ms pulse width)

mydelay (2);
status = Update_PWM(CHANNEL_1, plus45deg); //+45 degree deflection (2.0 ms
pulse width)

mydelay (2);
status = Update_PWM(CHANNEL_1, centerpos); //Center (1.5 ms pulse width)
}
}

16/29
AN2283 Conclusion

5 Conclusion

The PCA in the uPSD3400, in combination with the API, provides an easy-to-use high level
interface for controlling R/C Servo motors. With just over 11-bits (2502 total counts) of
resolution for an encoded pulse width varying between 1.0ms and 2.0ms, an R/C servo
motor's deflection can be controlled with approximately 0.036° per count (assuming the
servo's total deflection range is 90°). This provides for very fine and smooth control of the
servo motor with very satisfactory results.

17/29
upsd_pwm.h AN2283

Appendix A upsd_pwm.h

/*************** (C) COPYRIGHT 2005 STMicroelectronics **************


* File Name : upsd_pwm.h
* Author : MCU Application Team
* Date First Issued : 01/01/2005
* Description : Header file for the uPSD ...
*********************************************************************
* History:
* 07/01/2005 : V1.0
* 06/01/2005 : created
*********************************************************************
THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING
CUSTOMERS WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER
FOR THEM TO SAVE TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE
HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH
RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE AND/
OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED
HEREIN IN CONNECTION WITH THEIR PRODUCTS.
********************************************************************/
#ifndef _upsd_pwm_H
#define _upsd_pwm_H

// _returned_error_code values
typedef enum
{
SUCCESS = 0,
FAILURE
} _returned_error_code;

// fixed servo frequency


#define SERVO_FREQ 20// 20 msec

// fixed servo frequencies ranges


#define SERVO_DUTY_MIN1// minimum frequency (1 msec)
#define SERVO_DUTY_MID15// mid-frequency (1.5 msec)
#define SERVO_DUTY_MAX2// maximum frequency (2 msec)

// PCA Block ID
typedef enum
{
PCABLK_0 = 0,// PCA block 0
PCABLK_1 // PCA block 1
} PCABLOCK_ID;

// PWM type
typedef enum
{
PWM_STD, // standard PWM
PWM_SERVO // servo PWM
} PCATYPE;

// channel ID
typedef enum
{
CHANNEL_1 = 0,// channel 1
CHANNEL_2, // channel 2
CHANNEL_3, // channel 3
CHANNEL_4, // channel 4
CHANNEL_5, // channel 5

18/29
AN2283 upsd_pwm.h

CHANNEL_6 // channel 6
} CHANNEL_ID;

#define MAX_CHAN(CHANNEL_6+1)

// PWM State
typedef enum
{
PWM_ENABLED,// enabled
PWM_DISABLED// disabled
} PWM_STATE;

// PWM Mode (resolution)


typedef enum
{
RES_8_BIT, // 8-bit resolution
RES_10_BIT, // 10-bit resolution
RES_16_BIT // 16-bit resolution
} PWM_MODE;

// timer sources
typedef enum
{
T_PCA, // PCA
T_0, // timer 0
T_1, // timer 1
T_2_3 // timer 2/3
} T_SOURCE;

//
// datatypes
//

// channel control block


typedef struct
{
PWM_STATE state;// enabled/disabled
PWM_MODE mode;// 8-, 10-, 16-bit resolution
T_SOURCE timer;// timer source
u16 frequency;// frequency (bit-resolution)
u16 dutycycle;// duty cycle (bit-resolution)
} CH_CTL;

// prototype declarations

void Reset_PWM(void);
_returned_error_code Init_PWM(CHANNEL_ID channel, PWM_MODE mode, u8 frequency, u16
dutyCycle);
_returned_error_code Init_Servo_PWM(CHANNEL_ID channel);
_returned_error_code Disable_PWM(CHANNEL_ID channel);
_returned_error_code Update_PWM(CHANNEL_ID channel, u16 dutyCycle);

#endif /* _upsd_pwm_H */

/******** (C) COPYRIGHT 2005 STMicroelectronics *****END OF FILE****/

19/29
upsd_type.h AN2283

Appendix B upsd_type.h

/*************** (C) COPYRIGHT 2005 STMicroelectronics **************


* File Name : upsd_type.h
* Author : MCU Application Team
* Date First Issued : 01/01/2005
* Description : Common data types
*********************************************************************
* History:
* 07/01/2005 : V1.0
* 06/01/2005 : created
*********************************************************************
THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING
CUSTOMERS WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER
FOR THEM TO SAVE TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE
HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH
RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE AND/
OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED
HEREIN IN CONNECTION WITH THEIR PRODUCTS.
********************************************************************/
#ifndef _upsd_type_H
#define _upsd_type_H

typedef unsigned long u32;


typedef unsigned short u16;
typedef unsigned char u8;

typedef signed long s32;


typedef signed short s16;
typedef signed char s8;

typedef enum { RESET = 0, SET = !RESET } FlagStatus;

typedef enum { DISABLE = 0, ENABLE = !DISABLE } FunctionalState;

typedef enum { INDIRECT = 0, DIRECT = !INDIRECT } RegisterAccess;

#endif /* _upsd_type_H */

/********* (C) COPYRIGHT 2005 STMicroelectronics *****END OF FILE****/

20/29
AN2283 upsd_pwm.c

Appendix C upsd_pwm.c

/******************** (C) COPYRIGHT 2005 STMicroelectronics ********************


* File Name : upsd_pwm.c
* Author : AMCU Application Team
* Date First Issued : 01/01/2005
* Description : ... for the uPSD ...
*******************************************************************************
* History:
* 06/08/2006 : V1.0
* 06/01/2005 : created
*******************************************************************************
THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH
CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT
OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/

#include "upsd3400.h"
#include "upsd_type.h"
#include "upsd_pwm.h"

/*******************************************************************************
Global variables
*******************************************************************************/

CH_CTL ch_ctl_blk[MAX_CHAN];// channel control block

u8 P4SFS0_mask[MAX_CHAN] = {0x01, 0x02, 0x04, 0x10, 0x20, 0x40};


u8 P4SFS1_mask[MAX_CHAN] = {0xfe, 0xfd, 0xfb, 0xef, 0xdf, 0xbf};

/*******************************************************************************
* Function Name : Set_DutyCycle
* Description : This function sets the dutycycle for a specific PWM channel.
* Input : channel - 'CHANNEL_1', 'CHANNEL_2', ... 'CHANNEL_6'
* : mode - 8-, 10-, 16-bit
* : dutyCycle - (actual CAPCOM value) 0-FF, 0-03FF or 0-FFFF
* Output : None
* Return : SUCCESS = dutyCycle successfully set
* FAILURE = invalid channel id parameter
*******************************************************************************/
_returned_error_code Set_DutyCycle(CHANNEL_ID channel, PWM_MODE mode, u16 DutyCycle)
{
u8 dc_l;
u8 dc_h;

dc_l = DutyCycle & 0x00ff;

if (mode == RES_8_BIT) // In 8-bit mode, the PWM reload value is stored in


CAPCOMH0,
dc_h = dc_l; // so load CAPCOMH0 and CAPCOML0 with the same value.
else
dc_h = (DutyCycle >> 8) & 0x00ff;

switch (channel)
{
case CHANNEL_1:
CAPCOML0 = dc_l;
CAPCOMH0 = dc_h;

21/29
upsd_pwm.c AN2283

break;
case CHANNEL_2:
CAPCOML1 = dc_l;
CAPCOMH1 = dc_h;
break;
case CHANNEL_3:
CAPCOML2 = dc_l;
CAPCOMH2 = dc_h;
break;
case CHANNEL_4:
CAPCOML3 = dc_l;
CAPCOMH3 = dc_h;
break;
case CHANNEL_5:
CAPCOML4 = dc_l;
CAPCOMH4 = dc_h;
break;
case CHANNEL_6:
CAPCOML5 = dc_l;
CAPCOMH5 = dc_h;
break;
default:
return (FAILURE);
break;
}

return (SUCCESS);
}

/*******************************************************************************
* Function Name : Set_TCM
* Description : This function sets the TCM mode for a specific PWM channel.
* Input : channel - 'CHANNEL_1', 'CHANNEL_2', ... 'CHANNEL_6'
* mode - 8-, 10-, 16-bit
* Output : None
* Return : SUCCESS = mode successfully set
* FAILURE = invalid channel id parameter
*******************************************************************************/
_returned_error_code Set_TCM(CHANNEL_ID channel, u8 mode)
{
switch (channel)
{
case CHANNEL_1:
TCMMODE0 = mode;
break;
case CHANNEL_2:
TCMMODE1 = mode;
break;
case CHANNEL_3:
TCMMODE2 = mode;
break;
case CHANNEL_4:
TCMMODE3 = mode;
break;
case CHANNEL_5:
TCMMODE4 = mode;
break;
case CHANNEL_6:
TCMMODE5 = mode;
break;
default:
return (FAILURE);
break;

22/29
AN2283 upsd_pwm.c

return (SUCCESS);
}

/*******************************************************************************
* Function Name : Get_TCM
* Description : This function returns the TCM mode for a specific PWM channel.
* Input : channel - 'CHANNEL_1', 'CHANNEL_2', ... 'CHANNEL_6'
* Output : None
* Return : current TCM mode; 8-, 10-, 16-bit (returns 0 on error)
*******************************************************************************/
u8 Get_TCM(CHANNEL_ID channel)
{
u8 mode;

switch (channel)
{
case CHANNEL_1:
mode = TCMMODE0;
break;
case CHANNEL_2:
mode = TCMMODE1;
break;
case CHANNEL_3:
mode = TCMMODE2;
break;
case CHANNEL_4:
mode = TCMMODE3;
break;
case CHANNEL_5:
mode = TCMMODE4;
break;
case CHANNEL_6:
mode = TCMMODE5;
break;
default:
mode = 0;
break;
}

return (mode);
}

/*******************************************************************************
* Function Name : Set_PWMIO
* Description : This function sets the PWM I/O signal function for a channel.
* Input : channel - 'CHANNEL_1', 'CHANNEL_2', ... 'CHANNEL_6'
* Output : None
* Return : SUCCESS = I/O signal function successfully set
*******************************************************************************/
_returned_error_code Set_PWMIO(CHANNEL_ID channel)
{
P4SFS1 &= P4SFS1_mask[channel];
P4SFS0 |= P4SFS0_mask[channel];

return (SUCCESS);
}

/*******************************************************************************
* Function Name : Init_PWM
* Description : This function initializes and starts PCA operation for a
* PWM channel.

23/29
upsd_pwm.c AN2283

* Input : channel - 'CHANNEL_1', 'CHANNEL_2', ... 'CHANNEL_6'


* mode - 8-, 10-, 16-bit
* frequency - prescalar value (4-bit; uPSD33xx, pg. 124)
* dutyCycle - (actual CAPCOM value) 0-FF, 0-03FF or 0-FFFF
* Output : None
* Return : SUCCESS = channel ititialized
* FAILURE = channel failed to initialize
*******************************************************************************/
_returned_error_code Init_PWM(CHANNEL_ID channel, PWM_MODE mode, u8 frequency, u16
dutyCycle)
{
_returned_error_code status;
u8 prescalar;
u8 tcmmode;
CH_CTL *ch_p;

status = SUCCESS;

// set prescale and mode (map channel to register for group)

switch (channel)
{
case CHANNEL_1:
case CHANNEL_2:
case CHANNEL_3:

// calculate prescalar value, given frequency


// (for now, frequency is expressed as the prescalar value)
prescalar = frequency & 0x0f;

CCON2 = 0x10 | prescalar;// PCA0CLK enabled, prescalar, disable PCA counter

// set mode and get TCMMODE reg for channel


switch (mode)
{
case RES_8_BIT:
PCACON0 = 0x40;
Set_TCM(channel, 0x01);
break;

case RES_10_BIT:
PCACON0 = 0x44;
Set_TCM(channel, 0x03);
break;

case RES_16_BIT:
PCACON0 = 0x40;
Set_TCM(channel, 0x03);
break;
}
break;

case CHANNEL_4:
case CHANNEL_5:
case CHANNEL_6:

// calculate prescalar value, given frequency


// (for now, frequency is expressed as the prescalar value)
prescalar = frequency & 0x0f;

CCON3 = 0x10 | prescalar;// PCA0CLK enabled, prescalar, disable PCA counter

// set mode and enable counter

24/29
AN2283 upsd_pwm.c

switch (mode)
{
case RES_8_BIT:
PCACON1 = 0x40;
Set_TCM(channel, 0x01);
break;

case RES_10_BIT:
PCACON1 = 0x44;
Set_TCM(channel, 0x03);
break;

case RES_16_BIT:
PCACON1 = 0x40;
Set_TCM(channel, 0x03);
break;
}
break;
}

if (status == SUCCESS)
{
// setup I/O pin
Set_PWMIO(channel);

// set dutycycle
if ((status = Set_DutyCycle(channel, mode, dutyCycle)) == SUCCESS)
{
// enable comparator
tcmmode = Get_TCM(channel);
tcmmode |= 0x40;
status = Set_TCM(channel, tcmmode);

// configure channel control block


ch_p = &ch_ctl_blk[channel];

ch_p->state = PWM_ENABLED;
ch_p->mode = mode;
ch_p->timer = T_PCA;
ch_p->frequency = frequency;
ch_p->dutycycle = dutyCycle;
}
}

return (status);
}

/*******************************************************************************
* Function Name : Init_Servo_PWM
* Description : This function the PCA initializes and starts the PCA subsystem
* for servo motor PWM operation, for a specific channel.
* Input : channel - 'CHANNEL_1', 'CHANNEL_2', ... 'CHANNEL_6'
* Output : None
* Return : SUCCESS = channel ititialized
* FAILURE = channel failed to initialize
*******************************************************************************/
_returned_error_code Init_Servo_PWM(CHANNEL_ID channel)
{
// for now use prescalar = 16 (freq = 26.2 msec); dutycycle = 1.5msec
return (Init_PWM(channel, RES_16_BIT, 4, 61784));
}

/*******************************************************************************

25/29
upsd_pwm.c AN2283

* Function Name : Disable_PWM


* Description : This function disables PWM operations for a specific PWM
* channel. If the channel is already disabled, this has no
* effect.
* Input : channel - 'CHANNEL_1', 'CHANNEL_2', ... 'CHANNEL_6'
* Output : None
* Return : SUCCESS = PWM operations for channel disabled
* FAILURE = Invalid parameter or unable to handle request
* (channel state undefined)
*******************************************************************************/
_returned_error_code Disable_PWM(CHANNEL_ID channel)
{
_returned_error_code status;
CH_CTL *ch_p;
u8 mode;

status = SUCCESS;

// disable selected channel and update control block

if ((channel >= CHANNEL_1) && (channel <= CHANNEL_6))


{
mode = Get_TCM(channel);
mode &= 0xbf;
Set_TCM(channel, mode);

ch_p = &ch_ctl_blk[channel];

ch_p->state = PWM_DISABLED;
}
else
{
status = FAILURE;
}

return (status);
}

/*******************************************************************************
* Function Name : Update_PWM
* Description : This function updates the PWM duty cycle. It updates the
* specified channel according to how the channel is initialized
* (standard/servo, mode). The change is effective on the next
* PCA counter cycle.
* Input : channel - 'CHANNEL_1', 'CHANNEL_2', ... 'CHANNEL_6'
* dutyCycle - 8- or 16-bitvalue, depending on channelmode/type
* Output : None
* Return : SUCCESS = PWM operation mode successfully set
* FAILURE = Invalid parameter or unable to handle request;
* (channel state undefined)
*******************************************************************************/
_returned_error_code Update_PWM(CHANNEL_ID channel, u16 dutyCycle)
{
_returned_error_code status;
CH_CTL *ch_p;

// update duty cycle based on channel configuration

if ((channel >= CHANNEL_1) && (channel <= CHANNEL_6))


{
ch_p = &ch_ctl_blk[channel];

if (((ch_p->mode == RES_8_BIT) && (dutyCycle < 256)) ||

26/29
AN2283 upsd_pwm.c

((ch_p->mode == RES_10_BIT) && (dutyCycle < 1024)) ||


(ch_p->mode == RES_16_BIT))
{
status = Init_PWM(channel, ch_p->mode, ch_p->frequency, dutyCycle);
}
else
{
status = FAILURE;
}
}
else
{
status = FAILURE;
}

return (status);
}

/******************* (C) COPYRIGHT 2005 STMicroelectronics *****END OF FILE****/

27/29
Revision history AN2283

6 Revision history

Date Revision Changes

16-Jun-2006 1.0 Initial release.

28/29
AN2283 Revision history

Please Read Carefully:

Information in this document is provided solely in connection with ST products. STMicroelectronics NV and its subsidiaries (“ST”) reserve the right to make changes, corrections,
modifications or improvements, to this document, and the products and services described herein at any time, without notice.
All ST products are sold pursuant to ST’s terms and conditions of sale.
Purchasers are solely responsible for the choice, selection and use of the ST products and services described herein, and ST assumes no liability whatsoever relating to the
choice, selection or use of the ST products and services described herein.
No license, express or implied, by estoppel or otherwise, to any intellectual property rights is granted under this document. If any part of this document refers to any third party
products or services it shall not be deemed a license grant by ST for the use of such third party products or services, or any intellectual property contained therein or considered
as a warranty covering the use in any manner whatsoever of such third party products or services or any intellectual property contained therein.

UNLESS OTHERWISE SET FORTH IN ST’S TERMS AND CONDITIONS OF SALE ST DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY WITH RESPECT TO THE
USE AND/OR SALE OF ST PRODUCTS INCLUDING WITHOUT LIMITATION IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE (AND THEIR EQUIVALENTS UNDER THE LAWS OF ANY JURISDICTION), OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER INTELLECTUAL
PROPERTY RIGHT.
UNLESS EXPRESSLY APPROVED IN WRITING BY AN AUTHORIZE REPRESENTATIVE OF ST, ST PRODUCTS ARE NOT DESIGNED, AUTHORIZED OR WARRANTED
FOR USE IN MILITARY, AIR CRAFT, SPACE, LIFE SAVING, OR LIFE SUSTAINING APPLICATIONS, NOR IN PRODUCTS OR SYSTEMS, WHERE FAILURE OR
MALFUNCTION MAY RESULT IN PERSONAL INJURY, DEATH, OR SEVERE PROPERTY OR ENVIRONMENTAL DAMAGE.

Resale of ST products with provisions different from the statements and/or technical features set forth in this document shall immediately void any warranty granted by ST for
the ST product or service described herein and shall not create or extend in any manner whatsoever, any liability of ST.

ST and the ST logo are trademarks or registered trademarks of ST in various countries.

Information in this document supersedes and replaces all information previously supplied.

The ST logo is a registered trademark of STMicroelectronics. All other names are the property of their respective owners.

© 2006 STMicroelectronics - All rights reserved

STMicroelectronics group of companies


Australia - Belgium - Brazil - Canada - China - Czech Republic - Finland - France - Germany - Hong Kong - India - Israel - Italy - Japan - Malaysia - Malta - Morocco - Singapore
- Spain - Sweden - Switzerland - United Kingdom - United States of America
www.st.com

29/29

Vous aimerez peut-être aussi