Lecture Notes 4
Lecture Notes 4
• The simplest type of I/O via the PIC24 µC external pins are
parallel I/O (PIO) ports.
• A PIC24 µC can have multiple PIO ports named PORTA, PORTB, PORTC,
PORTD, etc.
• Each is 16-bits, and the number of PIO pins depends on the particular PIC24 µC
and package.
• The PIC24HJ128GP502/28 pin package has:
• PORTA – bits RA4 through RA0
• PORTB – bits RB15 through RB0
• These are generically referred to as PORTx.
• Each pin on these ports can either be an input or output – the data direction
is controlled by the corresponding bit in the TRISx registers (‘1’ = input, ‘0’ =
output).
• The LATx register holds the last value written to PORTx.
PIC24HJ128GP502 Pin Diagram
TRISB = 0x00FF;
Drive RB15, RB13 high;
others low:
Write to LAT/PORT
PORTx Pin Diagram (read from LAT)
Compiler
_RB0 = 1; bset PORTB,#0
Y A Y
A
OE
OE
OE = 0, then switch closed
OE = 1, then switch open
Schmitt Trigger Input Buffer
Each PIO input has a Schmitt trigger input buffer; this transforms slowly
rising/falling input transitions into sharp rising/falling transitions internally.
PORTx Shared Pin Functions
External pins are shared with other on-chip modules. Just setting _TRISx = 1
may be not be enough to configure a PORTx pin as an input, depending on
what other modules share the pin:
RB15 shared with AN9, which is an
analog input to the on-chip Analog-to-
Digital Converter (ADC). Must disable
analog functionality.
• Other macros are provided for pull-up and open drain configuration:
ENABLE_RB15_PULLUP();
DISABLE_RB15_PULLUP(); Output + Open drain config
ENABLE_RB13_OPENDRAIN(); in one macro
DISABLE_RB13_OPENDRAIN();
CONFIG_RB8_AS_DIG_OD_OUTPUT();
• General forms are:
ENABLE_Rxy_PULLUP()
DISABLE_Rxy_PULLUP(),
ENABLE_Rxy_OPENDRAIN(),
DISABLE_Rxy_OPENDRAIN()
CONFIG_Rxy_AS_DIG_OD_OUTPUT()
• A port may not have a pull-up if it does not share the pin with a change
notification input, in this case, the macro does not exist and you will get an error
message when you try to compile the code.
Microstick II Simplified Schematic
A red LED with a 470W
resistor is connected to
pin RA0
#include "pic24_all.h"
/// LED1
#define CONFIG_LED1() CONFIG_RB14_AS_DIG_OUTPUT()
#define LED1 _LATB14 //led1 state
• Defined in c:\microchip\lib\common\pic24_util.c
• Modified for use with Microstick II and putty terminal emulation program
• Our new approach is periodically sampling the switch every ~15 ms in the
while(1) loop
• In the first solution, we were reading the switch as fast as the PIC24 could
loop
• We want this sampling period to be longer than any switch bounce settling
time, and we want it to be short enough that we do not miss a switch press
entirely
• A human switch press is at least greater than 50 ms, so 15 ms is short enough
Software-Based Finite State Machines
#include "pic24_all.h"
/*
A program that uses a finite state machine approach for toggling an LED
whenever a pushbutton switch is pressed and released. Demonstrates the
use of debounce delays when polling a switch input.
*/
/// LED1
#define CONFIG_LED1() CONFIG_RB14_AS_DIG_OUTPUT()
#define LED1 _LATB14 // led1 state
STATE e_lastState = STATE_RESET; // print debug message for state when it changes
void printNewState (STATE e_currentState) {
if (e_lastState != e_currentState) {
Function to print the current
switch (e_currentState) { state whenever a state
case STATE_WAIT_FOR_PRESS: change occurs
outString("STATE_WAIT_FOR_PRESS\n");
break;
case STATE_WAIT_FOR_RELEASE:
outString("STATE_WAIT_FOR_RELEASE\n");
break;
default:
outString("Unexpected state\n");
break;
C Code Solution (continued)
State variable used for
tracking the current state
int main (void) {
STATE e_mystate;
Initialize
/** Toggle LED each time switch is pressed andstate variable
released to the
******************/ first state
e_mystate = STATE_WAIT_FOR_PRESS;
C Code Solution (continued)
while (1) {
printNewState(e_mystate); // print debug message when state changes
switch (e_mystate) {
case STATE_WAIT_FOR_PRESS:
if (SW1_PRESSED()) e_mystate = STATE_WAIT_FOR_RELEASE;
break;
Finite state machine
case STATE_WAIT_FOR_RELEASE:
implemented with a switch
if (SW1_RELEASED()) {
statement within an infinite
LED1 = !LED1; // toggle LED while() loop
e_mystate = STATE_WAIT_FOR_PRESS;
}
break;
default:
e_mystate = STATE_WAIT_FOR_PRESS;
}// end switch(e_mystate)
DELAY_MS(DEBOUNCE_DLY); // Debounce
// doHeartbeat(); // ensure we are alive, not used in
Sample output to putty (across serial port)
A More Complex Problem
C Solution (configuration)
Original file c:\microchip\chap8\ledsw1.c
#include "pic24_all.h"
/// LED1
#define CONFIG_LED1() CONFIG_RB14_AS_DIG_OUTPUT()
#define LED1 _LATB14 // led1 state
configBasic(HELLO_MSG);
case STATE_BLINK:
LED1 = !LED1; // Blink while not pressed
DELAY_MS(100); // Blink delay
if (SW1_PRESSED()) e_mystate = STATE_WAIT_FOR_RELEASE3;
break;
case STATE_WAIT_FOR_RELEASE3:
LED1 = 1; // Freeze LED1 at 1
if (SW1_RELEASED()) e_mystate = STATE_WAIT_FOR_PRESS1;
break;
default:
e_mystate = STATE_WAIT_FOR_PRESS1;
} // end switch(e_mystate)
DELAY_MS(15); // Debounce
} // end while (1)
}
Console Output for LED/SW Problem