Setting up and utilizing a DMA timer to measure frequency

Post your example source code and application notes to share with others
Post Reply
User avatar
Forrest
Posts: 263
Joined: Wed Apr 23, 2008 10:05 am

Setting up and utilizing a DMA timer to measure frequency

Post by Forrest » Tue Jul 28, 2009 1:29 pm

Using a DMA timer to measure frequency application note

Introduction

The 32-bit Direct Memory Access (DMA) timers can be used to measure input by comparing the system clock when you begin the timer and when you exit the timer. It can also measure input through DTIN. We will be providing the input we want to count, so we will use DTIN in this example. Using this method, you can measure the frequency of an incoming signal. In this example, we will be measuring the frequency of light using a light->frequency IC, along with a MOD5282 module.

This example source can be ported to any module with a dma timer, but the example source may vary depending on module. The methods described in step 2 will help you port this to any module.

This application note has 3 steps that we will cover.

1. Attaching the hardware
2. Referencing the Motorola Processor Manual to set up the timer
3. Reading the output

Parts List

Part Name
Part Code
Supplier
Price

NetBurner MOD5282 Development Kit
NNDK-MOD5282-KIT
http://www.netburnerstore.com
$299

TSL230R Light Intensity to Frequency IC
SEN-08940
http://www.sparkfun.com
$5.95

Attaching the hardware

The TSL230R
ImageImage

To make the code easier to read and easier to understand, I like to define the MOD5282 pins I am going to be using to be the same as the pins on the TSL230R. A few define statements will do this:

Code: Select all

#define s0 (J2[30]) // SPI CS0 / GPIO
#define s1 (J2[40]) // SPI CS1 / GPIO
#define s2 (J2[35]) // SPI CS2 / GPIO
#define s3 (J2[26]) // SPI CS3 / GPIO
#define in (J2[31]) // Analog i/o ch0
As you can see in the code above, the pins that we need should now be plugged into the module. In addition the the connections specified, you should also connect ~OE to GND, GND to GND, and Vdd to VCC. I used some simple, removable wiring to accomplish this. You could also solder the connections onto the prototype area of your carrier board.

Image
Image

Since many of the pins are dual use on the NetBurner module, you should now specify in code that you will be using the pins as GPIO and DTIN0.

Code: Select all

    s0.function(PIN_GPIO);
    s1.function(PIN_GPIO);
    s2.function(PIN_GPIO);
    s3.function(PIN_GPIO);
    in.function(PINJ2_31_TIN0);
s0->s3 are programmable input pins into the TSL230R. Reviewing the data sheet for the TSL230R, we discover that these pins allow us to program the sensitivity and scaling of the device.

Image

Code: Select all

    s0 = 1;
    s1 = 1;
    s2 = 0;
    s3 = 0;
I set my options to no scaling and maximum (100x) sensitivity. With the hardware set up, we now need to set up our timer.

Referencing the Motorola Processor Manual to set up the timer

When accessing features of the module processor, it is important to know how to read the reference material. You can always download your module's reference manual at http://www.netburner.com. From the homepage:

Image

Within the MOD5282 product page, select the Freescale Coldfire MCF5282 Manual:

Image

You now have the full power of the MCF5282 User Manual in your hands, or, rather, in your screen.

Since we will be using the DMA timer, scroll through the table of contents to find where the DMA Timer section starts:

Image

Scroll to this section. This is your guide to the DMA timer. The manual typically offers an introduction, features overview, and then gets in to the memory map to configure/read the timer.

NetBurner makes it easy to write to and read these memory maps through use of your module's sim file. Open up sim5282.h in c:\nburn\mod5282\system to follow along. The relevant code is below:

Code: Select all

typedef struct {            /* DMA Timer Module */
   vuword  tmr;             //      0x00 ->      0x01 - DMA Timer Mode Register
   vubyte  txmr;            //      0x02 ->      0x02 - DMA Timer Extended Mode Register
   vubyte  ter;             //      0x03 ->      0x03 - DMA Timer Event Register
   vudword trr;             //      0x04 ->      0x07 - DMA Timer Reference Register
   vudword tcr;             //      0x08 ->      0x0B - DMA Timer Capture Register
   vudword tcn;             //      0x0C ->      0x0F - DMA Timer Counter Register
   vubyte  pack00[48];      //      0x10 ->      0x3F - RESERVED
} timerstruct;              /* 0x00_0400 -> 0x00_04FF - For array timer[4] */
As you can see, a structure is created that corresponds to the memory map described in the MCF5282 manual. Once you include sim.h in your nbeclipse project, you can access this structure with

Code: Select all

sim.timer[0].tmr = // value; 
You may have noticed that timerstruct became timer. If you look further down sim5282.h, you will find it defined to timer when the mcf5282 structure is defined. You also noticed that timer[0] is used. We have 4 timers available, we will only be using the first in this example.

Back to the DMA Timer initialization. In section 21.2.6, you will find the DMA Timer mode registers. This will need to be written to to initialize the timer.

Image

Looking at this chart, we will configure timer[0] to count falling edges read from the DTIN0 pin.

Code: Select all

    /*			Timer0 Configuration
     *  [PS]	- 0x00		No Prescaling
     *  [CE]	- 00		Disable capture event output - Not used
     *  [OM]	- 0			Not using this
     *  [ORRRI]	- 0			Not using interrupts
     *  [FRR]	- 0			Timer continues to increment
     *  [CLK]	- 11		Measuring falling edges on DTIN0 pin
     *  [RST]	- 1			Enable Timer
     *  		
     *  		= 0x0007 
     */
    
    sim.timer[0].tmr = 0x0007;
Reading the Output

Now that the module is connected, and the timer0 is initialized, it's time to read output. To get the frequency, we must sample the DTIN0 line for 1 second, counting all the falling edges. Because this example operates without interupts or tasks, I opted to only sample 250ms, and then multiply the result by 4. This will reduce accuracy somewhat.

Code: Select all

DWORD readIn() {
	DWORD buffer = TimeTick; // Buffer holding current TimeTick
	while (buffer+1 > TimeTick);
	sim.timer[0].tcn = 0;
	while (buffer+1+5 > TimeTick);
	buffer = sim.timer[0].tcn; // Buffer holding frequency
	return (buffer*4);
}
The readIn() function first syncs to the value of TimeTick. We will use TimeTick to know when our sampling time starts and ends. Within the while statement, we wait for the next TimeTick to occur to start the sample. This puts us on the leading edge of the TimeTick variable. We then wait for 5 ticks to occur. We are using the default TICKS_PER_SECOND = 20, so 5 ticks = 250ms. Once our sample time has ended, we save the amount of falling edges counted on DTIN0 to buffer. This buffer is multiplied by 4 to give us the frequency of the input.

Once we have the frequency, displaying the frequency is a simple iprintf statement.

Code: Select all

    	iprintf("freq: %8d\r",i);
Open up MTTTY to see your results!

Image
Attachments
TimersAndTSL230R.zip
Download the source file used to run this application
(1.11 KiB) Downloaded 338 times
Forrest Stanley
Project Engineer
NetBurner, Inc

NetBurner Learn Articles: http://www.netburner.com/learn

User avatar
yevgenit
Posts: 84
Joined: Fri Apr 25, 2008 12:47 am
Contact:

Re: Setting up and utilizing a DMA timer to measure frequency

Post by yevgenit » Thu Apr 08, 2010 7:57 am

Accuracy of counting frequency can be significantly improved by using the hardware-timed counting interval instead of the software-timed.
Such hardware-timed interval can be implemented with system clock timebased pulse at DTOUT pin of the second DMA timer. This DTOUT pin needs to be tied to DTIN pin of the first timer. The first timer needs to be configured to capture its counter by both rising and falling transition at its DTIN pin.
Yevgeni Tunik
Embedded/RealTime software engineer
http://il.linkedin.com/in/yevgenitunik
________________________

Post Reply