![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Dec 03, 2006 2:57 pm |
|
|
Quote: | I use the setup_spi(MASTER | H_TO_L | DIV_4) | With respect to what Ttelmah wrote about operating the ADC in continuous mode and reading the status bit I recommend you study chapter 5.5 of the MCP3551 datasheet. It is recommended to operate the SPI-bus either in mode 0,0 or mode 1,1. You are operating the SPI-bus in mode 1,0.
In mode 0,0: read 4 bytes
In mode 1,1: read 3 bytes
Configuring the SPI-modes is always very confusing to me because Motorola (the inventor of SPI), Microchip and CCS do things in different ways. That's why I use the table below as reference
Code: | // MOTOROLA MICROCHIP CCS
//---------------------------------------------------------------------------------
// SPI Mode 0,0 == CKP = 0, CKE = 1 == SPI_L_TO_H | SPI_XMIT_L_TO_H
// SPI Mode 0,1 == CKP = 0, CKE = 0 == SPI_L_TO_H
// SPI Mode 1,0 == CKP = 1, CKE = 1 == SPI_H_TO_L
// SPI Mode 1,1 == CKP = 1, CKE = 0 == SPI_H_TO_L | SPI_XMIT_L_TO_H |
Use this in your program as Code: |
#define SPI_MODE_0_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1 (SPI_L_TO_H)
#define SPI_MODE_1_0 (SPI_H_TO_L)
#define SPI_MODE_1_1 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_4 );
|
Edit: Fixed error in number of bytes to read in mode 0,0 and 1,1.
Last edited by ckielstra on Sun Dec 03, 2006 4:01 pm; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
das Guest
|
SPI Help |
Posted: Sun Dec 03, 2006 3:05 pm |
|
|
I will try that. Right now, here is the current code:
#int_RDA
#define SPI_MODE_0_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1 (SPI_L_TO_H)
#define SPI_MODE_1_0 (SPI_H_TO_L)
#define SPI_MODE_1_1 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
int byte1, byte2, byte3, byte4;
int byte_1, byte_2, byte_3, byte_4;
int32 value;
int i;
int completed, loop;
RDA_isr()
{
puts("RDA was tripped");
}
void main()
{
int loop = 1;
OUTPUT_HIGH(PIN_D0); //Start with CS high
setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_4 );
delay_ms(5000); //Delay 5 seconds
puts("Magnum Torque Meter Initialized");
while(TRUE)
{
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
loop = 1;
OUTPUT_LOW(PIN_D0); //Start the conversion
delay_ms(10); //Delay 10 ms for the conversion to complete
do //Do...while loop
{
if(input(PIN_C4) == 0) //Check to see if the conversion is completed
{
byte_4 = spi_read(byte4);
byte_3 = spi_read(byte3);
byte_2 = spi_read(byte2);
byte_1 = spi_read(byte1);
value = make32(byte_4, byte_3, byte_2, byte_1);
for(i = 0; i < 32; i++)
{
putc(bit_test(value, 31 - i));
}
OUTPUT_HIGH(PIN_D0);
completed = 1;
}
if(input(PIN_C4) == 1)
{
delay_us(1);
} //Closing if PIN_
}while(loop = 1);
delay_ms(10000);
}
} |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Dec 03, 2006 3:41 pm |
|
|
Some general remarks:
- When posting code on this forum please use the 'code' buttons. It will help to preserve the layout of your program and makes it easier for us to read the code.
- When debugging a problem like this, get rid of all other program code that might interfere. Especially enabled interrupts might cause unexpected side effects.
- Never use a printf or put instruction in an interrupt handler unless you know and accept the side effects. Receiving a character on the UART will take the same amount of time as sending a single character. You are receiving one character and transmitting 10-fold, this will block receiving and cause buffer overflow. The UART will stop responding at receive buffer overflow (the third character). Resetting the UART requires specific actions or adding the ERRORS directive to the #use RS232 directive.
Then about your program:
- Move the enable_interrupt() functions out of the while loop. You never disable these functions, so why add the overhead?
- I made a mistake in an earlier post. For the spi_read() to generate a clock signal you have to pass the spi_read() function a value, however this doesn't have to be a variable. Just any constant value will do for generating the clock signal, for example spi_read(0).
- while(loop = 1); Change this to '=='
- In SPI-mode 0,0 you are supposed to read 3 bytes, not 4.
- You said you want to operate in single conversion mode. If so, then your handling of the ChipSelect line seems incorrect (read Ttelmah's note on this).
Last edited by ckielstra on Sun Dec 03, 2006 3:46 pm; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
das Guest
|
SPI Help |
Posted: Sun Dec 03, 2006 3:43 pm |
|
|
I refined some of the code shown above - and made changes to keep it in constant conversion mode. I am still seeing all outputs as zeros. Any other ideas? Current code is:
#int_RDA
#define SPI_MODE_0_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1 (SPI_L_TO_H)
#define SPI_MODE_1_0 (SPI_H_TO_L)
#define SPI_MODE_1_1 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
int byte1, byte2, byte3, byte4;
int byte_1, byte_2, byte_3, byte_4;
int32 value;
int i;
int completed, loop;
RDA_isr()
{
puts("RDA was tripped");
}
void main()
{
int loop = 1;
OUTPUT_LOW(PIN_D0); //Start with CS high
setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_4 );
delay_ms(5000); //Delay 5 seconds
puts("Initialized"); //Output string for debug
while(TRUE)
{
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
loop = 1;
delay_ms(10); //Delay 10 ms for the conversion to complete
do //Do...while loop
{
if(input(PIN_C4) == 0) //Check to see if the conversion is completed
{
byte_4 = spi_read(byte4);
byte_3 = spi_read(byte3);
byte_2 = spi_read(byte2);
byte_1 = spi_read(byte1);
value = make32(byte_4, byte_3, byte_2, byte_1);
for(i = 0; i < 32; i++)
{
putc(bit_test(value, 31 - i) + 48);
}
putc(10);
putc(13);
loop = 0;
}
if(input(PIN_C4) == 1)
{
delay_us(1);
}
delay_ms(10000);
}while(loop = 1);
}
}
I know that you said in a previous response something about the
if(input(PIN_C4) == 0)
Can you elaborate? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sun Dec 03, 2006 3:44 pm |
|
|
Your code, now generates 32 clocks. This won't work.
You need to either generate 25 clocks, and not operate the CS, or generate 24 and operate the CS.
Generating 32 clocks, will result in the bytes being shifted, and a garbage result.
The way to generate the extra clock, is to simply toggle it in software.
Code: |
#bit SSPEN=0x14.5
#bit SCL=0x7.3
//Add this after your three reads.
//Ensure the line is the same polarity as the SPI leaves it
SCL=1;
//Turn off the SPI
SSPEN=0;
//Clock the line low
SCL=0;
delay_cycles(1);
//clock the line high
SCL=1;
//turn the SSP back on
SSPEN=1;
//Now you can read the input bit, and see the conversion status in
//continuous mode.
|
I am directly accessing the bit, rather than using the 'output' instruction, so that TRIS doesn't get changed (it is already set as output for the SPI).
As an aside, Ckielstra is dead right that the SPI mode is wrong, but it shouldn't matter. The reason is that the value of the second bit in the SPI settings (CKE), only affects how data is sent. The chip you are using, only receives data, so shouldn't 'care' if this is right. In fact the description in the data sheet is 'misleading' here really, since it should accept modes 0,x, or 1,x, according to how the data is being read. It is still 'better' to get it right, but I don't think that affects your problem....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
das Guest
|
SPI Help |
Posted: Sun Dec 03, 2006 3:51 pm |
|
|
Sorry - I didn't realize about the code posting. I disabled what you recommended. Looking at the Mode 0 0 it generates 4 bytes - not three based on the Figure 5-7. That would seem to work better for the continuos conversion anyway as it will send out the 25th clock cycle. |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
Re: SPI Help |
Posted: Sun Dec 03, 2006 3:59 pm |
|
|
das wrote: | Looking at the Mode 0 0 it generates 4 bytes - not three based on the Figure 5-7. | You are right, I reversed 0,0 and 1,1. |
|
![](templates/subSilver/images/spacer.gif) |
das Guest
|
SPI Help |
Posted: Sun Dec 03, 2006 4:11 pm |
|
|
Thank you for the help. I am having some issues compiling the low level changes in. I am getting errors on your recommendation. Do these need another specification? |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Dec 03, 2006 4:22 pm |
|
|
What is the version number of your compiler? |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Dec 03, 2006 5:05 pm |
|
|
A problem in your program is that you are trying to read the _RDY signal from PIN_C4. This will return undefined values as the pin is used by the SPI module.
Not tested, but could you give the following program a try?
Code: | #include <16F877.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define SPI_MODE_0_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1 (SPI_L_TO_H)
#define SPI_MODE_1_0 (SPI_H_TO_L)
#define SPI_MODE_1_1 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
#define LF 10
#define CR 13
#bit SSPEN=0x14.5
void main()
{
int8 byte_1, byte_2, byte_3;
int8 i;
int32 value;
output_high(PIN_D0); //Start with CS high
setup_spi(SPI_MASTER | SPI_MODE_1_1 | SPI_CLK_DIV_4 );
puts("Initialized"); //Output string for debug
while(TRUE)
{
// Toggle CS in order to start AD conversion
output_low(PIN_D0);
output_high(PIN_D0);
// Wait for AD conversion to finish
SSPEN = 0; // disable SPI so we can access the data line.
do
{
// The Ready state is latched on each falling edge of CS and will not
// dynamically update if CS is held low. CS must be toggled high
// through low.
output_low(PIN_D0);
if (input(PIN_C4) == 0) // Check to see if the conversion is completed
break; // Break out of the loop, leaving _CS active.
output_high(PIN_D0);
} while (TRUE);
SSPEN = 1; // Enable SPI again
// Read value from ADC
byte_3 = spi_read(0);
byte_2 = spi_read(0);
byte_1 = spi_read(0);
output_high(PIN_D0); // De-select ADC
value = make32(0, byte_3, byte_2, byte_1);
for (i = 32; i>0; i--)
{
putc(bit_test(value, i-1) + '0');
}
putc(CR);
putc(LF);
delay_ms(10000);
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Mon Dec 04, 2006 3:43 am |
|
|
PIN C4, should read OK.
If you look at the 'logic' for the I/O pin, there is a pickoff for read, and a picoff for the SPI, and both should be working. When SPI is enabled, it overrides the logic feeding the 'output' connections, but doesn't affect the input connections in this case.
I have driven the ADC involved here OK, but have only used it in single conversion mode, not continuous conversion mode.
I used a pull up on the SD line, and read PIN C4 fine.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Mon Dec 04, 2006 3:48 am |
|
|
I think there is a critical misnderstanding about the useable 'modes' going on here.
If you use the four byte transfer, you cannot read C4, to get the RDY status. When four byte transfer is used, the RDY bit is transferred as the first _bit_ of the fourth byte, and from then he line sits high. To have the bit available to read on pin C4, you need to use the 25bit transfer mode.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Dec 04, 2006 8:01 am |
|
|
Ttelmah wrote: | PIN C4, should read OK.
If you look at the 'logic' for the I/O pin, there is a pickoff for read, and a picoff for the SPI, and both should be working. When SPI is enabled, it overrides the logic feeding the 'output' connections, but doesn't affect the input connections in this case. | You are right. Because the digital output is disabled when using SPI I assumed the same to be true for the input. Instead of only reading the table of PortC functions I should have looked at the diagrams as well.
Quote: | I think there is a critical misnderstanding about the useable 'modes' going on here.
If you use the four byte transfer, you cannot read C4, to get the RDY status. When four byte transfer is used, the RDY bit is transferred as the first _bit_ of the fourth byte, and from then he line sits high. To have the bit available to read on pin C4, you need to use the 25bit transfer mode. | Sorry, I don't agree with you here. As I read Figure 5-7 the RDY bit is in the first bit of the _first_ byte. At first I thought we had a misunderstanding in numbering the bytes, which one is first and which one fourth? But then you wrote 'from then the line sits high', this is only true for the byte most right in the picture which I also see as fourth. The fourth byte contains the LSB data bit, not the RDY status bit !
Besides the 3 or 4 byte transfer 'mode' there is also the choice of 'single conversion' and 'continuous conversion' mode. The behaviour of the RDY pin is different in both modes:
1) In the continuous mode the CS pin is always low and the RDY pin dynamically changes depending on the state of the internal conversion process.
2) In 'single conversion' mode the RDY pin shows the Ready state at the time of falling _CS edge. There are no dynamic updates of the RDY pin, in order to get a status update CS must be toggled high through low.
So, in 'single conversion' mode you can always read the RDY status by toggling the CS line, this is independent of reading the data with 3 or 4 byte transfers.
Although my posted code can be simplified by removing all lines referring to SSPEN, I guess it should work as it is. I don't have access to a MCP3551 chip to confirm this, so shoot and tell me if I'm wrong. ![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
das Guest
|
SPI Help |
Posted: Mon Dec 04, 2006 8:13 am |
|
|
I can change it to single conversion mode... I just need it to work ASAP. Can I see your code that you used to drive it in single conversion mode? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Mon Dec 04, 2006 8:16 am |
|
|
The more I read this part of the sheet, the more I am inclined to go back to my original statement, that you cannot (sensibly) use the 4 byte mode, for continuous conversions!.
The diagram that shows the status in the first bit, is from a mode with CS enabled, where the bit becomes available when CS is lowered, and is then clocked in as the first bit of the first byte. The description text for the two wire transfer (without CS), says that the RDY line activates one clock after 24 bits are transferred, and a transfer cannot be interrupted. As such then, four byte mode cannot be used this way. Look at paragraph 5.4.1. It is the only one that refers to the mode being used, and makes no mention of using a four byte transfer.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|