/*********************************************************************** Thermo Sensor*********************************************************************** FileName: temperature.c* Dependencies: See INCLUDES section below* Processor: PIC18* Compiler: C18 2.30.01+* Company: Microchip Technology, Inc.** Software License Agreement** The software supplied herewith by Microchip Technology Incorporated* (the Company) for its PICmicro® Microcontroller is intended and* supplied to you, the Companys customer, for use solely and* exclusively on Microchip PICmicro Microcontroller products. The* software is owned by the Company and/or its supplier, and is* protected under applicable copyright laws. All rights are reserved.* Any use in violation of the foregoing restrictions may subject the* user to criminal sanctions under applicable laws, as well as to* civil liability for the breach of the terms and conditions of this* license.** THIS SOFTWARE IS PROVIDED IN AN AS IS CONDITION. NO WARRANTIES,* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.*********************************************************************//** I N C L U D E S **********************************************************/#include "Compiler.h"#include "GenericTypeDefs.h"#include "HardwareProfile.h"#include "temperature.h"#if defined(__18CXX)#include <spi.h>#endif/** V A R I A B L E S ********************************************************/#pragma udataunsigned int I2CStateVariable; // Used for keeping track of the I2C state// machine when using the HPC Explorer board's// I2C based TC74 temperature sensor.signed char TempAccumulator; // Used for averaging temperature samplessigned char TempSave;WORD_VAL temperature; // Raw data formatchar tempString[10]; // Buffer for storing data in ASCII format/** P R I V A T E P R O T O T Y P E S ***************************************//** D E C L A R A T I O N S **************************************************/#pragma code/******************************************************************************* Function: void InitTempSensor(void)** PreCondition: None** Input: None** Output: None** Side Effects: None** Overview: Initializes SPI interface & chip select line** Note: None*****************************************************************************/void InitTempSensor(void){#if defined(PICDEM_FS_USB)cs_temp_sensor = 1;tris_cs_temp_sensor = OUTPUT_PIN;OpenSPI(SPI_FOSC_64, MODE_11, SMPMID);// Initialize readable values - default to room temperaturetemperature.Val = 0x0C87; // 25 degree celsiusUpdateCelsiusASCII();#elif defined(PIC18F87J50_PIM)temperature.Val = 0x0C87; // 25 degree celsiusUpdateCelsiusASCII();//Need to initialize I2C Module to prepare for communication with//TC74 temperature sensor on the HPC Explorer board.mInitI2CPins(); // See io_cfg.hSSP1STAT = 0xC0; // Slew rate control disabled, SMBusSSP1CON1 = 0x08; // I2C Master modeSSP1CON2 = 0x00;SSP1ADD = 0x7D; // Just under 100kHz at 48MHz core frequencySSP1CON1bits.SSPEN = 1; // Enable MSSP moduleI2CStateVariable = 0; // Initial state for I2C state machine#endif}//end InitTempSensor/******************************************************************************* Function: void AcquireTemperature(void)** PreCondition: None** Input: None** Output: None** Side Effects: None** Overview: None** Note: None*****************************************************************************/BOOL AcquireTemperature(void){#if defined(PICDEM_FS_USB)//The PICDEM FS USB Demo Board uses a TC77 (13 bit) temperature sensor and//communicates with it through the SPI interface.cs_temp_sensor = 0;temperature.v[1] = ReadSPI();temperature.v[0] = ReadSPI();cs_temp_sensor = 1;if(temperature.bits.b2 == 0)return FALSE;#elif defined(__C30__) || defined(__C32__)//Create temp variables to store the conversion datafloat temp;//get ready to sample the A/D#if defined(__C30__)AD1CHS = 0x4; //MUXA uses AN4AD1PCFGLbits.PCFG4 = 0;for(temp=0;temp<1000;temp++); //Sample delay// Get an ADC sampleAD1CON1bits.SAMP = 1; //Start samplingfor(temp=0;temp<1000;temp++); //Sample delay, conversion start automaticallyAD1CON1bits.SAMP = 0; //Start samplingfor(temp=0;temp<1000;temp++); //Sample delay, conversion start automaticallywhile(!AD1CON1bits.DONE); //Wait for conversion to complete#elseAD1PCFGbits.PCFG4 = 0;AD1CON1 = 0x0000; // SAMP bit = 0 ends sampling ...// and starts convertingAD1CHS = 0x00040000; // Connect RB4/AN4 as CH0 input ..// in this example RB2/AN2 is the inputAD1CSSL = 0;AD1CON3 = 0x0002; // Manual Sample, Tad = internal 6 TPBAD1CON2 = 0;AD1CON1SET = 0x8000; // turn ADC ONAD1CON1SET = 0x0002; // start sampling ...for(temp=0;temp<1000;temp++); //Sample delay, conversion start automaticallyAD1CON1CLR = 0x0002; // start Convertingwhile (!(AD1CON1 & 0x0001));// conversion done?#endif//convert the results to a floattemp = (float)ADC1BUF0;// voltage = A2D_reading * 3.3v / 1024temp *= 3.3;temp /= 1024;// align to 0C (subtracting -.65v)temp -= .55;//convert to TC77 style output and store to temperaturetemp *= 12800;temperature.Val = (WORD)temp;temperature.Val |= 0x7;//#elif defined(__C32__)//#warning "TODO"#elif defined(PIC18F87J50_PIM) // Uses TC74 (8 bit)//The PIC18F87J50 FS USB Plug-In Module (PIM) does not have a temperature//sensor, but there is a TC74 (8 bit) I2C based temperature sensor on the//HPC Explorer demo board. In order for this temperature demo code to do//anything useful, the PIM should be used in conjunction with the HPC Explorer.//The TC74 comes in 5V and 3.3V optimized versions. If a 5V part is run at//3.3V (as with the PIM installed), it may have relatively large offsets.return TRUE; // Don't need to do anything in this function, temperature// polling with the PIC18F87J50 FS USB Plug-In Module is// done with the PollTempOnHPCExplorer() function.// This is done so the I2C communication can be done with// a non-blocking approach.#elif defined(LOW_PIN_COUNT_USB_DEVELOPMENT_KIT)temperature.Val = 0x0000;return TRUE;#elif defined(PIC18F46J50_PIM)//Create temp variables to store the conversion datafloat temp;//get ready to sample the A/DADCON0bits.CHS = 0x07;for(temp=0;temp<1000;temp++){}ADCON0bits.GO = 1; // Start AD conversionwhile(ADCON0bits.NOT_DONE); // Wait for conversion//convert the results to a floattemp = (float)ADRES;// voltage = A2D_reading * 3.3v / 1024temp *= 3.3;temp /= 1024;// align to 0C (subtracting -.65v)temp -= .55;//convert to TC77 style output and store to temperaturetemp *= 12800;temperature.Val = (WORD)temp;temperature.Val |= 0x7;return TRUE;#else#error "Unknown temperature acquire configuration. See AcquireTemperature function in __FILE__"#endifreturn TRUE;}//end AcquireTemperature/******************************************************************************* Function: void PollTempOnHPCExplorer(void)** PreCondition: None** Input: None** Output: Temperature data from TC74 on HPC Explorer, but formatted* like the TC77, stored in the "temperature" variable.* Side Effects: None** Overview: None** Note: None*****************************************************************************/#if defined(PIC18F87J50_PIM)void PollTempOnHPCExplorer(void){//The PIC18F87J50 FS USB Plug-In Module (PIM) does not have a temperature//sensor, but there is a TC74 (8 bit) I2C based temperature sensor on the//HPC Explorer demo board. In order for this temperature demo code to do//anything useful, the PIM must be used in conjunction with the HPC Explorer.//The TC74 comes in 5V and 3.3V optimized versions. If a 5V part is run at//3.3V (as with the PIM installed), it may have relatively large offsets.#define TC74AddressWrite 0b10011010 // This is the default address for the TC74, use this for writes#define TC74AddressRead 0b10011011 // This is the default address for the TC74, use this for reads#define RTR 0x00 // This is the read temp command for TC74// Should not use blocking functions in USB code. Therefore, these I2C// communications are done with a state machine as shown below.switch(I2CStateVariable){case 0x00:PIR1bits.SSP1IF = 0;SSP1CON2bits.SEN = 1; // Send Start BitI2CStateVariable = 0x01;break;case 0x01:if(PIR1bits.SSP1IF == 0) {break;}PIR1bits.SSP1IF = 0;SSP1BUF = TC74AddressWrite; // Begin sending the actual addressI2CStateVariable = 0x02;break;case 0x02:if(PIR1bits.SSP1IF == 0) {break;}PIR1bits.SSP1IF = 0;SSP1BUF = RTR; // Send command to select the TEMP registerI2CStateVariable = 0x03;break;case 0x03:if(PIR1bits.SSP1IF == 0) {break;}PIR1bits.SSP1IF = 0;SSP1CON2bits.SEN = 1; // Send another start bitI2CStateVariable = 0x04;break;case 0x04:if(PIR1bits.SSP1IF == 0) {break;}PIR1bits.SSP1IF = 0;SSP1BUF = TC74AddressRead; // Send the address again, but this time "read"I2CStateVariable = 0x05;break;case 0x05:if(PIR1bits.SSP1IF == 0) {break;}PIR1bits.SSP1IF = 0;SSP1CON2bits.RCEN = 1; // Initiate read from deviceI2CStateVariable = 0x06;break;case 0x06:if(PIR1bits.SSP1IF == 0) {break;}PIR1bits.SSP1IF = 0;TempSave = SSP1BUF; // Finally got the result, need to save itSSP1CON2bits.ACKDT = 1; // Prepare I2C NACK handshakeSSP1CON2bits.ACKEN = 1; // Send the acknowledge bitI2CStateVariable = 0x07;break;case 0x07:if(PIR1bits.SSP1IF == 0) {break;}PIR1bits.SSP1IF = 0;SSP1CON2bits.PEN = 1; // Now send a stop bitI2CStateVariable = 0x08;break;case 0x08:if(PIR1bits.SSP1IF == 0) {break;}PIR1bits.SSP1IF = 0;I2CStateVariable = 0x09;break;case 0x09:TempAccumulator = ((TempAccumulator + TempSave) / 2); // Get an averageI2CStateVariable = 0x10;break;case 0x10://Now format data like that of the TC77, which is what the PC side code expects,//since it was originally intended to be used with the TC77.temperature.v[1] = TempAccumulator;if(temperature.bits.b15 == 0) // == 0 when positive temperature{temperature.Val = temperature.Val >> 1;temperature.bits.b15 = 0; // Positive temperature, upper MSb clear}else{temperature.Val = temperature.Val >> 1;temperature.bits.b15 = 1; // Negative temperature, upper MSb set}temperature.bits.b0 = 1; // Lower three LSbs = 1 on TC74 formattemperature.bits.b1 = 1; // Lower three LSbs = 1 on TC74 formattemperature.bits.b2 = 1; // Lower three LSbs = 1 on TC74 formatI2CStateVariable = 0x11; // Could go back to 0, but don't want to poll that fastbreak;case 0x5000: // This slows down the sample rate of the device.I2CStateVariable = 0x00; // The temp sensor itself only updates around 8 times/sec.break;default:I2CStateVariable++;break;}//end switch}//end PollTempOnHPCExplorer#endif/******************************************************************************* Function: void UpdateCelsiusASCII(void)** PreCondition: None** Input: None** Output: None** Side Effects: None** Overview: This routine converts data output to ASCII string** Note: None*****************************************************************************/void UpdateCelsiusASCII(void){WORD_VAL temp;BYTE i;temp.Val = temperature.Val >> 3;if(temp.bits.b12 == 0){temp.byte.HB &= 0x1F;tempString[0] = '+';}else{temp.byte.HB |= 0xE0;tempString[0] = '-';temp.Val = temp.Val ^ 0xFFFF; // Negatetemp.Val++;}//end iftemp.Val = (temp.Val*10U) >> 4; // Turn into celsius xx.x/* Populate string */for(i=4;i>0;i--){tempString[i] = (((char)(temp.Val % 10)) & 0x0F) | 0x30;temp.Val /= 10;}//end for/* Turn leading zeros into spaces */if(tempString[1] == '0'){tempString[1] = ' ';if(tempString[2] == '0')tempString[2] = ' ';}//end if/* Adjust decimal digit */tempString[5] = tempString[4];tempString[4]='.';tempString[6]=0xF8; // Degree symboltempString[7]='C';tempString[8]='\r';tempString[9]=0x00; // Null-Terminated}//end UpdateCelsiusASCII/** EOF temperature.c ********************************************************/