Go Down

Topic: Generating a separate but continuous clock signal that's in sync with SPI CLK (Read 1 time) previous topic - next topic

__lonestar__

Hi Gurus,

I'm working on a project at the moment that uses a custom SPI device but another part of the electronics requires a continuous clock signal that's at the same speed and preferably in sync with the SPI clock signal.

I'm not an expert with registers but feel this may be the way to do it. I'm using an ATMega328 (UNO).

Free pins I have are D3-D6 or any Analogue pin A0-A5.

I'm using the hardware serial pins D0 and D1 as well as the SoftwareSerial library for a second serial port on pins D6 and D7.

My SPI is running at 4Mhz at the moment with:

Code: [Select]


#include <SPI.h>
#define SSPin 10

void setup() {

pinMode (SSPin, OUTPUT);
  SPI.begin();
  SPI.setDataMode(SPI_MODE2);
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV4);

}

void loop() {

  checkSensor();
}

void checkSensor() {

  byte sensorValues;

  // ATMega 328
  digitalWrite(SSPin, LOW);
  sensorValues = SPI.transfer(0xFF);
  digitalWrite(SSPin, HIGH);

  // Do stuff with sensorValues

}


Running this code on an UNO will generate multiples of 8 pulses at 4Mhz with around about 16us delay between each burst on my scope. How do I get a continuous 4Mhz signal based on this without affecting SPI.

I've tried using the TimerOne library but it breaks parts of the software when attaching an interrupt (I think it may break the softwareSerial library). I feel there must be a better way since there's a clock divider already setup with SPI.

Ideas?

Koepel

Can you explain why it needs to be in sync ?

An internal hardware timer can be used to generate a clock. I don't know which timer SoftwareSerial is using, but there are three timers, and Timer0 is used by Arduino for timing.

To be in sync requires extra external hardware.

__lonestar__

It's doesn't need to be in sync but it does need to be at the same speed. Basically I'm using a JK Flip Flop to detect triggering of a sensor and the state of JK and CLK need to be in a stable state when a reset takes place.

I'm using the MOSI to reset the Flip Flop and would prefer the clock state to be consistent for predictable operation of the circuit. It could either be high or low.


nickgammon

What's the problem with using SCK itself (pin 13)? Or do you want this signal to be continuous?
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

Coding Badly


Configure timer 2 to output the signal.  Should be four lines of code.


__lonestar__

In order to keep the Flip Flops alive the clock needs to be continuous.

Thanks Coding Badly (I should use that name!) - The use of Timer 2 is perfect but what are the four lines of code? I tried a couple of things with registers but it affected other bits of code that use the timer.

nickgammon

You can put this in setup:

Code: [Select]
const byte CLOCKOUT = 9;   // Uno, Duemilanove, etc.

  // set up 4 MHz timer on CLOCKOUT (OC1A)
  pinMode (CLOCKOUT, OUTPUT);

   // set up Timer 1
  TCCR1A = bit (COM1A0);  // toggle OC1A on Compare Match
  TCCR1B = bit (WGM12) | bit (CS10);   // CTC, no prescaling
  OCR1A =  1;       // output every other cycle


Warning though, the clock is not necessarily in sync with SCK. I observed the signal being 62.5 ns out, or falling (when SCK is rising), or rising (when SCK is rising).
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

CrossRoads

You're aware the SPI clock only occurs when a transfer occurs? Is that going to be a problem?
Maybe you can set a fuse bit to output the system clock, run it thru a flip flop to divide it by two, and use that.
Will be running all the time.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

__lonestar__

You're a genius Nick!

Don't even need to write to the ports (pins) with toggles etc. Not sure how it works but great!

The maximum speed i could get by doing timer compare interrupts with direct port manipulation was 200Kz!

i.e. This might be useful for someone else if you don't need Mhz speeds...
http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS

And this is about 4 x faster than digitalWrite()
http://www.instructables.com/id/Fast-digitalRead-digitalWrite-for-Arduino/?ALLSTEPS

But none of it got me near what you've achieved.

nickgammon

You're aware the SPI clock only occurs when a transfer occurs? Is that going to be a problem?
Maybe you can set a fuse bit to output the system clock, run it thru a flip flop to divide it by two, and use that.
Will be running all the time.

That would certainly be a highly viable approach. You might still suffer from the problem I had with the timer code. The SPI clock might start on a different clock cycle to the one (divided by 2) that you use.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

nickgammon

Don't even need to write to the ports (pins) with toggles etc. Not sure how it works but great!
The hardware is designed to do it. Interrupts are all very well, but they have an overhead.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

smartsystemdesign

I have a project that does requires an output clock to be synchronized with the SPI clock, but after much research, haven't found a way to do it with the Arduino SPI library which I prefer to use for its speed.  Is it possible to make the SPI clock wait for the next rising edge of my output clock to synchronize with it?  Maybe a change to the SPI library code?

Warning though, the clock is not necessarily in sync with SCK. I observed the signal being 62.5 ns out, or falling (when SCK is rising), or rising (when SCK is rising).
Nick, do you know?

nickgammon

The SPI library is pretty small, and just basically makes the SPI hardware do its thing. I doubt you can do that, unless you use bit-banged SPI. I have a bit-banged SPI library on my page about SPI.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

Go Up