Setting up digital IO in Dynamic C for Rabbit 4000 boards and newer?

Note: This information is general to the Rabbit 4000 and certain pins may not be available on your product.

The first thing I want to do is to point you to our Rabbit 4000 Processor Easy Reference Poster: http://ftp1.digi.com/support/documentation/0230125_b.pdf

The poster shows all the registers you need to set and makes it pretty easy to find what you need.

In the center of the poster is a description of the Parallel Ports and the registers associated with each one. For more specific details on the Parallel Ports, you will want to look here: 
http://ftp1.digi.com/support/documentation/019-0152_N.pdf

Using the digital I/O on the Rabbit products isn’t difficult but is easier to do after looking at an example. Let’s step back for a moment and consider a simpler problem like lighting up two LEDs on Parallel Port D.

You could hook the LEDs directly up to PD4 and PD5 and use pull-up resistors with the LEDs like this.
+5 Volts ------/\/\/\/\------- LED1 ----------PD4
+5 Volts ------/\/\/\/\------- LED2 ----------PD5
(I would recommend a 330 Ohm or bigger resistor.)
With the LEDs hooked up as above, you should be able to use this code to light both LEDs.
/************************************************************/
#define ON 0
#define OFF 1 
main()
{
  WrPortI(PDDCR, &PDDCRShadow,0); // make D driven high and low (see manual for details)
  WrPortI(PDDDR, &PDDDRShadow, 0xFF); //make D output (see manual for details)
  BitWrPortI(PDDR, &PDDRShadow, ON,4); // PD4 becomes GND and LED lights up
  BitWrPortI(PDDR, &PDDRShadow, ON,5); // PD5 becomes GND and LED lights up
}
/************************************************************/ 

PDDCR = Port D Drive Control Register (Use this to set open drain)
PDDDR = Port D Data Direction Register (Use this to define input or output)
PDDR = Port D Data Register (Use this to actually send the data)
 
This provides a very basic example of the digital I/O of a Rabbit microprocessor. 
Full details on Parallel Port D (and more) can be found in the Rabbit 4000 Microprocessor User’s Manual here:
http://ftp1.digi.com/support/documentation/019-0152_N.pdf 

After looking over this example, you should be able to do more complicated things.
Parallel Port A is configured byte-wise. That means that all ports are either inputs or outputs and there cannot be a combination. Port A is unique in this respect and the other ports can have inputs and outputs on the same port.
TheWrPortI is used to write a value to a register and it needs three parameters.
WrPortI(SPCR, &SPCRShadow,0x84);

Parameter1 - The register you wish to change 
Parameter2 - The shadow register of the register you wish to change
Parameter3 - The value to write to the register

With any Port except Port A, you could also use BitWrPortI to configure a single bit on the port. (Remember that Port A is configured byte-wise.)
BitWrPortI(PGDR, &PGDRShadow, 1,0);

Parameter1 - The register you wish to change
Parameter2 - The shadow register of the register you wish to change
Parameter3 - The value to write to the register
Parameter4 - Which bit you wish to change
 
Questions:
1)Does this mean that I cannot use any of the A ports as inputs?
This means you can use all the pins on Port A as inputs OR outputs, but not both.

2)If I wanted to use pins on port B as well or another port as outputs, what is the equivalent line command like the above that configures port B or another port as output?
PortA looks a little funny because the register is named Slave Port ControlRegister (SPCR). The other ports use a "Data Direction Register" toset the direction of the data.
PortA - No register to specifically control bits (Use SPCR for byte-wise)
PortB – PBDDR
PortC - PCDDR (Pins used for serial lines)
PortD - PDDDR
PortE - PEDDR

3)With the above line command in the code, can I intermix inputs and outputs on the same port? For example PA0 = output, PA3=input,….
You won't be able to use BitWrPortI to set up individual inputs and outputs on PortA as we discussed earlier. When
you want to set individual bits to inputs and outputs on a port that will allow that, you can use BitWrPortI to do it.
 
In the code here I have set the Port E Data Register (PEDR). The value is "1" and the pin number is "0". This code would continuously toggle the data bit:

while(1)
{
  BitWrPortI(PEDR, &PEDRShadow, 1,0); // Set PE0 to value 1
  BitWrPortI(PEDR, &PEDRShadow, 0,0); // Set PE0 to value 0
}
 
5)What does the 0x84 mean?
The value is a hexadecimal number and we use that system because it makes it easier to read the bits at a glance. Take a look at this table:
 
Hex Binary
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
A 1010
B 1011
C 1100
D 1101
E 1110
F 1111

Each hexadecimal digit is 4 bits and two digits gives us a full byte.
Some examples:
0x00 = 0000 0000
0x40 = 0100 0000
0xAC = 1010 1100
0x84 = 1000 0100

This statement WrPortI(SPCR, &SPCRShadow, 0x84) writes "1000 0100" to the bits of the SPCR register.
Looking at the Easy Reference Poster, I look at SPCR in the middle of the poster under SLAVE PORT to see how to set the bits.
Bit7 - 1 (ignore smode pins)
Bit6 - 0 (ignored for Write)
Bit5 - 0 (ignored for Write)
Bit4 - 0 (Disable slave port -port is byte-wide input)
Bit3 - 0 (Disable slave port -port is byte-wide input)
Bit2 - 0 (Disable slave port -port is byte-wide input)
Bit1 - 0 (Priority 2 interrupt)
Bit0 - 1 (Priority 2 interrupt)

Here's an example of how to setup Port D to toggle an output.
/************************************************************/
#define ON 0
#define OFF 1
main()
{
  WrPortI(PDDCR, &PDDCRShadow, 0); //make D non-open drain
  WrPortI(PDDDR, &PDDDRShadow, 0xFF); //make Port D an output
  BitWrPortI(PDDR, &PDDRShadow, ON,4); //PD4 becomes GND
  BitWrPortI(PDDR, &PDDRShadow, OFF, 4); // PD4 becomes High
}
/************************************************************/
 
PDDCR= Port D Drive Control Register (Use this to set open drain)
PDDDR= Port D Data Direction Register (Use this to define input or output)
PDDR= Port D Data Register (Use this to actually send the data)

Notice I used WrPortI to set everything at once on Port D as an output?
0xFF= 1111 1111 and passes a 1 to every pin on Port D making everything an output. I could have used BitWrPortI to set just one pin on Port D as an output as well.
BitWrPortI(PDDDR, &PDDDRShadow,1, 4); // Set PD4 as output

If you want to read from a parallel port use
BitRdPortI(PDDR,4); //read from PD4
Or
RdPortI(PDDR); //read the entire 8 bits
Last updated: May 24, 2019

Filed Under

Embedded

Recently Viewed

No recently viewed articles

Did you find this article helpful?