K40: Turning A Servo Tutorial

Document created by GUO XIAOLI Employee on Jul 12, 2012Last modified by GUO XIAOLI Employee on Jul 25, 2012
Version 13Show Document
  • View in full screen mode

This tutorial covers the details of Turning A Servo on the Kinetis K40 using TWR-K40x256-KIT evaluation board.





In this exercise you will build a “bare metal” (no RTOS) application which turns a servo, targeting a Freescale K40 board.


You will:

  • Create the Servo code in CodeWarrior
  • Build the Servo project
  • Download and run the code on a Kinetis K40 Tower System board
  • Learn how to utilize the FlexTimer module to control a Servo


  To successfully complete this exercise you need the following board and development environment.

  • The K40 Tower card, TWR-K40x256
  • Tower Elevator Panels
  • Servo
  • Prototyping Board
  • Power to your servo - either utilize the 7.2v Nicad Battery or a DC power supply
  • CodeWarrior for Microcontrollers

1. Hardware


  The first step of this tutorial requires you read the Turn A Servo article for background information on servo's, timer modules, PWM signals and counters.

You will need to connect your servo to the microcontroller and also to a separate power source.

2. Create a New CodeWarrior Project


The next step is to create a new project (or add this code to an existing project).

3. Build the Code


If you have more than one project in your project view, make sure the proper project is the focus. The most reliable way to do this is to right click the project and choose Build Project as shown below. You can also go to the Project menu and choose the same command.

If you encounter errors, look in the Problems view and resolve them. You can ignore any warnings.

4. Download/Debug/Run


This link shows a video of the servo turning the wheels from left to right in small increments

5. Learning Step: Servo Code Description


Your code will sweep your servo from max to minimum angular position, and then back again continuously.

Example Code


This code sets up the Pulse Width Modulation Timer Module for use by a servo. It is set to utilize Edge-Aligned PWM, and this file properly configures the period, and pulse width for use by the other modules


Several important functions are contained in this file:
1. Init_PWM_Servo () - initializes the timer module
2. PWM_Servo (double duty_Cycle) - enter the desired duty cycle setting for the servo
3. PWM_Servo_Angle (int Angle) - enter the desired angle for the servo

  • Straight forward - PWM_Servo_Angle (45)
  • Full left - PWM_Servo_Angle (90)Full right - PWM_Servo_Angle (0)

  4. Servo_Tick - interrupt routine which executes once/servo period


PWM_Servo (double duty_Cycle)
Init_PWM_Servo ()
PWM_Servo_Angle (float Angle)
void ServoTick()


  • Pulse_Width_Low
  • Pulse_Width_High
  • Total_Count
  • Low_Count
  • Scale_Factor
  • Angle



Void Init_PWM_Servo ()



//Enable the Clock to the FTM0 Module

//Pin control Register (MUX allowing user to route the desired signal to the pin. 

//FTM0_MODE[WPDIS] = 1; //Disable Write Protection - enables changes to QUADEN, DECAPEN, etc. 

//FTMEN is bit 0, need to set to zero so DECAPEN can be set to 0
FTM0_MODE &= ~1;



//Set Edge Aligned PWM
//QUADEN is Bit 1, Set Quadrature Decoder Mode (QUADEN) Enable to 0,   (disabled)

// Also need to setup the FTM0C0SC channel control register
FTM0_CNT = 0x0; //FTM Counter Value - reset counter to zero
FTM0_CNTIN = 0; //Set the Counter Initial Value to 0

// FTMx_CnSC - contains the channel-interrupt status flag control bits
FTM0_C3SC |= FTM_CnSC_ELSB_MASK; //Edge or level select
FTM0_C3SC &= ~FTM_CnSC_ELSA_MASK; //Edge or level Select
FTM0_C3SC |= FTM_CnSC_MSB_MASK; //Channel Mode select

//Edit registers when no clock is fed to timer so the MOD value, gets pushed in immediately
FTM0_SC = 0; //Make sure its Off!

//FTMx_CnV contains the captured FTM counter value, this value determines the pulse width

//Status and Control bits
FTM0_SCFTM_SC_CLKS(1); // Selects Clock source to be "system clock" or (01)

//sets pre-scale value see details below

/******begin FTM_SC_PS details ****************************
* Sets the Prescale value for the Flex Timer Module which divides the
* Peripheral bus clock -> 48Mhz by the set amount
* Peripheral bus clock set up in clock.h

* The value of the prescaler is selected by the PS[2:0] bits. 
* (FTMx_SC field bits 0-2 are Prescale bits -  set above in FTM_SC Setting)

*  000 - 0 - No divide
*  001 - 1 - Divide by 2
*  010 - 2 - Divide by 4
*  011 - 3 - Divide by 8
*  100 - 4 - Divide by 16
*  101 - 5 - Divide by 32
*  110 - 6 - Divide by 64 -
*  111 - 7 - Divide by 128
*  ******end FTM_SC_PS details*****************************/

// Interrupts
FTM0_SC |= FTM_SC_TOIE_MASK; //Enable the interrupt mask.  timer overflow interrupt.. enables interrupt signal to come out of the module itself...  (have to enable 2x, one in the peripheral and once in the NVIC
enable_irq(62)// Set NVIC location, but you still have to change/check NVIC file sysinit.c under Project Settings Folder




Void PWM_Servo (double duty_Cycle)


     FTM0_C3V =  FTM0_MOD*(duty_Cycle*.01);







//PWM_Servo_Angle is an integer value between 0 and 90
//where 0 sets servo to full right, 45 sets servo to middle, 90 sets servo to full left
void PWM_Servo_Angle (float Angle)
   High_Count = FTM0_MOD*(Pulse_Width_High)*FTM0_OVERFLOW_FREQUENCY;
   Low_Count = FTM0_MOD*(Pulse_Width_Low)*FTM0_OVERFLOW_FREQUENCY;
   Total_Count = High_Count - Low_Count;
   Scale_Factor = High_Count -Total_Count*(Angle/90);  
   FTM0_C3V = Scale_Factor; //sets count to scaled value based on above calculations

Set Up a Look-Up Table for Servo Angles

int main(void)
  //Servo angles can be stored in a look-up table for steering the car.
  float table[n] = { steering_angle_0;
  Steering_Angle = table[x];
  PWM_Servo_Angle (Steering_Angle); // Call PWM_Servo_Angle function.

Other K40 Tutorials:


  1. K40 Blink LED Tutorial
  2. K40 DC Motor Tutorial
  3. Kinetis K40: Turning A Servo
  4. K40 Line Scan Camera Tutorial



Kinetis K40