Offline
Newbie
Karma: 0
Posts: 24
|
 |
« on: June 22, 2012, 04:02:49 pm » |
I am coding a SPI device that required 13us clock period(76923Hz) . I calculate the clock divider is 208, but 208 is not available in the "SPI.setClockDivider()" function. How can I get the clock frequency I need?
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Dallas
Online
Shannon Member
Karma: 129
Posts: 10384
|
 |
« Reply #1 on: June 22, 2012, 05:02:53 pm » |
Seriously? You have a device that requires that exact timing / frequency?
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 75
Posts: 6975
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #2 on: June 22, 2012, 05:26:58 pm » |
SPI is supposed to be bit-rate independent, what device do you have that needs such a specific rate?
______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 24
|
 |
« Reply #3 on: June 23, 2012, 03:35:33 pm » |
Seriously? You have a device that requires that exact timing / frequency?
it's a non-standard spi device(like spi, but not). I read the communication between the master device and slave device. The clock is 76.9kHz, 8 bits, idle high, rising edge sampling.
|
|
|
|
|
Logged
|
|
|
|
|
Leeds, UK
Offline
Edison Member
Karma: 38
Posts: 1028
Once the magic blue smoke is released, it won't go back in!
|
 |
« Reply #4 on: June 23, 2012, 04:20:55 pm » |
Have you got a link to the datasheet?
It won't be possible to be that specific with the SPI of the Arduino unless you use a different crystal frequency (and hence modified bootloader).
It may however be possible to do it using an Timer1 or Timer2 and compare/overflow interrupts. If you can post a datasheet I can give you a better example of how the timer could be used.
|
|
|
|
« Last Edit: June 23, 2012, 04:23:33 pm by TCWORLD »
|
Logged
|
~Tom~
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 24
|
 |
« Reply #5 on: June 23, 2012, 05:07:12 pm » |
Have you got a link to the datasheet?
It won't be possible to be that specific with the SPI of the Arduino unless you use a different crystal frequency (and hence modified bootloader).
It may however be possible to do it using an Timer1 or Timer2 and compare/overflow interrupts. If you can post a datasheet I can give you a better example of how the timer could be used.
I am decoding a spi-like protocol. There are a master device and a slave device. Then I want use my UNO instead of the origin master device. Waveform as follow picture.  As you can see the clock period is around 13 us. The corresponding clock frequency is 76.9kHz. Is that possible to write my own clock generator that is based on the system clock and a clock counter? For example, count 100 system clock and set my_clk_generator to 1, then count another 100 system clock and set my_clk_generator to 0.
|
|
|
|
« Last Edit: June 23, 2012, 05:09:48 pm by jenaflex »
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 75
Posts: 6975
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #6 on: June 23, 2012, 05:23:05 pm » |
OK so you're not generating this you're at the mercy of an existing system.
Why not just hang your Arduino off the same line as a slave, that would allow you the sample one signal in hardware.
Alternatively run the CLK signal to an external interrupt input, then read the two signals in the ISR and reconstruct the data from that.
Either way you don't have to know or care about the frequency.
______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Leeds, UK
Offline
Edison Member
Karma: 38
Posts: 1028
Once the magic blue smoke is released, it won't go back in!
|
 |
« Reply #7 on: June 23, 2012, 05:23:17 pm » |
What I would suggest you do is to use the SPI module, set the divider to 128 (that will give you 125kHz), and try it.
In all likelyhood the slave device will work fine at that frequency. The design of the SPI devices should allow them to run at any speed the master sets (as long as they can keep up). I would think that the slave should manage 125kHz.
|
|
|
|
|
Logged
|
~Tom~
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 75
Posts: 6975
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #8 on: June 23, 2012, 06:13:01 pm » |
Then I want use my UNO instead of the origin master device. Doh, I didn't read this bit. Just because you are seeing 76.9kHz now that doesn't mean you have to generate the same, that frequency is probably generated by some bit banging from the current master device using who-knows-what processor, language and crystal. If the slave device didn't work at 125kHz as TCWORLD said or some other slow rate I would eat my Arduino (the small one that is  ). ______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 24
|
 |
« Reply #9 on: June 24, 2012, 04:20:30 pm » |
What I would suggest you do is to use the SPI module, set the divider to 128 (that will give you 125kHz), and try it.
In all likelyhood the slave device will work fine at that frequency. The design of the SPI devices should allow them to run at any speed the master sets (as long as they can keep up). I would think that the slave should manage 125kHz.
It seems that it doesn't work.  My Code #include "Arduino.h" //include the SPI library #include <SPI.h>
const int CLKpin = 13; // set pin 13 as the CLK const int MOSIpin = 11; // set pin 11 as the MOSI const int MISOpin = 12; // set pin 12 as the MISO const int SSpin = 10; // set pin 10 as the SS
// initialize setup void setup(){ pinMode (CLKpin, OUTPUT); // set CLKpin as an output pinMode (MOSIpin, OUTPUT); // set MOSIpin as an output pinMode (MISOpin, INPUT); // set MISOpin as an input pinMode (SSpin, OUTPUT); // set SSpin as an output SPI.begin(); // initialize SPI SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE3); SPI.setClockDivider(SPI_CLOCK_DIV128); }
void loop() { byte COMMAND = 0x13; byte cmd_step = 0x02; SPI.transfer(COMMAND); // contract iris command delayMicroseconds(191); SPI.transfer(cmd_step); delayMicroseconds(16000);
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 75
Posts: 6975
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #10 on: June 25, 2012, 07:34:12 am » |
It does indeed look like the slave is struggling, can you further reduce the speed?
Do you have a data sheet for the device?
______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Leeds, UK
Offline
Edison Member
Karma: 38
Posts: 1028
Once the magic blue smoke is released, it won't go back in!
|
 |
« Reply #11 on: June 25, 2012, 10:13:28 am » |
Just as a quick test, try adding this to the start of the setup():
CLKPR = 0b10000000; CLKPR = 0b00000001;
You will also have to half all of the delays for this test as the Arduino IDE wont know how to account for this change.
What it does is prescales the whole system clock from 16MHz down to 8MHz, which will mean you get a 62.5kHz SPI clock.
The other thing is what are the three signals in the first scope trace you posted? It doesn't quite look like SPI.
|
|
|
|
« Last Edit: June 25, 2012, 10:24:30 am by TCWORLD »
|
Logged
|
~Tom~
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 24
|
 |
« Reply #12 on: June 25, 2012, 10:17:17 am » |
It does indeed look like the slave is struggling, can you further reduce the speed?
Do you have a data sheet for the device?
______ Rob
I haven't the data sheet. I use the "SPI.setClockDivider(SPI_CLOCK_DIV128); " , which is the slowest spi clock in the SPI library. I am decoding the protocol of Canon lens. There is no data sheet available. But there is a Canon services manual that was released by some guys. The Canon services manual said as follows: clock pulse 62.5kHz, 16us pulse 8 bit My observation on oscilloscope: clock pulse,13us pulse 8bit clock idle high rising edge sampling Other non-official info (might be wrong): 1. Motorola SPI; 8 bit serial; Such as the protocol used with the 68HC05 chip.
|
|
|
|
|
Logged
|
|
|
|
|
Leeds, UK
Offline
Edison Member
Karma: 38
Posts: 1028
Once the magic blue smoke is released, it won't go back in!
|
 |
« Reply #13 on: June 25, 2012, 10:47:45 am » |
Oh, another option if you dont need the serial port is to use it in fake SPI mode. This allows you exact control over the baud rate. Example (Note: This is untested, I based it on the code examples in the 328p datasheet): void SPIInitialise() { // put your setup code here, to run once: pinMode(4,OUTPUT); //SCLK pin pinMode(0,INPUT); //MISO pinMode(1,OUTPUT); //MOSI pinMode(2,OUTPUT); //SS //Set UART as SPI. UBRR0 = 0; UCSR0C = (1<<UMSEL01)|(1<<UMSEL00)|(1<<UCPHA0)|(1<<UCPOL0); //Set to MasterSPI (UMSEL0=1, UMSEL1=1), in Mode3 (CPHA=1, CPOL=1) UCSR0B = (1<<RXEN0)|(1<<TXEN0); //Enable TX and RX (TX = MOSI, RX = MISO) UBRR0 = 127; //SPI clock rate. UBRR0 = (FCPU/(2*BAUD)) -1;. So for 62.5KHz, UBRR0 = (16000000/(2*62500))-1 = 128 -1 = 127 }
byte SPITransfer(byte data) { /* Wait for empty transmit buffer */ while ( !( UCSR0A & (1<<UDRE0)) ); /* Put data into buffer, sends the data */ UDR0 = data; /* Wait for data to be received */ while ( !(UCSR0A & (1<<RXC0)) ); /* Get and return received data from buffer */ return UDR0; }
void setup(){ SPIInitialise(); }
void loop(){ //Main loop }
|
|
|
|
|
Logged
|
~Tom~
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 226
Posts: 14106
Lua rocks!
|
 |
« Reply #14 on: June 26, 2012, 02:08:05 am » |
My bit-banged SPI used for uploading hex files: // bit banged SPI pins const byte MSPIM_SCK = 4; // port D bit 4 const byte MSPIM_SS = 5; // port D bit 5 const byte BB_MISO = 6; // port D bit 6 const byte BB_MOSI = 7; // port D bit 7
// 8 MHz clock on this pin const byte CLOCKOUT = 9;
// for fast port access (Atmega328) #define BB_MISO_PORT PIND #define BB_MOSI_PORT PORTD #define BB_SCK_PORT PORTD const byte BB_SCK_BIT = 4; const byte BB_MISO_BIT = 6; const byte BB_MOSI_BIT = 7;
// control speed of programming const byte BB_DELAY_MICROSECONDS = 4;
...
// Bit Banged SPI transfer byte BB_SPITransfer (byte c) { byte bit; for (bit = 0; bit < 8; bit++) { // write MOSI on falling edge of previous clock if (c & 0x80) BB_MOSI_PORT |= _BV (BB_MOSI_BIT); else BB_MOSI_PORT &= ~_BV (BB_MOSI_BIT); c <<= 1; // read MISO c |= (BB_MISO_PORT & _BV (BB_MISO_BIT)) != 0; // clock high BB_SCK_PORT |= _BV (BB_SCK_BIT); // delay between rise and fall of clock delayMicroseconds (BB_DELAY_MICROSECONDS); // clock low BB_SCK_PORT &= ~_BV (BB_SCK_BIT); } return c; } // end of BB_SPITransfer
By tweaking BB_DELAY_MICROSECONDS you should be able to get the frequency you want.
|
|
|
|
|
Logged
|
|
|
|
|
|