8254定时器的使用说明与解读

标签:
定时器8254pwm |
分类: 技术与学术 |
下面这段英文详细讲解了使用8254定时器产生PWM信号的方法(这块内容仅涉及如何用高级语言如C、QBasic进行编程,并读写硬件的方法,但未涉及到Matlab与C协同产生PWM的内容。这一点将在英文后另有叙述。)
参考:http://www.boondog.com/tutorials/2993pwm/2993pwm.htm
8254定时器几大主要功能,与本文内容关系较为密切的是第一、二项功能:第一项是产生PWM信号;第二项是生成方波信号:
- create pulse-width-modulated (PWM) signals (e.g. for motor speed control)
- generate +5 V square waves
- count the number of times a switch toggles
- count pulses from a motor wheel encoder disk
- generate timed interrupts for analog-to-digital data acquisition
- implement a PC-controlled oneshot timer
- have a PC-controlled rate generator
- have fine resolution (e.g. 0.1 microsecond) timing instead of imprecise for...next delay loops
- The 8254 is Programmable...
This is the real power and flexibility behind the 8254. Because the 8254 was meant to be a one-chip solution, Intel designed it with 6 programmable modes, by identifying the most common timing/counting needs. The 6 modes are described in detail in the 8254 data sheet. They are
- Mode 0: Interrupt on terminal count
- Mode 1: Hardware retriggable one-shot
- Mode 2: Rate generator
- Mode 3: Square wave mode
- Mode 4: Software triggered mode
- Mode 5: Hardware triggered strobe
本教程主要以模式3为例,解读8254的用法。
·
Programming
With 6 programmable modes, your 8254 Card can answer almost any timing or counting problem you can conceive. The 8254 data sheet provides details on how to implement each of mode. Before programming, you will need to understand some preliminaries.
I. Preliminaries
A. Reading and Writing of Bytes(“读”和“写”硬件的基本指令,不同的语言有所区别,比如下面QBasic写指令是用OUT,而Turbo C用的是outportb。我们在后面用到的是outp。这一点需要特别注意!!!)
You can use any compiler you like (e.g. Turbo C, Quick Basic, Pascal, Visual Basic (with a DLL), Borland C, Microsoft C++). that allows allows the writing and reading of bytes to a port address. For example in QBasic you use:
OUT(portAddress, byteValue)
byteValue = IN(portAddress)
OUT writes byteValue (0 to 255 decimal) to the address defined in portAddress and IN reads the value from portAddress and stores it in the variable byteValue.
In Turbo C you use:
outportb(portAddress, byteValue)
byteValue = inportb(portAddress)
to accomplish the same thing. outportb() and inportb() are defined in the conio.h header file, so you must to #include it in your Turbo C program. For this tutorial we will use Turbo C to highlight programming in DOS and easy enough to translate into other languages. 读写指令包含在conio.h头文件中,所以无论是用什么方式编程,都要包含这个头文件。
B. The Base Address(对基地址的定义要特别小心,对于不同的硬件基地址是不同的。如果设置有误,不仅等不到正确的结果,而且有时还会引起很大的错误,如造成系统死机等。我们在后面用到的1711板卡的基地址是“0xc400”,通过板卡自带的Device Manager软件可以获得这方面信息。)
The Address Decoding section assigned your 8254 card with a unique address (608D). This is called the base address. Each counter also has an address:
int baseAddress, counter0, counter1, counter2;
baseAddress = 608;
counter0 = baseAddress;
counter1 = baseAddress + 1;
counter2 = baseAddress + 2;
one then does a outportb(counter0, counterValue) to write a value to counter0 or a counterValue = inportb(counter0) to read a value from counter0 . You do the same outportb() and inportb() if you need to select counter1 and counter2.
·C. Control Register(8254定时器的“控制字寄存器”。通过写这个寄存器的8位,可以控制寄存器的工作模式,定时器初值的读写方式等等。认真学习每一位的意义和用法!!特别是RW1和RW0两位!!在后面实例中我们定义这两位为“11”,即先写低8位[LSB],后写高8位[MSB]。)
The 6 programmable modes mentioned before are invoked by writing a 8-bit value to the control register. This is done as follows:
where the variable controlWord is determined with the following chart (Figure 9)
From Figure 9 we can see that the control word is an 8-bit binary number. There are 5 steps to calculate the proper control word number:
Step 1: Chose one counter (SC1 and SC0)
Step 2: Chose method to load (RW1 and RW0)
Step 3: Chose programming mode (M2, M1 and M0)
Step 4: Chose binary or BCD number (BCD).
Step 5: Convert the final binary word into decimal
Example: Suppose you want to make counter 0 a binary counter that generates square waves, and uses LSB and MSB read/write loading. What is the proper control word?
Figure 10 shows the answer. From Step 1, SC1 and SC0 both are 0 if you want to use counter 0. Step 2 say that LSB and MSB are both loaded. For square wave generation, you use Mode 3 and Step 3 says that M2,M1,M0 = 011. Step 4 makes BCD = 0 to have a binary counter. Thus the resulting binary number is 00110110 or, 54 decimal. Thus you would load the control register with controlWord with 54:
10110
controlRegister = baseAddress + 3;
outportb(controlRegister, 54);
上面一条指令是写控制字寄存器,设定counter0工作于模式3。其中“54”是十进制,转化为二进制是“00110110”,即写入的控制字。
D. LSB and MSB(低8位和高8位的概念,不明白的好好看看!!)
All 3 counters are 16-bits. A byte is 8-bits long, hence each timer is 2-bytes. This means that each counter can have values ranging from:
0000000000000000 (16 zeros) to 1111111111111111 (16 ones) in binary, or 0 to 65535 decimal. ISA is an 8-bit data bus and can read or write only one byte at a time. Thus to read or write a 16-bit value, you must do so one byte at a time.
The lower and higher 8-bit numbers are called least and most-significant bytes (LSB, MSB) respectively. For example, to load counter0 with 38370 decimal, the LSB is 226 decimal, and its MSB is 149 decimal (Figure 11).
http://s16/middle/625c01d6g9e9191f15b4f&690
The control word's RW1 and RW0 setting tells the
8254 that you will read or write 16-bit byte values with the LSB
first followed by
outportb(counter0, 226); outportb(counter0, 149);
先写第八位,再写高八位。这一点也要特别注意!!!
There might be cases where you only want to read
or write the LSB or MSB.
E. Counter Reading and/or Writing
By reading the counter value you can determine how many pulses it has received. Rather than counting upwardly (0,1,2..., 65535), the 8254's counters by default, count downwardly (65535, 65534...,0). In many of the programming modes, the counter will wrap around and start at 65535 once it has reached 0.
You can give a counter a preset value to start
counting down from by writing this value to it.
For timed applications, using a 1.0 MHz
oscillator, each count takes 1 microseconds (usec).
You now may know see the significance of using the
74HC393. By changing jumper positions you can easily drive the
counter with a different frequency.
Frequency time/count
1.0 MHz 1 usec
500 KHz 2 usec
250 KHz 4 usec
125 KHz 8 usec
62.5 KHz 16 usec
II. The Code
With the preliminaries out of the way, 3sqwave.c . is a short Turbo C program that allows the user to select a counter and frequency to generate square waves. A useful application of this code is to drive a stepper motor. Many dedicated stepper motor chips (such as Allegro Microsystems 5804) require a square wave, thus you can extend the code to run a stepper motor.
The program begins by defining crystalValue with
1.0 MHz.
Each counter is then configured in Mode 3 (square wave) as a binary counter with LSB and MSB loading. This makes the control word 54, 118 and 182 decimal (see Figure 9).
During program execution the user is then promped to select a counter (0, 1 or 2) and its gate, (gateNumber) is then assigned.
The user is then asked to enter a
frequency.
As you can see programming the 8254 is not very complicated. The 8254's other modes can be programmed similarly.
Final Words
This tutorial provides a solution to many timing and counting needs required in PC interfacing. By building the 8254 circuit on an ISA card, one can have a very powerful, flexible and high resolution timer.
Program mode 3 was illustrated to demonstrate the
8254 card's squave wave generating ability.
1. (Available 06/14/99) A motor speed control using pulse-width-modulation
2. Counting motor revolutions
3. Stepper motor application
4. Running servo motor