骏豪地产集团有限公司:Introduction to Embedded Prog

来源:百度文库 编辑:九乡新闻网 时间:2024/05/06 17:11:57

GPIO (General Purpose Input/Output) Inputs

A GPIO pin configured as an input is used to read (to input) thevalue of one digital signal.  In this case the pin is converting thevoltage being delivered to the pin into a logical value of 0 or 1 forsubsequent use in the program.  By convention, when the voltage on thepin is “high” (near Vcc), reading the pin will result in reading alogic 1, while when the voltage is “low” (near GND), reading the pinwill result in reading a logic 0.  Let’s talk a little bit more aboutwhat is an acceptable “high” voltage and an acceptable “low” voltage. Simply put, if your high voltage is too high (too far above Vcc), oryour low voltage is too low (too far negative with respect to GND), youwill probably damage your chip.  On the other hand, if your highvoltage isn’t high enough or your low voltage isn’t low enough, thechip will not reliably read the input value correctly.  To illustratesome example numbers, here are the required input range values for atypical microcontroller, as taken directly from the “ElectricalCharacteristics” section of the datasheet:

High input: 0.6Vcc to Vcc+0.5
Low input: -0.5 to 0.3Vcc

Thus if your Vcc is 5V, a valid “high” is 3 to 5.5V and a valid“low” is -0.5 to 1.5V.  If your input is connected to a standard outputpin of another digital chip using the same Vcc you will get validinput voltages without any extra effort.  However, when your input isconnected to some other hardware, or to chips running off of differentsupply voltages, the circuitry must be designed to guarantee that theinput voltage levels are within spec. To allow yourself good noisemargins (that is, margins where noise on the input does not drive theinput voltage out of the valid '1' or '0' range), use the 10% rule: aimfor highs ('1s') near Vcc (between Vcc and Vcc-10%) and lows ('0s') nearGND (between GND and GND+10%), where 10% refers to 10% of the Vccvalue.

 

What does it mean to “read” an input?

Reading an input means that your program executes an instructiondesigned to bring the logical value of the voltage present on the inputpin into the CPU as a data bit.  Any μC will have one or moreinstructions which can read an entire processor word (being N bitswide) into the CPU.  Thus an 8-bit μC will have instructions to read 8bits of input pin data into the CPU.  A 16-bit μC will haveinstructions to read 16 bits of input data, and may also haveinstructions to read 8 bits (it is common for CPUs with word widthsgreater than 8 bits to also have 8-bit data transfer instructions, since8-bit data is so common).  And, not surprisingly, a 32-bit μC willhave instructions to read 32 bits of input data, and may also haveinstructions to read 8 bits of data. 

Perhaps you noticed that we’ve gone from talking about reading asingle input (one bit) to reading fields of 8, 16 or 32 bits.  But veryoften we really do just want to read that one bit, so what do we do? In that case you can use the logic instructions of the μC to isolate asingle bit from a field of N bits:

Many microcontrollers also have special instructions for readingand writing single bits.  This is one example of the type ofinstruction a μC is more likely to have than a traditionalmicroprocessor.  When writing your program in assembly language youhave direct access to these instructions.  When writing in C oranother high level language, you may be able to access theseinstructions by using compiler-specific directives to embed assemblerinstructions into your program.  A good compiler may also be able torecognize suitable HLL statements and translate them into sequences ofthese special instructions.  The important thing is that, one way oranother, it is a simple task to isolate the state of a single bit from amulti-bit field.

 

GPIO state on power-up and reset

Any time a microcontroller is reset (including on power up), allthe GPIO pins will be configured as inputs.  To configure any GPIO pinas an output requires that the software execute specific code tochange the default input configuration once the device program startsrunning.  This reconfiguration will typically not happen until sometens or hundreds of milliseconds after power is applied.  This meansthat anytime the device is reset, all hardware that is connected topins which are intended to be outputs must be able to handle the factthat the device pins are inputs.  For example, if a GPIO pin isconnected to a logic gate input then that GPIO pin would configured inthe program as an output, but for a brief time on reset the logic gateinput would not be driven by an output.  In some cases this briefinput-that-should-be-an-output state doesn’t matter, but in many othersit matters a great deal and precautions must be taken in the circuitdesign to deal with this time when outputs are really inputs.  Just togive one example, imagine a uC output pin that triggers an automobileairbag.  If the brief invalid state of that pin on reset is not handledcorrectly in the hardware, the result could be all the airbags goingoff the instant the key is turned!

 

Pullup and pulldown resistors

An important rule in handling digital inputs is that they shouldnever be left floating – that is, left unconnected.  If an input isunused it must still be connected to a valid input voltage, which couldeither be near GND or near Vcc.  Such an input can be connecteddirectly to GND or Vcc, but in many cases there is good reason toconnect the input to GND or Vcc through a resistor instead.  Such aresistor is called a pullup resistor if it is connected to Vcc, or apulldown resistor if connected to GND.  Obviously we know the voltageon one end of the resistor (the Vcc or GND end).  But by Ohm’s Law wecan only know the voltage at the pin if we know the current through theresistor – that is, the current flowing into or out of the pinitself.  It turns out than every μC or other digital device data sheetwill give you this important information.  Here is the input currentdata for an ATmega48 and a 9SP12:

ATmega48: 1uA


If we pick a pullup (or pulldown) resistor of e.g. 10kOhms, we geta voltage drop across the resistor of 10mV for the ATmega48 and 100mVfor the 89C51.  This gives μs an input voltage of (Vcc-0.01) for theATmega48 and (Vcc-0.1) for the 89C51.  These values are very comfortablywithin the allowed range of input voltage for a “high”, so they willbe read as a solid ‘1’ by the chip, which is what we want when we use apullup (pulldown) resistor.

Now why did we go to this trouble when we could have just wired thepin directly to Vcc or GND?  One reason is that, especially during thesoftware development phase, an error may result in an input pinmistakenly configured as an output.  An ouput pin wired to e.g. Vcc andset to ‘0’ (low voltage) is a conflict that could easily damage yourchip, as the poor output transistor on the chip essentially trys toshort out the power supply.  With a pullup or pulldown resistor on thepin, no damage can occur if the pin is mistakenly wired as an output,because the resistor limits the possible current flow to a value thatis safe for the μC.  Another reason, also more important in thedevelopment phase, is that you may find you need another input youhadn’t counted on.  If the unused input is wired directly to Vcc orGND you’ll have to first cut (literally) that connection before usingthe pin as an input.  But if the unused input is connected to a pullupor pulldown, you can use the input without disconnecting the resistoror cutting any traces.  This is because the output driving the inputwill be able to override the pullup or pulldown, and drive the input tothe desired state.

What is the allowable range of pullup/pulldown values?  Again,Ohm’s Law, combined with the limits given on the device datasheet, giveμs the answer.  On the low side, the lowest resistor value is the onethat will limit the current through the resistor to a value low enoughthat the output driving that resistor is within its allowed rating. Thus if a typical digital output can drive 4mA (the specification ofthe 74HC logic family), for a Vcc of 5V the minimum resistor value is5V/4mA or 1250 Ohms.  A more prudent minimum resistance might be 1800or 2200 Ohms in this case.  On the high side, the maximum value mustguarantee that, with the maximum leakage current flowing through theresistor, the input value is within range.  For modernlow-leakage-current inputs, this resistance value can be quite large. 1.5V/1uA = 1.5MegOhm.  This is an very high value for digital circuitryand one that would not typically be used in an actual circuit.  A valuein the range of perhaps 4.7k to 100k would be more suitable, withvalues higher than this not gaining you anything unless you arestriving for the lowest possible power consumption.  Otherwise, if youwant to remember just a single number, a value of 10k for your pullupsand pulldowns should be suitable for modern devices in mostcircumstances.  A 10k resistor will pull an input very close to therail (Vcc or GND), but is also easy for an output signal to override(requiring the output to source or sink only 0.5mA in a 5V design, lessin a lower-voltage design).

This discussion on pullups/pulldowns should help to remind youthat every input and every output has electrical limits that must beobserved if the circuit is to be reliable, or even function at all.

 

Reading switches and buttons

Switches and buttons are, needless to say, very common inembedded systems.  Switches are current devices – open they allow nocurrent flow, closed they do allow current flow.  Since our input pinsrespond to voltage, not current, we need to convert ourcurrent-controlling switches to voltage signals.  As it turns out thisis extremely simple to do, requiring only the addition of a singleresistor (which in many cases is already built in to the μC).  Infact, interfacing switches is one of the main uses of pullup/pulldownresistors. 

A switch can be connected to a GPIO input in either of two ways,as shown below.  Of the two arrangements, connecting the switch to GND(Fig. A) is usually preferred.  We will first examine the case of aswitch and a pullup resistor.  When the switch is open the pullupresistor is doing what pullup resistors do, pulling the input to avalid “high” state.  Thus when the switch is open the input will read a‘1’.  Now close the switch and, clearly, the voltage at the inputdrops to zero.  The switch is now passing to GND the current flowingthrough the pullup resistor, as well as the input current.  When theswitch is closed, the input will read a ‘0’.  The fact that anunclosed switch / unpressed button will read ‘1’ and a closed switch /pressed button will read ‘0’ is counterintuitive to many, but it issimply a consequence of wiring one end of the switch to GND.  It is nota problem at all – your software simply has to recognize that an openswitch reads as a ‘1’ and a closed switch reads as a ‘0’.

One can also use a pulldown resistor and wire the switch to Vccrather than GND.  Now when the switch is open the pulldown resistorcauses the input to read ‘0’, and when the switch is closed the inputreads ‘1’.  This arrangement should only be used when an open switch(or disconnected output, see section XYZ) must be read as a ‘0’.  Oneexample when this may be necessary is in a RESET input, which areusually active-low.  There may be times when a loss of input to theRESET line must result in the device being RESET, to prevent invalidoperation.  In this case the pulldown resistor will perform thatfunction.

In the drawing below, diagram A shows a switch wired with apulldown resistor, and diagram B shows a switch wired with a pullupresistor. The input signal in diagram A is active-high (the input willgo high when the switch is closed) and the input signal in diagram B isactive-low (the input will go low when the switch is closed).

 

Connecting a Switch to an Input

 

A problem – switches are not perfect and microcontrollers are very fast

You might think that throwing a switch from closed to open oropen to closed was a simple matter, but things aren’t that easy.  Amechanical switch will actually bounce a number of times in themilliseconds it takes to settle.  This bouncing is insignificant inhuman time frames, but a μC that is executing millions of instructionsper second will have no trouble reading each of these switch bounces asa new switch event.  Thus one pushbutton press can register to thesoftware as dozens of presses and releases.  This is almost always a BadThing, and therefore in most cases your software should be designed toignore the switch bounces while still reading the overall change ofswitch state from open to closed or closed to open.  That’s just a longway of saying that what is intended to be a single switch changeshould indeed be seen by the software as a single switch change.

There are a number of ways to debounce a switch.  One way is touse hardware to filter out the brief (high frequency) pulses generatedby switch bounce.  This makes the software easy (it can ignore theproblem of switch bounce completely), but it makes the hardware morecomplicated and more expensive, since additional components must beincorporated.  For this reason, switch debouncing is commonly done insoftware rather than hardware.  Two methods of debouncing switches insoftware are (a) after detecting a switch event, wait long enough forthe switch to stop bouncing, or (b) after detecting a switch event,wait for a pre-established number (N) of consecutive matching switchreads.  The first method explicitly relies on a time interval to ignoreany bounce, while the second method implicitly relies on a timeinterval, specifically, the time it takes to read the switch state Ntimes.  Examples of both methods are given below.