Académique Documents
Professionnel Documents
Culture Documents
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.
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
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.
4/29
AN2283 Functional overview
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
This section shows how PWM is implemented using the µPSD3400 PCA.
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.
6/29
AN2283 Description of PWM using the PCA
7/29
Description of PWM using the PCA AN2283
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.
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.
10/29
AN2283 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.
The constants, data types, prototypes and data structures needed by the application to use
the API are declared in the following header files.
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
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.
3.2 Init_Servo_PWM
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
3.3 Update_PWM
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.
3.4 Disable_PWM
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
14/29
AN2283 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.
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.
main()
{
_returned_error_code status;
// 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
// _returned_error_code values
typedef enum
{
SUCCESS = 0,
FAILURE
} _returned_error_code;
// 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;
// timer sources
typedef enum
{
T_PCA, // PCA
T_0, // timer 0
T_1, // timer 1
T_2_3 // timer 2/3
} T_SOURCE;
//
// datatypes
//
// 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 */
19/29
upsd_type.h AN2283
Appendix B upsd_type.h
#endif /* _upsd_type_H */
20/29
AN2283 upsd_pwm.c
Appendix C upsd_pwm.c
#include "upsd3400.h"
#include "upsd_type.h"
#include "upsd_pwm.h"
/*******************************************************************************
Global variables
*******************************************************************************/
/*******************************************************************************
* 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;
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
status = SUCCESS;
switch (channel)
{
case CHANNEL_1:
case CHANNEL_2:
case CHANNEL_3:
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:
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);
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
status = SUCCESS;
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;
26/29
AN2283 upsd_pwm.c
return (status);
}
27/29
Revision history AN2283
6 Revision history
28/29
AN2283 Revision history
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.
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.
29/29