|
|
View previous topic :: View next topic |
Author |
Message |
Warren Massey Guest
|
How to read 16-bit data from SPI ? |
Posted: Thu Feb 20, 2003 5:45 pm |
|
|
I'm trying to use a 16F877 to monitor the data passing on one side of the SPI bus. The PIC is configured as a slave and shares the same select line as the device receiving the data. The data consists of 2 bytes transferred as one 16-bit word. The SPI_READ() function can return the high data byte and if I call it twice in a row it can return the high data byte twice in a row. What does it take to get both the high & low byte of the same word as it passes by on the bus?
Thanks!
___________________________
This message was ported from CCS's old forum
Original Post ID: 11939 |
|
|
stevev Guest
|
Re: How to read 16-bit data from SPI ? |
Posted: Thu Feb 20, 2003 8:36 pm |
|
|
One thing to consider is that the master won't send the second byte until its good and ready... do you have an interrupt receive handler that queues each byte when sent? That way you can easily wait until the 2nd byte has been sent. Otherwise be sure to ues some other scheme to ensure the data is there. Or maybe I'm on the wrong track. I have no problems sending 2 consecutive bytes using the interrupt handler approach. Good luck! -steve-
:=I'm trying to use a 16F877 to monitor the data passing on one side of the SPI bus. The PIC is configured as a slave and shares the same select line as the device receiving the data. The data consists of 2 bytes transferred as one 16-bit word. The SPI_READ() function can return the high data byte and if I call it twice in a row it can return the high data byte twice in a row. What does it take to get both the high & low byte of the same word as it passes by on the bus?
:=
:=Thanks!
___________________________
This message was ported from CCS's old forum
Original Post ID: 11944 |
|
|
Warren Massey Guest
|
Re: How to read 16-bit data from SPI ? |
Posted: Fri Feb 21, 2003 9:18 am |
|
|
First of all, I'm not sending bytes, I'm receiving them.
Second, once an SPI transaction** starts, for the system I'm monitoring, there is never a pause between "bytes" within the same transaction.
FWIW, the SPI Master in this case is a Motorola Neuron chip running code produced using an Echelon compiler and its SPI implementation allows as many as 255 bits to be transferred in a >>>single<<< SPI transaction. In my case the transaction is only 16 bits long (the Neuron is talking to a MAX3110 UART which wants its data in 16-bit chunks) and I'm trying to monitor the transaction with the PIC. I can make the PIC acquire the first 8 bits that pass by but, so far, have not managed to snag the second eight that are part of the same transaction.
** My definition of one SPI transaction = CS (chip select) goes low followed by SCLK cycling once for each bit transferred (the data lines are assumed to be stable half way through any one SCLK cycle) and after the correct number of SCLK cycles have been completed, SCLK stops cycling and CS goes high. In my case, with a scope, I can watch SCLK and there is no pause between the first 8 bits and the second 8 bits.
This doesn't say that there cannot be irregularities in the period of SCLK (like pauses between bytes). It's just not the case for the Neuron Master.
Thanks for taking the time to reply.
:=One thing to consider is that the master won't send the second byte until its good and ready... do you have an interrupt receive handler that queues each byte when sent? That way you can easily wait until the 2nd byte has been sent. Otherwise be sure to ues some other scheme to ensure the data is there. Or maybe I'm on the wrong track. I have no problems sending 2 consecutive bytes using the interrupt handler approach. Good luck! -steve-
___________________________
This message was ported from CCS's old forum
Original Post ID: 11959 |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Re: How to read 16-bit data from SPI ? |
Posted: Sat Feb 22, 2003 11:09 am |
|
|
:=I'm trying to use a 16F877 to monitor the data passing on one side of the SPI bus. The PIC is configured as a slave and shares the same select line as the device receiving the data. The data consists of 2 bytes transferred as one 16-bit word. The SPI_READ() function can return the high data byte and if I call it twice in a row it can return the high data byte twice in a row. What does it take to get both the high & low byte of the same word as it passes by on the bus?
:=
:=Thanks!
Too sum things up I dont think the PIC can support what you want to do using the built in hardware(CCP). If you get it working I would really like to hear about it. You should be able to capture each bit and by simply watching the pins change. Something like this can run very fast and you could capture as many bytes as you want.
If the hardware can do it
While(SPI_Buffer_index < 255)
{
temp_byte_bit_index = 8;
While(temp_byte_bit_index)
{
While(clock_input);
shift_left(temp_byte,1,MOSI_input);
temp_byte_bit_index--;
While(!clock_input);
}
SPI_Buffer[SPI_Buffer_index] = temp_byte;
SPI_Buffer_index++;
}
If the hardware can do it, it would need to be like this.
Hi_Byte = spi_read(0);
Lo_Byte = spi_read(0);
___________________________
This message was ported from CCS's old forum
Original Post ID: 12009 |
|
|
Warren Massey Guest
|
Re: How to read 16-bit data from SPI ? |
Posted: Mon Feb 24, 2003 6:04 pm |
|
|
<font face="Courier New" size=-1>:=To sum things up I dont think the PIC can support what you want to do using the built in hardware(CCP). If you get it working I would really like to hear about it. You should be able to capture each bit and by simply watching the pins change. Something like this can run very fast and you could capture as many bytes as you want.
:=
:=
I agree. This is indeed what I decided to do.
Here's the code that worked for me:
<pre>
// Routine to monitor the passage of data on one side or the other of the SPI bus.
//
// Warren Massey 2-24-2003
//
// Written for a CCS "Software Prototyping Board" with the CCS 2x16 LCD display on Port D
// and a 16F877 PIC running at 20MHz
//
// The SPI bus CS (chip select) line for the slave device whose communication is to
// be monitored is assumed to be connected to Port B, bit #00 (of 00-07)
//
// The SPI bus SCLK (clock) line is assumed to be connected to Port B, bit #01 (of 00-07)
//
// A normally HIGH (push for LOW) pushbutton is connected to Port B, bit #02 (of 00-07)
// If communications >>> TO <<< the slave device are to be monitored then do not press the button.
// If communications >>> FROM <<< the slave device are to be monitored then press the button.
//
// The SPI bus DIN (data in) line is assumed to be connected to Port B, bit #04 (of 00-07)
//
// The SPI bus DOUT (data out) line is assumed to be connected to Port B, bit #05 (of 00-07)
//
#include <16f877.h>
#device ICD=TRUE
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=20000000)
#include <lcd.c> // from CCS "Drivers" directory
// SPI Handshake definitions
#define CPOL 0 // 0 or 1, Clocking Polarity, 0 => read data after L-to-H transition of SCLK
// 1 => read data after H-to-L transition of SCLK
#define CPHA 0 // 0 or 1, SCLK idle state, 0=> idle low, 1=> idle high
#if CPOL^CPHA // Exclusive OR of these gives the state of SCLK when we should wait
#define READ_WHEN_SCLK_HI 0 // if we should wait for SCLK to go HI before reading data line state
#else
#define READ_WHEN_SCLK_HI 1 // else if we should wait for SCLK to go LO before reading data line state
#endif
#byte port_b = 0x06 // Port B address
#byte TrisB = 0x86 // Port B direction control register address
#define PortB_IO 0b11111111; // 1's are inputs, 0's are outputs
// IO bits we will use
#bit SPI_CS = port_b.0 // bit #00 = chip select (input)
#bit SPI_CLK = port_b.1 // bit #01 = SPI clock (input)
#bit BUTTON_UP = port_b.2 // bit #02 = pushbutton (input)
#bit SPI_DIN = port_b.4 // bit #04 = SPI data in (input)
#bit SPI_DOUT = port_b.5 // bit #05 = SPI data in (input)
void SPI_READ_bytes( int num_bytes, int ButtonUp, unsigned int *accumulator )
{
signed int i, j;
for( i=num_bytes-1; i>=0; i-- ) // Loop once for each byte we want to retrieve
{ // starting with most significant byte first
for( j=0; j<8; j++ ) // Loop once for each bit we want to retrieve
{
#if READ_WHEN_SCLK_HI
while( ~SPI_CLK ); // Wait for clock to go HI
#else
while( SPI_CLK ); // Wait for clock to go LO
#endif
if( ButtonUp ) // Move a bit from the appropriate data line into the LSB of our accumulator
shift_left( &accumulator[i], 1, SPI_DIN); // if SPI DIN line
else
shift_left( &accumulator[i], 1, SPI_DOUT); // else if SPI DOUT line
#if READ_WHEN_SCLK_HI
while( SPI_CLK ); // Wait for clock to go LO
#else
while( ~SPI_CLK ); // Wait for clock to go HI
#endif
}
}
}
main()
{
unsigned long DIN_data=0xABCD, DOUT_data=0xABCD; // make initial values obvious on LCD
setup_adc_ports(NO_ANALOGS);
TrisB = (int)PortB_IO; // configure IO direction
lcd_init(); // initialize the LCD
printf(lcd_putc,"\f DIN: \%LX \n DOUT: \%LX", DIN_data, DOUT_data);
while(TRUE) // Main program loop
{
while( SPI_CS ); // wait for SELECT line to be asserted (CS is active low, so asserted = LO)
if( BUTTON_UP ) // based on the button state
SPI_READ_bytes( 2, 1, &DIN_data ); // move two bytes from the DIN line to our (long) word
else
SPI_READ_bytes( 2, 0, &DOUT_data ); // move two bytes from the DOUT line to our (long) word
printf(lcd_putc,"\f DIN: \%LX \n DOUT: \%LX", DIN_data, DOUT_data); // show current & previous
while( ~SPI_CS ); // wait for SELECT line to be deasserted (CS is active low, so deasserted = HI)
}
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 12072 |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Nice |
Posted: Wed Feb 26, 2003 12:08 pm |
|
|
___________________________
This message was ported from CCS's old forum
Original Post ID: 12128 |
|
|
Paul_B
Joined: 08 Sep 2003 Posts: 9 Location: Birmingham, UK
|
Re: How to read 16-bit data from SPI ? |
Posted: Thu Feb 27, 2003 5:09 am |
|
|
:=I'm trying to use a 16F877 to monitor the data passing on one side of the SPI bus. The PIC is configured as a slave and shares the same select line as the device receiving the data. The data consists of 2 bytes transferred as one 16-bit word. The SPI_READ() function can return the high data byte and if I call it twice in a row it can return the high data byte twice in a row. What does it take to get both the high & low byte of the same word as it passes by on the bus?
:=
:=Thanks!
I am having exactly the same problem at the moment, only i need to read 32 bits serial data, at a speed of 100Kbits/s. Can receive second and third byte but first and fourth byte are garbage at the moment. It would be interesting to know how you got on, cus i'm having trouble figuring out what i'm doing wrong.
Best of luck anyhow.
Paul B
___________________________
This message was ported from CCS's old forum
Original Post ID: 12163 |
|
|
Warren Massey Guest
|
Re: How to read 16-bit data from SPI ? |
Posted: Thu Feb 27, 2003 4:49 pm |
|
|
<font face="Courier New" size=-1>:=I am having exactly the same problem at the moment, only i need to read 32 bits serial data, at a speed of 100Kbits/s. Can receive second and third byte but first and fourth byte are garbage at the moment. It would be interesting to know how you got on, cus i'm having trouble figuring out what i'm doing wrong.
:=Paul B
I did get it working. I posted the code here. You should be able to use the "SPI_READ_bytes" subroutine for reading 32 bits if you call it with a pointer to a 4-byte array in the place of the "accumulator" argument.
Warren</font>
___________________________
This message was ported from CCS's old forum
Original Post ID: 12187 |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|