0,0 → 1,412 |
/********************************************************************* |
* |
* 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 udata |
unsigned 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 samples |
signed char TempSave; |
WORD_VAL temperature; // Raw data format |
char 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 temperature |
temperature.Val = 0x0C87; // 25 degree celsius |
UpdateCelsiusASCII(); |
|
#elif defined(PIC18F87J50_PIM) |
temperature.Val = 0x0C87; // 25 degree celsius |
UpdateCelsiusASCII(); |
|
//Need to initialize I2C Module to prepare for communication with |
//TC74 temperature sensor on the HPC Explorer board. |
mInitI2CPins(); // See io_cfg.h |
SSP1STAT = 0xC0; // Slew rate control disabled, SMBus |
SSP1CON1 = 0x08; // I2C Master mode |
SSP1CON2 = 0x00; |
SSP1ADD = 0x7D; // Just under 100kHz at 48MHz core frequency |
SSP1CON1bits.SSPEN = 1; // Enable MSSP module |
|
I2CStateVariable = 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 data |
float temp; |
|
//get ready to sample the A/D |
|
#if defined(__C30__) |
AD1CHS = 0x4; //MUXA uses AN4 |
AD1PCFGLbits.PCFG4 = 0; |
for(temp=0;temp<1000;temp++); //Sample delay |
// Get an ADC sample |
AD1CON1bits.SAMP = 1; //Start sampling |
for(temp=0;temp<1000;temp++); //Sample delay, conversion start automatically |
AD1CON1bits.SAMP = 0; //Start sampling |
for(temp=0;temp<1000;temp++); //Sample delay, conversion start automatically |
while(!AD1CON1bits.DONE); //Wait for conversion to complete |
|
#else |
AD1PCFGbits.PCFG4 = 0; |
|
AD1CON1 = 0x0000; // SAMP bit = 0 ends sampling ... |
// and starts converting |
AD1CHS = 0x00040000; // Connect RB4/AN4 as CH0 input .. |
// in this example RB2/AN2 is the input |
AD1CSSL = 0; |
AD1CON3 = 0x0002; // Manual Sample, Tad = internal 6 TPB |
AD1CON2 = 0; |
AD1CON1SET = 0x8000; // turn ADC ON |
|
AD1CON1SET = 0x0002; // start sampling ... |
for(temp=0;temp<1000;temp++); //Sample delay, conversion start automatically |
AD1CON1CLR = 0x0002; // start Converting |
while (!(AD1CON1 & 0x0001));// conversion done? |
#endif |
|
//convert the results to a float |
temp = (float)ADC1BUF0; |
|
// voltage = A2D_reading * 3.3v / 1024 |
temp *= 3.3; |
temp /= 1024; |
|
// align to 0C (subtracting -.65v) |
temp -= .55; |
|
//convert to TC77 style output and store to temperature |
temp *= 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 data |
float temp; |
|
//get ready to sample the A/D |
ADCON0bits.CHS = 0x07; |
for(temp=0;temp<1000;temp++){} |
ADCON0bits.GO = 1; // Start AD conversion |
while(ADCON0bits.NOT_DONE); // Wait for conversion |
|
//convert the results to a float |
temp = (float)ADRES; |
|
// voltage = A2D_reading * 3.3v / 1024 |
temp *= 3.3; |
temp /= 1024; |
|
// align to 0C (subtracting -.65v) |
temp -= .55; |
|
//convert to TC77 style output and store to temperature |
temp *= 12800; |
temperature.Val = (WORD)temp; |
temperature.Val |= 0x7; |
|
return TRUE; |
#else |
#error "Unknown temperature acquire configuration. See AcquireTemperature function in __FILE__" |
#endif |
return 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 Bit |
I2CStateVariable = 0x01; |
break; |
case 0x01: |
if(PIR1bits.SSP1IF == 0) {break;} |
PIR1bits.SSP1IF = 0; |
SSP1BUF = TC74AddressWrite; // Begin sending the actual address |
I2CStateVariable = 0x02; |
break; |
case 0x02: |
if(PIR1bits.SSP1IF == 0) {break;} |
PIR1bits.SSP1IF = 0; |
SSP1BUF = RTR; // Send command to select the TEMP register |
I2CStateVariable = 0x03; |
break; |
case 0x03: |
if(PIR1bits.SSP1IF == 0) {break;} |
PIR1bits.SSP1IF = 0; |
SSP1CON2bits.SEN = 1; // Send another start bit |
I2CStateVariable = 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 device |
I2CStateVariable = 0x06; |
break; |
case 0x06: |
if(PIR1bits.SSP1IF == 0) {break;} |
PIR1bits.SSP1IF = 0; |
TempSave = SSP1BUF; // Finally got the result, need to save it |
SSP1CON2bits.ACKDT = 1; // Prepare I2C NACK handshake |
SSP1CON2bits.ACKEN = 1; // Send the acknowledge bit |
I2CStateVariable = 0x07; |
break; |
case 0x07: |
if(PIR1bits.SSP1IF == 0) {break;} |
PIR1bits.SSP1IF = 0; |
SSP1CON2bits.PEN = 1; // Now send a stop bit |
I2CStateVariable = 0x08; |
break; |
case 0x08: |
if(PIR1bits.SSP1IF == 0) {break;} |
PIR1bits.SSP1IF = 0; |
I2CStateVariable = 0x09; |
break; |
case 0x09: |
TempAccumulator = ((TempAccumulator + TempSave) / 2); // Get an average |
I2CStateVariable = 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 format |
temperature.bits.b1 = 1; // Lower three LSbs = 1 on TC74 format |
temperature.bits.b2 = 1; // Lower three LSbs = 1 on TC74 format |
|
I2CStateVariable = 0x11; // Could go back to 0, but don't want to poll that fast |
break; |
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; // Negate |
temp.Val++; |
}//end if |
|
temp.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 symbol |
tempString[7]='C'; |
tempString[8]='\r'; |
tempString[9]=0x00; // Null-Terminated |
|
}//end UpdateCelsiusASCII |
|
/** EOF temperature.c ********************************************************/ |