direct port access

Hi.
I want to set up a tracer for measuring the characteristics of electronic devices. So I made my own “shield” with an r2r network as a DAC controlled by pins 2…7 of uno or duemilanove.
The recommended way to access the port is like in “SimpleDAC” (simply counting up and down for test of DAC). This is very slow and gives very high glitches, which may eventually destroy the devices.

// SimpelDAC

void setup(){
int i;
for (i=2; i<8; i++){
pinMode(i, OUTPUT);
digitalWrite(i, LOW);
}
}

void loop(){

for (int i=0; i<64; i++){
for (int j=0; j<8; j++){
if (bitRead(i, j)==HIGH) {
digitalWrite(j+2, HIGH);
}
else {
digitalWrite(j+2, LOW);
}
}
}

for (int i=63; i>=0; i–){
for (int j=0; j<8; j++){
if (bitRead(i, j)==HIGH) {
digitalWrite(j+2, HIGH);
}
else {
digitalWrite(j+2, LOW);
}
}
}

}

For a microcontroller the more logical way is the direct port access like in “DACbyte”:
// DAC byte
int t=13;

void setup()
{
// set pins 1 (serial transmit) and 2…7 as output,
// but leave pin 0 (serial receive) as input
// (otherwise serial port will stop working!) …
DDRD = DDRD | B11111110; // digital pins 7,6,5,4,3,2,1,0
}

void loop(){
PORTD = B00000000;
for (byte i=0; i<253; i +=4){
PORTD = i;
delayMicroseconds(t);
}
PORTD = B11111100;
for (byte i=252; i>=0; i -=4){
PORTD = i;
delayMicroseconds(t);
}
}

But here the problem comes in: “loop” always skips everything after the first for- ( or while- or do-) loop. Without these inner loops (DACbyteNf) it works.

// DAC byte no for
byte i=0;
byte n=4;
int t=4; //4, 6
void setup()
{
// set pins 1 (serial transmit) and 2…7 as output,
// but leave pin 0 (serial receive) as input
// (otherwise serial port will stop working!) …
DDRD = DDRD | B11111100; // digital pins 7,6,5,4,3,2,1,0
PORTD = B00000000;
}

void loop(){
PORTD = i;
delayMicroseconds(t);
i+=n;
if (i==252 || i==0){
delayMicroseconds(40t);
n
=-1;
}
}

To read out the voltage over the device (e.g. diode) via serial interface the program looks like “Tracer”.

// Kennlinienschreiber Tracer
byte i;
int adc=0, U0, U1;

void setup()
{
Serial.begin(9600);
// set pins 1 (serial transmit) and 2…7 as output,
// but leave pin 0 (serial receive) as input
// (otherwise serial port will stop working!) …
DDRD = DDRD | B11111100; // digital pins 7,6,5,4,3,2,1,0
Serial.println(“Kennlinienschreiber”);
Serial.println();
}

void loop(){
if ((Serial.available() > 0) && (Serial.read()==32)){
Serial.flush();
Lesen();
}
}

void Lesen(){
PORTD = B00000000;
for (i=0; i<253; i +=4){
PORTD = i;
U0=i>>2;
delay(1);
U1=analogRead(adc);
delay(100);
Serial.print(U0);
Serial.print("\t");
Serial.println(U1);
}
}

But here again the loop never stops, unless I turn off the terminal. The solution is again with a for loop with the known problems (“TraceFor”).

// Kennlinienschreiber Tracer mit for
byte i;
int adc=0, U0, U1;

void setup()
{
for (int j=2; j<8; j++){
pinMode(j, OUTPUT);
digitalWrite(j, LOW);
}
Serial.begin(9600);
Serial.println(“Kennlinienschreiber”);
Serial.println();
}

void loop(){
if ((Serial.available() > 0) && (Serial.read()==32)){
Serial.flush();
Lesen();
}
}

void Lesen(){
for (i=0; i<64; i++){
for (int j=0; j<8; j++){
if (bitRead(i, j)==HIGH) {
digitalWrite(j+2, HIGH);
}
else {
digitalWrite(j+2, LOW);
}
}
U0=i;
delay(1);
U1=analogRead(adc);
delay(100);
Serial.print(U0);
Serial.print("\t");
Serial.println(U1);
}
for (int j=2; j<8; j++){
digitalWrite(j, LOW);
}
}

Is there any way to avoid interference of “loop” by direct port access?

Regards

TracerFor.pde (756 Bytes)

“loop” always skips everything after the first for- ( or while- or do-) loop.

This has to be because your first loop is wrong…

void loop(){
  PORTD = B00000000;
  for (byte i=0; i<253; i +=4){
    PORTD = i;
    delayMicroseconds(t);
  }
    PORTD = B11111100;
  for (byte i=252; i>=0; i -=4){
    PORTD = i;
    delayMicroseconds(t);
  }
}

“byte” is an unsigned 8-bit number, which means that it goes from 0 to 255.
In your first loop, it goes 0, 4, 8, …, 244, 248, 252, 0, 4…
It will NEVER be larger than 253, so the loop never exits.

The second loop looks like it will just barely work (and you can fix the first loop by making it <= 252 instead of < 253.)

Making the loop variable an int and converting it to byte for port access works!! Thanks for the hint with wrap around of byte, I still was thinking in terms of int.