Parallel data bus

Hi:

I'm trying to make a parallel data bus in Arduino UNO in order to conect it to and ADC0807 (8 bits). I've searched on several sites and forums with no luck.

Explicitly, what I'm trying to do (as part of a bigger project) is to read a value from analogpin(0) and the send that value (in binary) to a data bus connected to the ADC0807 in order to get the a value on the ADC0807 output. It may sounds dumb but the analog reading is going thru a series of calculations and the output value wont be the same that the analogpin(0).

Hope you can help me or at least guide me in the right direction.

Thanks in advance.

You need to look up “direct port manipulation.”

Each pin on the board is connected to an 8-bit group called a port. You could assign the appropriate port an 8-bit value. For example, PORTD are pins 0 through 7.

So after you configure the pins for output,

PORTD = 0x55;

That would cause the pins to alternate HIGH / LOW. (0101 0101)

If you look at the schematic for the Uno, you’ll see the pins in the ATmega328 have a “Pxy” designator. X is the letter of the port and Y is the bit of that port.

The downside to using PORTD is that it’s also Pins 0/1 which are responsible for USB/Serial communication.

I would use a shift register (SPI) to send a byte out in parallel. It is difficult, on the Uno, to control 8 pins as a parallel port (unlike say 8051). Only 2 or 3 wires and SPI is very fast (4MHz). Direct port manipulation is a way but since all three ports have pins with extra functions (tx,rx, xtal1, xtal2) you have to deal with that.

Thanks for the fast reply!

On this section:

PORTD = 0x55;

That would cause the pins to alternate HIGH / LOW. (0101 0101)

Isnt the "55" supposed to be 110111? or the number 0101 0101 refers to a different matter?

Provide a link to the data sheet for the chip your using.

Mark

Gilgamesh90: Thanks for the fast reply!

On this section:

PORTD = 0x55;

That would cause the pins to alternate HIGH / LOW. (0101 0101)

Isnt the "55" supposed to be 110111? or the number 0101 0101 refers to a different matter?

A friend of mine told me about converting to binary the number that is read on the analogpin(0) then send each digit of that number to an array and then send each slot of that array to a pin. Isnt that an easier method? Is it possible?

Gilgamesh90:

Gilgamesh90: Thanks for the fast reply!

On this section:

PORTD = 0x55;

That would cause the pins to alternate HIGH / LOW. (0101 0101)

Isnt the "55" supposed to be 110111? or the number 0101 0101 refers to a different matter?

A friend of mine told me about converting to binary the number that is read on the analogpin(0) then send each digit of that number to an array and then send each slot of that array to a pin. Isnt that an easier method? Is it possible?

Thanks for the interest!

http://pdf1.alldatasheet.es/datasheet-pdf/view/8296/NSC/DAC0808.html

I'm trying to connect the typical application on page 3.

Gilgamesh90: PORTD = 0x55; Isnt the "55" supposed to be 110111? or the number 0101 0101 refers to a different matter?

0x means hexadecimal. 0x55 in binary is 01010101.

Easier to use is this http://www.digikey.com/product-detail/en/MCP4901-E%2FP/MCP4901-E%2FP-ND/2332819

Like having as shift register internal to the DAC. Can get 10 and 12 bit versions as well. Your chip driving direct from Arduino pins is possible, will need to send 6 bits out one port and 2 bits out of another, or give up the serial IO.

PORTD = manipulatedAnalogRead;

at a minimum: manipulatedAnalogRead = analogRead(A0)>>2; // shift away the lower 2 bits to make 8 bit result.

Using 2 ports: PORTD = manAnaRead & 0b11111100; // upper 8 bits go out PORTD 7-2 PORTC = manAnaRead & 0b00000011; // lower 2 bits go out PORTC 1-0

Actually we borrow a MCP4725 to complete part of the project and it worked!. Unfortunately for me is very difficult to get access to those IC's. The ADC0808 is easy to get here in town.

Gilgamesh90:
A friend of mine told me about converting to binary the number that is read on the analogpin(0) then send each digit of that number to an array and then send each slot of that array to a pin. Isnt that an easier method? Is it possible?

Possible? Sure. Easier? Gosh no. OK, you’ve solved your immediate problem, but this is something you’ll probably want to understand later.

On an AVR (the CPU), every I/O pin is part of an 8-bit “port”. The Uno is a horrible example of this because there are several ports, but none of them are completely free and available for 8-bit general purpose I/O – at least, not without giving up other usually essential functions. Still, ports are 8-bit and control (up to) 8x I/O pins like this:

PORTD = b00000000;  // Binary: all pins on this port set LOW
PORTD = 0x00;       // Equivalent statement, just in hex instead of binary
PORTD = b11111111;  // All pins on this port set HIGH
PORTD = 0xFF;       // Same as above, in hex
PORTD = b00001111;  // Pins 0-3 HIGH, pins 4-7 LOW
PORTD = 0x0F;       // Same, hex
PORTD = b01010101;  // Pins 0, 2, 4, 6 HIGH, pins 1, 3, 5, 7 LOW
PORTD = 0x55;       // You get it, right?

Now, setting the pins the way your friend is recommending would be done like this:

byte  pinval[8];  // Array of bits, with each bit stored in a byte
int   analogval = analogRead(A_PIN);

// Convert 10-bit ADC reading to 8-bit value, discarding two least-significant bits
analogval = analogval >> 2;

// Loop through bits and assign to pinval array
for (int i = 0; i < 8; i++) {
  // Mask the bit at position "i", shift it to 1's place, and store it in the array
  pinval[i] = (analogval & (1 << i)) >> i;
}

// Loop through array and set pin according to stored value
for (int i = 0; i < 8; i++) {
  // Set PORTD pin "i" on or off depending on array value
  PORTD = ( ~(PORTD & (1 << i)) | (pinval[i] << i) );
}

The way you should do it is like this:

int  analogval= analogRead(A_PIN);

// Convert 10-bit ADC reading to 8-bit value, discarding two least-significant bits
analogval = analogval >> 2;

// Set pins accordingly
PORTD = (uint8_t)analogval;

Which do you think is easier? :wink:

Well, I've been working the whole day on this and found this piece of code:

{
    int var = // the number is placed here
    digitalWrite(11, HIGH && (var & B00001000));
    digitalWrite(12, HIGH && (var & B00000100));
    digitalWrite(13, HIGH && (var & B00000010));
    digitalWrite(14, HIGH && (var & B00000001));
}

and actually is working for me!. The only problem is when the output is supposed to be 0 (zero) is not 0. is 1.25V. . EDIT: also, there shouldnt be any loss of information. Let me exemplify:

Let's say we receive a value of 1V on analogpin(0) that should be converted to 204. Then that 204 in binary is 11001100 and that number is sent to the data bus and voila!, there is no data loss. Am I wrong wih this method?

If it works, then good on ya. That's all that matters. For the sake of understand though...

That code does effectively the same thing as the array method, just using digitalWrite instead of direct port I/O. digitalWrite will do the direct I/O itself calls after it looks up which port and pin number correspond with the Arduino pin number you provided. In reality, this is the slowest possible way to do achieve your result since digitalWrite has more overhead than even the array approach.

Why this is (possibly) not a good approach:

  • Due to the aforementioned overhead, it's an enormous waste of cycles over just writing the bits all at once. (If you have cycles to spare, no biggie.)

  • As such, you'll be severely speed-impaired WRT how many writes you can perform per unit of time. (If you have no data throughput constraints, then no loss.)

  • Each pin will be set several uS after the previous one due to the one-pin-at-a-time approach used by digitalWrite. (If your receiving device gets all 8 bits before its next clock cycle, or before you set a latch pin, then this is also of no concern.)

Why you might want to do it anyway:

  • It's beginner-friendly.

Well, it seemed to be a very easy to solve problem at the beggining. Unfortunately it requires a lot of extra knowledge but I wont give up!

For the chip you gave the link to you need to use a latched shift register between the Arduino and the and your chip.

Then you load the data into the shift reg's input and then when all the data is loaded, toggle a single pin and the data is put (all in one go) on the output. Look at the examples in the playground to find out about using shift reg's in general. No need to play with direct port stuff.

Mark

Is it really so scary you would suggest additional components to avoid it? ;) (Not criticizing, just amused.)