CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

SPI problem (PIC18F252 + MAX6682)
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
khalis



Joined: 12 Feb 2009
Posts: 54

View user's profile Send private message

SPI problem (PIC18F252 + MAX6682)
PostPosted: Thu Feb 12, 2009 9:38 pm     Reply with quote

Hi,
Recently I tried to interface the max6682 with pic(18F252) using spi mode. Unfortunately, what I can see on the desktop through the hyperterminal was just displayed ' 0 '. For information, I was trying to retrieve 10bit data from the max6682 and display it on PC.

The recent coding that I used as below:
Code:
#include <18F252.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, bits=8)
#byte PORTA = 5
#byte PORTB = 6
#byte PORTC = 7

void main()
{
byte incode;

setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16);

while(1)
  {
    set_tris_c(0x90);
    incode = spi_read(); // Read character from UART
    printf( " Thermocouple Reading = %d ",incode); // Display it on
    putc(13);
    delay_ms(1000);
  }

}
Ttelmah
Guest







PostPosted: Fri Feb 13, 2009 3:25 am     Reply with quote

Some comment:

First, though you are not using them, you have definitions for PORTA etc., that are _wrong_. The values you have are for a 16 chip, not a 18 chip. These need fixing.

Second, you are trying to operate the 6682, without using CS. You _need_ to connect the CS line. The 6682, actually outputs 11bit data, and then tri-states the output line. The way you read it with a chip (like the PIC), that only supports 8bit clocking for SPI, is to lower the CS line, perform two 8bit transfers, and then raise the CS line. If you put the result into a signed 16bit integer, and then divide it by 32, you get the ten bit result _and sign_ correctly presented.

The SPI bus for this chip, needs to have the clock idle low, and read the data on the rising edge of the clock pulse. In SPI 'mode numbers', this is Mode0_0. Pull the posted mode number conversions from here (I think it was Ckielstra who first posted these), and use them. You need:
SPI_L_TO_H | SPI_XMIT_L_TO_H

For this chip.

As currently written (without CS), you will only get one and a third bytes at the start, containing anything 'useful', after this, the bus will go idle, and the display will depend totally on whether the data line floats high or low.

Best Wishes
khalis



Joined: 12 Feb 2009
Posts: 54

View user's profile Send private message

Need more explanations
PostPosted: Fri Feb 13, 2009 7:15 pm     Reply with quote

Thank you for your advise but if you don't mind, could you give a simple coding for me to follow..i'm new in c programming..thanks..
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Feb 14, 2009 2:22 am     Reply with quote

Look at the code in this post. It has some of the things that Ttelmah
has mentioned. For example, it sets the Chip Select signal low while
the SPI read operations are in progress. It has an spi_write() line
which is not needed by the MAX6682 (and should be removed for your
code). It combines the two bytes with a make16() function. It does not
do the division by 32 which Ttelmah mentions. You need to add that.

You should read Ttelmah's post and look at the timing diagram on page 6 of the MAX6682 data sheet. Then try to write the code yourself.
It's better for you to learn by doing it that way.
http://www.ccsinfo.com/forum/viewtopic.php?t=27833&start=2
khalis



Joined: 12 Feb 2009
Posts: 54

View user's profile Send private message

PostPosted: Sat Feb 14, 2009 11:37 pm     Reply with quote

First of all...i would to thank for the reply..i finally understand to use write spi coding...this is my first trial using spi and i'm very excited today..the coding that i used as below...

Code:
#include <18F252.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, bits=8)

void main()
{
int8 lsb;
int8 msb;
int16 result1;
set_tris_c(0b10110110);
output_high(PIN_C0);
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_64);

   while(1)
   {
   output_low(PIN_C0);
   msb = spi_read(0x00);     
   lsb = spi_read(0x00);   
   output_high(PIN_C0);

   result1 = make16(msb, lsb);
   printf("Thermistor Value = %Lx\n\r", result1);
   delay_ms(1000);
   }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Feb 15, 2009 12:29 am     Reply with quote

Quote:
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_64);

Ttelmah said that you need to use SPI mode 0 with the MAX6682.
You should add these #define statements above main():
Code:
// SPI modes
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

Then do your setup_spi() statement like this:
Code:
setup_spi(SPI_MASTER | [b]SPI_MODE_0[/b] | SPI_CLK_DIV_4);
 

According to the MAX6682 data sheet, the maximum SCLK frequency
is 5 MHz. 20 MHz / 4 = 5 Mhz. You don't need to divide by 64. Dividing
the crystal frequency by 4 will work. If you want to be conservative,
you can divided it by 16, and use SPI_CLK_DIV_16.


Quote:
set_tris_c(0b10110110);

You don't need to set the TRIS. The compiler will set it for you, if you use
the CCS library code and CCS pin i/o statements (which you are doing).
You can delete this line.


Quote:

result1 = make16(msb, lsb);
printf("Thermistor Value = %Lx\n\r", result1);

Ttelmah said that you should put the result in a signed int16 variable, and
then divide it by 32. So your code really should be changed to this:
Quote:

signed int16 result1;
.
.
.
result1 = make16(msb, lsb);
printf("Thermistor Value = %Lx\n\r", result1 / 32);
khalis



Joined: 12 Feb 2009
Posts: 54

View user's profile Send private message

PostPosted: Sun Feb 15, 2009 12:56 am     Reply with quote

[SPI_MODE_0]

what does it means by the letter of 'b' in this code SPI_MODE_0 [/quote]
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Feb 15, 2009 1:05 am     Reply with quote

That was supposed to put in it "bold" print. But, I put the line in
a Code block by mistake. Features such as bold and italics don't
work in code block. This is what I intended it to be:
Quote:
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_4);
khalis



Joined: 12 Feb 2009
Posts: 54

View user's profile Send private message

PostPosted: Sun Feb 15, 2009 1:31 am     Reply with quote

O..i see...one more thing, we know that output comes out on display is in hex value..is there a way to convert the value into decimal
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Feb 15, 2009 2:17 am     Reply with quote

Quote:
Is there a way to convert the value into decimal ?

Use "%Ld" instead of "%Lx".
khalis



Joined: 12 Feb 2009
Posts: 54

View user's profile Send private message

PostPosted: Sun Feb 15, 2009 4:34 am     Reply with quote

I have tried the %Ld to display the result into decimal..and when i tried to multiply the decimal data with 0.125..the result became 0.. Question
khalis



Joined: 12 Feb 2009
Posts: 54

View user's profile Send private message

PostPosted: Sun Feb 15, 2009 5:37 am     Reply with quote

Below the update coding that i made to display decimal

Code:
#include <18F252.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, bits=8)

// SPI modes
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

void main()
{
int8 lsb;
int8 msb;
signed int16 result1;
signed int16 result2;

output_high(PIN_C0);
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_4);

   while(1)
   {
   output_low(PIN_C0);
   msb = spi_read(0x00);     
   lsb = spi_read(0x00);   
   output_high(PIN_C0);

   result1 = make16(msb, lsb);
   result2 = (result1 / 32)*125; 
   delay_ms(500);
   printf("Thermistor Value  Actual = %Ld   Final(x120) = %Ld\n\r",result1,result2);
   delay_ms(1000);
   }
}
khalis



Joined: 12 Feb 2009
Posts: 54

View user's profile Send private message

PostPosted: Sun Feb 15, 2009 5:43 am     Reply with quote

Is it possible to calculate and display the final result ex : 27.125 , 26.125?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Feb 15, 2009 10:08 am     Reply with quote

Change the declaration of result2 to 'float', instead of signed int16.

Then change the 32 to a floating point value as shown below:
Quote:
result2 = (result1 / 32.0) * 125;


Then use "%7.3f" in printf to display result2.
Ttelmah
Guest







PostPosted: Sun Feb 15, 2009 10:21 am     Reply with quote

Or, probably faster, and smaller, consider doing:

Code:

signed int32 result2; //Make this large enough to store value * 3200

result2 = ((int32)result1 * 12500)/ 32;



Then use "%7.2w" to display result2.

This handles result2 as an int32 value, holding the required number * 100. Arithmetic for int32, is faster than floating point, typically perhaps 50% (and a lot faster for the division by 32), and uses CCS's ability to display this as a scaled value to give the required result.

As with most things, there are actually dozens of possible 'solutions'. Smile

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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