• AVR Freaks

Helpful ReplySPI Fail; PIC16F690 with ADT7301 Temp Sensor

Author
CNoob#1
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2013/02/09 14:34:36
  • Location: 0
  • Status: offline
2013/03/23 13:45:07 (permalink)
0

SPI Fail; PIC16F690 with ADT7301 Temp Sensor

(Well, the code tags won't seem to work, so I tried to edit that section manually.  Sorry for the mess.)
(MPLAB XC8)  
The SPI interface between my PIC16F690 MC (8 bit) and an ADT7301 (16 bit) temp sensor does not work.  The SSPBUF seems to be filled with ones (1s), because after the calculations are made, and the result is rounded down by conversion to integer, both the high byte and the low byte are seven (7).  The end result is a temperature of 2047.  Separately, either byte will read seven (7).  The last conversion is just there to make sprintf() easy to work with for now since %f doesn't seem to work in this situation (memory?).
 
http://www.analog.com/sta...ata_sheets/ADT7301.pdf
http://ww1.microchip.com/...n/DeviceDoc/41262c.pdf
 
I will post the relevant code (minus LCD sections which work) and the things I have tried.  Hopefully I write the code tags correctly!
 
I have tried two arbitrary binary numbers for MSByte and LSByte.  I've left them in this code.  The ADT7301 datasheet shows 10 C for the result, and this is what I get, so the code should be correct for that part.  When I try to read from the temp sensor with MSByte and LSByte, the result is 2047 C.  That appears to be 7.9+ multiplied by 32 (in the code), so it's likely that both bytes are being read as all ones (1s) = 255.
 
I added some code once to see if the buffer flag (BF) was changing after a read, and it did change from 1 to 0.  Anything else I've tried was mostly from samples of other SPI code or examples in a book.  I don't understand the timing and/or pauses that are sometimes needed, so there could be an error there.  I've checked the pins/wiring many times.  I tried all four combinations of clock polarity and clock edge.
 
I'm just trying hit and miss solutions now, so anything more specific would be welcome.
 
      
#pragma config FOSC = INTRCIO   // Oscillator Selection bit
#pragma config WDTE = OFF      // Watchdog Timer Enable bit
#pragma config PWRTE = OFF      // Power-up Timer Enable bit
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit
#pragma config CP = OFF         // Code Protection bit
#pragma config CPD = OFF        // Data Code Protection bit
#pragma config BOREN = ON       // Brown-out Reset Selection bits
#pragma config IESO = ON        // Internal External Switchover bit
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit  


#include <xc.h> // Include HITECH CC header file
#include <stdio.h>
#include <stdlib.h>

#ifndef _XTAL_FREQ // Unless specified elsewhere, 4MHz system frequency is assumed
#define _XTAL_FREQ 4000000
#endif

#define CS  RC6        // Define Slave Select as bit 6 on PORTC.
#define SDO RC7        // Define Serial Data Out as bit 7 on PORTC.
#define SDI RB4        // Define Serial Data In as bit 4 on PORTB.
#define SCK RB6        // Define SPI Clock as bit6 on PORTB.

//unsigned char b0;
unsigned int MSByte = 0, LSByte = 0;
long int ADC_Temp_Code;
float TempVal, ADC_Temp_Code_dec;
int TempValDec;

/* Function Prototypes*/
void pause(unsigned short usvalue);
void msecbase(void);
void Delay_5mS(void); 


//----------------------PROGRAM MEMORY----------------------
void Delay_5mS(void)
{   T0IF = 0;           //Make sure the T0IF is cleared.
     TMR0 = 100;         //Preload the TMR0 register.

    while (T0IF == 0);  //Sit here and wait for Timer0 to overflow.}

//******  PAUSE FUNCTION  *************************************************
void pause( unsigned short usvalue )    // Pause function
 
{
unsigned short x;
for (x=0; x<=usvalue; x++) // Loop through a delay equal to usvalue
{ // in milliseconds.               
msecbase(); // Jump to millisec delay routine.
}

//*******************************************************
void msecbase(void)                     // Msecbase function
{ OPTION_REG = 0b00000001;    // Set prescaler to TMRO 1:4
TMR0 = 0xD;                 // Preset TMRO to overflow on 250 counts
while(!T0IF);               // Stay until TMRO overflow flag equals 1
T0IF = 0;                   // Clear the TMR0 overflow flag}
main() {
    ANSEL   = 0; // Intialize ports as digital.   
ANSELH  = 0;
    CM1CON0 = 0; // Initialize Comparator 1 off.   
CM2CON0 = 0; // Initialize Comparator 2 off.
    PORTC = 0x00;   
PORTA = 0x00;
    CS     = 1;   
pause(10);
    TRISB6 = 0;
    TRISB4 = 1;
    /*SSPCON Settings*/   
SSPCON = 0b00000001;   
CKP    = 1;   
//CKP = 0;   
/*SSPSTAT Settings*/   
SMP = 1;   
CKE = 0;   
//CKE = 1;   
/*SPI Peripheral On*/   
SSPEN = 1;
while(1)
{
    ADC_Temp_Code = 0;   
/*Send and Recieve*/
    //while(1) {
    BF = 0;   
SSPIF = 0;       
CS     = 0;       
pause(10);       
SSPBUF = 0x00;
            while(!BF){}
                                 MSByte = SSPBUF;
                //MSByte = 0b00000001;
        SSPBUF = 0x00;
            while(!BF){}
                LSByte = SSPBUF;
                //LSByte = 0b01000000;
                ADC_Temp_Code = ((MSByte<<8) + LSByte);
                ADC_Temp_Code_dec = (float)ADC_Temp_Code;
                TempVal = ADC_Temp_Code_dec/32;
                TempValDec = (int)TempVal;
//while (1==1)
//{
    char str[16];
    sprintf(str, "Temp = %d", TempValDec);
        /*for(b0=0; b0<10; b0=b0+1)
        {
            lcd_putch (b0+number);
            pause(250);
        }*/
    lcd_goto(0x40);
    lcd_puts(str);
    pause(2000);//}
}
}

post edited by CNoob#1 - 2013/03/23 16:28:52
#1
CNoob#1
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2013/02/09 14:34:36
  • Location: 0
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2013/03/23 13:48:45 (permalink)
0
Ok, what is the correct code tag syntax?!
post edited by CNoob#1 - 2013/03/23 13:51:24
#2
GruntStripe
Super Member
  • Total Posts : 144
  • Reward points : 0
  • Joined: 2008/08/20 05:29:21
  • Location: nr Mold, Wales, UK
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2013/03/23 15:27:31 (permalink)
0
Hi,
Have you set the PORT data directions? (i.e.) TRIS registers.

I built your code and programmed a 16F6990. Single stepping through the code showed that CS = 1 was not happening. 
post edited by GruntStripe - 2013/03/23 15:29:08
#3
CNoob#1
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2013/02/09 14:34:36
  • Location: 0
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2013/03/23 15:40:01 (permalink)
0
I will check them over again and then focus on CS.  I changed it to a simple RC6 (SS pin-active low on the 7301) a few times, but still no luck.  I will focus on that for now, and if you notice anything else, please let me know.  I may have butchered that code, however, when I was manually editing in the post :(
 
Thanks!
#4
GruntStripe
Super Member
  • Total Posts : 144
  • Reward points : 0
  • Joined: 2008/08/20 05:29:21
  • Location: nr Mold, Wales, UK
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2013/03/23 16:13:52 (permalink)
0
Hi,
I think you have to clear TRISB6 as well...
 

 
Also, according to the data sheet all TRISB bits are set at POR so you don't need to set TRISB4 in main.
#5
CNoob#1
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2013/02/09 14:34:36
  • Location: 0
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2013/03/23 16:50:43 (permalink)
0
Sorry, I must have erased TRISB6 = 0; while I was trying to format the code in the forum.  I edited the original post.  
 
Now that I've read more about the value on POR, would it seem likely that I've never actually moved any data into or out of the temp sensor?  I don't know if there's much in the way of debugging with the free HiTech C compiler/PICkit3 setup, so how could I check to see if I'm enabling SS and moving any data?
 
I'm not very confident in the clock settings, either:  frequency, polarity, and edge.
 
Another thing that is very odd is that I can find various forum posts from people reading all zeros (0s) from SSPBUF, but I've managed to come up with all ones (1s).  I must be exceptionally incompetent! :(
post edited by CNoob#1 - 2013/03/23 17:32:05
#6
GruntStripe
Super Member
  • Total Posts : 144
  • Reward points : 0
  • Joined: 2008/08/20 05:29:21
  • Location: nr Mold, Wales, UK
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2013/03/23 19:05:07 (permalink) ☄ Helpful
0
Hi,
I don't have an ADT7301 so can't duplicate your setup exactly. So, I set up an 18F2420 as a slave and made it transmit two bytes with the same values as you used in your code.
It sends data ok to the 16F690 running your code.
I'll post your code as I've used it and, just for clarity the 2420 code.
No idea if any of it will be a help to you! Smile
  Edit: I didn't use the CS function. Will set that up and try it.

/*01:45 24 March 2013      
* E:\Electronics\PIC Projects\MCP Forum\cNoob#1\SPI Fail\Source\Main.c
*
*
*
*/

 #include <xc.h>                // Include HITECH CC header file
 #include <stdio.h>
 #include <stdlib.h>

/*------------------------------------------------------------------------*/

#pragma config FOSC = INTRCIO   // Oscillator Selection bit
#pragma config WDTE = OFF      // Watchdog Timer Enable bit
#pragma config PWRTE = OFF      // Power-up Timer Enable bit
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit
#pragma config CP = OFF         // Code Protection bit
#pragma config CPD = OFF        // Data Code Protection bit
#pragma config BOREN = ON       // Brown-out Reset Selection bits
#pragma config IESO = ON        // Internal External Switchover bit
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit

/*------------------------------------------------------------------------*/
#define _XTAL_FREQ (4000000)     /* Not using xtal, only to make delays work as
                                   it won't compile without this */

#define CS  RC6     // Define Slave Select as bit 6 on PORTC.
#define SDO RC7     // Define Serial Data Out as bit 7 on PORTC.
#define SDI RB4     // Define Serial Data In as bit 4 on PORTB.
#define SCK RB6     // Define SPI Clock as bit6 on PORTB.

//unsigned char b0;
unsigned int MSByte = 0, LSByte = 0;
long int ADC_Temp_Code;
float TempVal, ADC_Temp_Code_dec;
int TempValDec;

/* Function Prototypes*/
void pause(unsigned short usvalue);
void msecbase(void);
void Delay_5mS(void);


 //----------------------PROGRAM MEMORY----------------------
 void Delay_5mS(void) 
 {   T0IF = 0;           //Make sure the T0IF is cleared.
      TMR0 = 100;         //Preload the TMR0 register.

     while (T0IF == 0);  //Sit here and wait for Timer0 to overflow.
     } 

 //******  PAUSE FUNCTION  *************************************************
 void pause( unsigned short usvalue )   // Pause function  

{
    unsigned short x;
    for (x=0; x<=usvalue; x++)          // Loop through a delay equal to usvalue
    {                                   // in milliseconds.
        msecbase();                     // Jump to millisec delay routine.
        }
}
//*******************************************************
void msecbase(void)                  // Msecbase function
{
    OPTION_REG = 0b00000001;    // Set prescaler to TMRO 1:4
    TMR0 = 0xD;                 // Preset TMRO to overflow on 250 counts
    while(!T0IF);               // Stay until TMRO overflow flag equals 1
    T0IF = 0;                   // Clear the TMR0 overflow flag
}

void main(void)
{
    OSCCON  = 0b01100000;   // MY ADDITION FOR CLARITY
    ANSEL   = 0;            // Intialize ports as digital.
    ANSELH  = 0;
    CM1CON0 = 0;            // Initialize Comparator 1 off.
    CM2CON0 = 0;            // Initialize Comparator 2 off.
    PORTA   = 0x00;
    PORTC   = 0x00;
    //TRISC = 0x0;
    TRISB6 = 0;             // RB6 = SCK
    TRISC6 = 0;             // RC6 = CS
    /* TRISB = 0xF0 at power up i.e. RB<7-4> auto configured as inputs */
    //TRISB4 = 1;           // RB4 = SDI

    CS  = 1;
    pause(10);

    /*SSPCON Settings*/
    SSPCON = 0b00000001;
    CKP = 0;                // Clock polarity
    SSPEN = 1;              /*SPI Peripheral On*/

    /*SSPSTAT Settings*/
    SMP = 1;                // Data sampled at end of output time
    CKE = 0;                // Data transmitted on falling edge of SCK


while(1)
{
    ADC_Temp_Code = 0;

    /*Send and Recieve*/

    //BF = 0;
    //SSPIF = 0;

    SSPBUF = 0xAA;          // Write to buffer to clk data in
    while(!BF){}
    MSByte = SSPBUF;

    SSPBUF = 0x0F;          // Write to buffer to clk data in
    while(!BF){}
    LSByte = SSPBUF;

    ADC_Temp_Code       = ((MSByte<<8) + LSByte);
    ADC_Temp_Code_dec   = (float)ADC_Temp_Code;
    TempVal             = ADC_Temp_Code_dec/32;
    TempValDec          = (int)TempVal;

     //__delay_ms(100); DEBUGGING

 }
 }

 
2420 code:
 
/*       
 * File:   2420 Tx main.c
 * Author: Me
 *
 * Created on 26 December 2012, 09:11
 * Schematic: PIC to PIC SPI V1.sch
 */

#include <xc.h>

/*------------------------------------------------------------------------*/

#pragma config CONFIG1H = 0X08;
#pragma config CONFIG2L = 0X19;
#pragma config CONFIG2H = 0X1E;
#pragma config CONFIG3H = 0X81; // MCLRE = off is ?
#pragma config CONFIG4L = 0X80;
#pragma config CONFIG5L = 0X0F;
#pragma config CONFIG5H = 0XC0;
#pragma config CONFIG6L = 0X0F;
#pragma config CONFIG6H = 0XE0;
#pragma config CONFIG7L = 0X0F;
#pragma config CONFIG7H = 0X40;

/*------------------------------------------------------------------------*/

#define _XTAL_FREQ (4000000)     /* Not using xtal, only to make delays work as
                                   it won't compile without this */

#define rx_buffer_full  (SSPSTATbits.BF)

/*------------------------------------------------------------------------*/

char    null_data;
char    High_byte;
char    Low_byte;
/*------------------------------------------------------------------------*/

void SPI_init (void);

/*------------------------------------------------------------------------*/
void main (void)
{

OSCCON = 0b01100010;            // Fosc = 4MHz (Inst. clk = 1MHz)
ADCON1 = 0xF;                   // No analog, all digital i/o
TRISA = 0x00;                   // DIL switch inputs
TRISB = 0x0;                    // Button input
TRISC = 0x0;
TRISC3 = 1; // SLAVE
LATA = 0x0;
LATB = 0x0;
LATC = 0x0;

SPI_init();                     // Set up the SPI

/********* Start of main program loop **********/
 while(1)
{
        SSPBUF = 0b00000001;
        while (!rx_buffer_full)     // Wait until buffer is full (tx done)
            if (SSPCON1bits.SSPOV)
            {
                SSPCON1bits.SSPOV = 0;
            }
        null_data = SSPBUF;         // Read buffer to clear BF flag

        SSPBUF = 0b01000000;
        while (!rx_buffer_full)     // Wait until buffer is full (tx done)
            if (SSPCON1bits.SSPOV)
            {
                SSPCON1bits.SSPOV = 0;
            }
        null_data = SSPBUF;         // Read buffer to clear BF flag

 }
}

void SPI_init (void)
{
    SSPSTAT = 0b00000000;      // b7 = SMP: Sample bit
                                // b6 = CKE: SPI ClK Select bit !!!!!!!!!!
                                // b5-1 = I2C mode only
                                // b0 = BF: Buffer Full Status bit

    SSPCON1 = 0b00100101;      // b7 = WCOL: Write collision detect
                                // b6 = SSPOV: Receive Overflow Indicator bit
                                // b5 = SSPEN: Synchronous Serial Port Enable
                                // b4 = CKP: Clock Polarity Select
                                // b3-0 = SSPM: Synchronous Serial Port Mode Select bits


    TRISCbits.TRISC5 = 0;       // [pic pin16] SPI data out
    TRISCbits.TRISC3 = 1;       // [pic pin14] SPI clock in

}


 
Two bytes, clock is 16f690, bytes are transmitted from 2420;

 
 
Good luck!
post edited by GruntStripe - 2013/03/23 19:16:36
#7
CNoob#1
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2013/02/09 14:34:36
  • Location: 0
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2013/03/23 19:30:53 (permalink)
0
Wow!! That definitely gives me some encouragement grin  Since you have a working model AND you understand the datasheets, can you please clarify one thing for me?
 
The datasheet for the ADT7301 shows pin connections to a PIC16 as Dout(pin 6) to SDO(PIC 16 MC) and Din(pin 2) to SDI(PIC 16 MC).  While I was researching how SPI works, I only saw master/slave examples where an SDO on one chip connected to the SDI on the other, and vice versa.  I was so confused that I tried switching the in/out connections on my circuit, and then I got a zero rather than 2047.  So, it's either all 1s or all 0s.  
 
I'll look at your code some more and keep looking at my code and pinouts.  You gave me some hope, at least!...lol
#8
GruntStripe
Super Member
  • Total Posts : 144
  • Reward points : 0
  • Joined: 2008/08/20 05:29:21
  • Location: nr Mold, Wales, UK
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2013/03/23 19:48:42 (permalink)
0
Hi,
Just had a quick peek at the ADT data sheet. I think they show the interconnections wrongly. DOUT must go to SDI and DIN to SDO. I would have thought so anyway.
#9
GruntStripe
Super Member
  • Total Posts : 144
  • Reward points : 0
  • Joined: 2008/08/20 05:29:21
  • Location: nr Mold, Wales, UK
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2013/03/23 20:59:47 (permalink)
0
Hi,
Also noticed in the ADT data sheet example that the clock should idle high, so CKP (PIC) should = 1.
 
post edited by GruntStripe - 2013/03/23 22:01:10
#10
CNoob#1
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2013/02/09 14:34:36
  • Location: 0
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2013/03/24 05:34:33 (permalink)
+2 (1)
OMG!!  OMG!!  I was up at 5:00 a.m. to tackle this again.  This time I looked over the modifications you made to my code in your post, and I switched the pins opposite of what the ADT7301 datasheet shows (why didn't I trust myself from the start?).
 
Instead of one-shot change-and-compile runs, I did everything at once and....IT'S WORKING!!!!!
 
I know I'm still on thin ice 'cause I'm not sure which piece(s) of code are the triggers, but after a month of bashing my brain on just this one problem, I DON"T CARE...lol
 
Thank you so very much!! Smile  I need to split the circuit apart now, and add transceivers.  I was hoping to store data on an SD card, too.  Care to be my mentor? wink
#11
CNoob#1
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2013/02/09 14:34:36
  • Location: 0
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2013/03/24 05:37:28 (permalink)
0
Yes, that part I didn't change.  At least the datasheet code example had that correct.
#12
GruntStripe
Super Member
  • Total Posts : 144
  • Reward points : 0
  • Joined: 2008/08/20 05:29:21
  • Location: nr Mold, Wales, UK
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2013/03/24 05:43:54 (permalink)
0
Hi,
 
Glad you've made progress! Good feeling isn't it when things start working wink
Never used an SD card with PIC, so if you get it going let me know. I might learn something from you!
 
Regards, GS
#13
Dennis1010
New Member
  • Total Posts : 5
  • Reward points : 0
  • Joined: 2018/12/23 06:28:56
  • Location: 10
  • Status: offline
Delete the post 2019/01/09 09:21:15 (permalink)
0
please delete me
post edited by Dennis1010 - 2019/01/11 10:52:53
#14
mbrowning
USNA79
  • Total Posts : 1741
  • Reward points : 0
  • Joined: 2005/03/16 14:32:56
  • Location: Melbourne, FL
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2019/01/10 11:08:21 (permalink)
0 (2)
Aside from the thread highjack, why do you suppose that a Microchip forum would have an answer for a problem with a TI microcontroller and an Analog Devices sensor?
#15
MBedder
Circuit breaker
  • Total Posts : 6876
  • Reward points : 0
  • Joined: 2008/05/30 11:24:01
  • Location: Zelenograd, Russia
  • Status: offline
Flagged as Spam (1)
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2019/01/10 11:24:27 (permalink)
0 (2)
Dennis1010I can not post anything in the Forum (because Access Denied)
It's correct because access is definitely denied for the idiots.


#16
mbrowning
USNA79
  • Total Posts : 1741
  • Reward points : 0
  • Joined: 2005/03/16 14:32:56
  • Location: Melbourne, FL
  • Status: offline
Re:SPI Fail; PIC16F690 with ADT7301 Temp Sensor 2019/01/10 11:34:16 (permalink)
0 (2)
MBedder
because access is definitely denied for the idiots.

We wish !
#17
Jump to:
© 2020 APG vNext Commercial Version 4.5