Weird digitaiRead() behavior in the SPI part of my project..

Status
Not open for further replies.

milhead

Member
Hi Folks;

I'm sure I'm doing something simple wrong but am getting incorrect data in my attempt to
read data back from an SPI slave.

The data is showing correctly on the logic analyzer but received wrong in the Arduino
program.

In the attached code I did not believe that my serial output was correct so I output the two read
bytes immediately to a bogus SPI to see what I received..

My snippet.. (Whole Program below..)

digitalWrite(adcCS, LOW);
transfer(cmd1);
r1 = transfer(cmd2);
r2 = transfer(0);
digitalWrite(adcCS, HIGH);

digitalWrite(otherCS, LOW);
transfer(r1);
transfer(r2);
digitalWrite(otherCS, HIGH);

If you look at the logic analyzer trace the r1 and r2 bytes I tried to read in the actual ADC
read are incorrect but they do agree with the serial data.

the transfer() is giving me the same bazzar results it I use the SPI library or bit-bang the SPI.

Capture.JPG


Also when I try just to read a pin hooked to high or ground it's not reading the value correctly..

Questions:
1) Are Teensy 3.1 pins identified differently like they are in the 2.0 when used with arduino so I;'m using the wrong pin?
2) Is there something silly I'm doing wrong.

Teensy 3.1
Arduino 1.0.5-r2
TeensyDuino 1.18
SPI talking to an Isolation IC ADuM7441
and 4-channel ADC on the far side of that MCP3302

imageSmall.jpeg

Full Source:
PHP:
// kill_a_watt.c
// code to read ADC on the watt meter..

#define BANG_SPI
#ifdef BANG_SPI
const int BSCK    = 13;
const int BMOSI   = 11;
const int BMISO   = 12;
#define transfer(x) spiBangTransfer((x))
#else
#include <SPI.h>
#define transfer(x) SPI.transfer((x))
#endif


const int greenLedPin =  5;
const int redLedPin =  7;
const int adcCS  = 10;
const int dio23 = 23;
const int otherCS = 9;

// the setup() method runs once, when the sketch starts
char bbuf[128];

void setup() {
  // initialize the digital pin as an output.
  pinMode(greenLedPin, OUTPUT);
  pinMode(redLedPin, OUTPUT);
  pinMode(adcCS, OUTPUT);
  pinMode(otherCS, OUTPUT);
  pinMode(0, INPUT);
  digitalWrite(otherCS, HIGH);
  digitalWrite(adcCS, HIGH);
  #ifdef BANG_SPI
  pinMode(BSCK, OUTPUT);
  pinMode(BMOSI, OUTPUT);
  pinMode(BMISO, INPUT_PULLUP);
  digitalWrite(BSCK, LOW);
  digitalWrite(BMOSI, LOW);
  #endif
  digitalWrite(redLedPin, HIGH);
  digitalWrite(greenLedPin, HIGH);
  Serial.begin(38400);
  
#ifndef BANG_SPI
  // start the SPI library:
  SPI.begin();
#endif
 
}

void report(int count)
{
  double v, a;
  char buf[128];

  v = cos((double)count / 100)*4.5;
  a = cos((double)count / 120)*3.5;
  
  sprintf(buf, "v:%15.6lf  a:%15.6lf c:%d\n", v, a, count);
  Serial.println(buf);
}

#ifdef BANG_SPI
char spiBangTransfer(char SPIDataOut)
{
    unsigned char SPICount;                               // Counter used to clock out the data
    unsigned char SPIDataIn = 0;

    digitalWrite(BSCK,LOW);
    
    for (SPICount = 0; SPICount < 8; SPICount++)
    {
        digitalWrite(BMOSI, (SPIDataOut & 0x80));      // set Output bit
        digitalWrite(BSCK, HIGH);                        // Clock Rising Edge
        SPIDataIn += (digitalRead(BMISO)&1);               // Read the data bit
        digitalWrite(BSCK, LOW);
        SPIDataOut <<= 1;
        SPIDataIn <<= 1;
    }                                        
    digitalWrite(BMOSI,LOW);              
    
    return (SPIDataIn);                      
}
#endif


int16_t readAdcChannel(int channel)
{
  char cmd2;
  char cmd1 = 0x18 + channel;
  char r1, r2;
  uint16_t res;
  
  cmd2 = cmd1 << 7;
  cmd1 = cmd1 >> 1;
  
  digitalWrite(adcCS, LOW);
  transfer(cmd1); 
  r1 = transfer(cmd2);
  r2 = transfer(0);
  digitalWrite(adcCS, HIGH);
  
  digitalWrite(otherCS, LOW);
  transfer(r1);
  transfer(r2);
  digitalWrite(otherCS, HIGH);
  
  
  sprintf(bbuf, "r1: 0x%02x,  r2: 0x02x, D0:%d D23:%d", r1, r2, (digitalRead(0) & 0x01), (digitalRead(dio23) & 0x01));
  Serial.println(bbuf);
  
  res = r1;
  res = (res << 8) + r2;
  res = res & 0x0fff;
  
  return res;
}


void loop() 
{
  static int count;
  static int ledState = 0;
  char dat;
  
  digitalWrite(greenLedPin, ledState);   // set the LED
  ledState = ! ledState;

  sprintf(bbuf, "c0:%d c1:%d c2:0d", readAdcChannel(0), readAdcChannel(1), readAdcChannel(2));
  Serial.println(bbuf);
//  report(count);
  count ++;
  delay(1000);  
}


Gives the output...

PHP:
r1: 0x8c,  r2: 0x02x, D0:48 D23:1
r1: 0x8c,  r2: 0x02x, D0:48 D23:1
r1: 0x8c,  r2: 0x02x, D0:50 D23:1
c0:3120 c1:3120 c2:0d
r1: 0x8c,  r2: 0x02x, D0:50 D23:1
r1: 0x8c,  r2: 0x02x, D0:50 D23:1
r1: 0x8c,  r2: 0x02x, D0:50 D23:1
c0:3122 c1:3122 c2:0d
r1: 0x8c,  r2: 0x02x, D0:50 D23:1
r1: 0x8c,  r2: 0x02x, D0:50 D23:1
r1: 0x8c,  r2: 0x02x, D0:50 D23:1


Any ideas why I'm reading the wrong data would be a great help!


Miller
 
Yeah, it's off to the left of the photo but I'd expect the isolation chip not to work at all if I missed that one...

If you look at the analyzer trace the SPI signals correctly make it across the isolation barrier and back just delayed a tad,, By the time
the clock rises, all is good..

If I ran the 4MHz clock of the default SPI it was sometimes missing a clock edge, 2.oMHz would work fine but since I'm
stuck at reading the wrong data it's kinda moot.

Mil
 
Last edited:
I've made some headway... I've found a defect in my SPI bit-banging code and found that the SPI library code will run well at 1 MHz...
The isolation chip is definitely forcing the slow SPI clock.. Stay tuned...
 
Correct Bit Bang Transfer..

PHP:
#ifdef BANG_SPI
char spiBangTransfer(char SPIDataOut)
{
    unsigned char SPICount;                               // Counter used to clock out the data
    unsigned char SPIDataIn = 0;

    digitalWrite(BSCK,LOW);
    
    for (SPICount = 0; SPICount < 8; SPICount++)
    {
        digitalWrite(BMOSI, (SPIDataOut & 0x80));            // set Output bit
        digitalWrite(BSCK, HIGH);                            // Clock Rising Edge
        SPIDataIn = (SPIDataIn <<= 1) | (digitalRead(BMISO) & 1);
        digitalWrite(BSCK, LOW);
        SPIDataOut <<= 1;
    }                                        
    digitalWrite(BMOSI,LOW);              
    
    return (SPIDataIn);                      
}
#endif
 
Status
Not open for further replies.
Back
Top