Jump to content
43oh

Reading the ds18b20 temperature sensor


Recommended Posts

The DS18B20 differs from the DS1821 enough that I thought I should start a new thread for it.

 

Since this reset function works well for me, I decided to post it up. It features presence pulse detection.

 

It works in combination with the code Touch posted here.

 

int OW_Reset( int Pin )
{
 int result, test;

 delayMicroseconds( 0 );  // delay for 0us
 digitalWrite(Pin, LOW);
 pinMode(Pin, OUTPUT);
 delayMicroseconds( 480 );  // delay for 480us
 pinMode(Pin, INPUT);
 delayMicroseconds( 70 );  // delay for 70us

 test = digitalRead( WIRE_PORT );

 if( test == 0 )     // Mask off everything but P1.7 input
 {
   result = TRUE;      // Presense pulse detected
 }
 else
 {
   result = FALSE;     // ds18b20 is not there
 }

 delayMicroseconds( 410 );  // delay for 410us

 return ( result );        // return the sampled presence pulse result  
}

 

I know that the function could be refactored to make it smaller and sleeker by removing the local variables. I left them in so that people who use this code can make those local variables into watch variables when they are debugging their hardware.

 

Next, I have to create the master read and write time slots in the readbit and writebit functions.

Link to post
Share on other sites

Well, after grinding through the DS18B20 datasheet and making graphs, I realize that Peter H Anderson of Baltimore, MD did a fine job back in 2007.

 

Thanks go to Touch for that link.

 

I now can read the ROM Code out of my DS18B20. It is 0A-00-00-02-E1-39-80-28.

 

I know this is working because the datasheet states that the LSByte will be 0x28 for the DS18B20.

 

64-BIT LASERED ROM CODE

Each DS18B20 contains a unique 64

Link to post
Share on other sites

Okay, I have my code running.

 

 

Here's main.c

#include 
#include "ds18b20.h"

#define UART_TXD   0x02             // TXD on P1.1 (Timer0_A.OUT0)
#define UART_RXD   0x04             // RXD on P1.2 (Timer0_A.CCI1A)
#define UART_TBIT_DIV_2 (16000000 / (9600 * 2))
#define UART_TBIT (16000000 / 9600)

#define delayMicroseconds(n) __delay_cycles(n<<4)

// The One Wire bus is connected to this pin
#define WIRE_PORT 7 //Remember you need a 4.7k pullup resistor here.

#define LOW 0
#define HIGH 1
#define INPUT 0
#define OUTPUT 1   
#define FALSE 0
#define TRUE 1   


//Zeke's mod's
int  OW_Reset( int Pin );
void OW_WriteByte(int Pin, char d);
char OW_ReadByte(int Pin);

// Routines written by Peter H Anderson
// http://www.phanderson.com/arduino/ds18b20_1.html
char digitalRead( char Pin );
void pinMode( int Pin, int Out );
void digitalWrite( int Pin, int Bit );

// Software UART routines
void TimerA_UART_init( void );
void TimerA_UART_tx( unsigned char byte );

unsigned int  txData;    // UART internal variable for TX
unsigned char rxBuffer;  // Received UART character


void main(void)
{
//  int temp = 0;
 int i;
 int ROMCode[8];
 int ScratchPad[9];
 int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

  WDTCTL = WDTPW + WDTHOLD;               // Stop watchdog timer
  BCSCTL1 = CALBC1_16MHZ;
  DCOCTL  = CALDCO_16MHZ;

  P1OUT = UART_RXD;                       // RXD as IN
  P1SEL = UART_TXD + UART_RXD;            // Timer function for TXD/RXD pins
  P1DIR = UART_TXD;   

  TimerA_UART_init();
  __enable_interrupt();


  while ( 1 )
  {      
     if ( 1 == OW_Reset( WIRE_PORT ) )
     {
       OW_WriteByte( WIRE_PORT, 0x33 );  // Read ROM Code from DS18B20

       for( i=0; i<8; i++ )
       {
         // Read the values inside of the ROMCode array in the debugger window
         ROMCode[i] = OW_ReadByte( WIRE_PORT );
       }
     }

     if ( 1 == OW_Reset( WIRE_PORT ) )
     {
       OW_WriteByte( WIRE_PORT, SKIPROM );  // Skip ROM Code matching
       OW_WriteByte( WIRE_PORT, CONVERTTEMP );  // Read ROM Code from DS18B20
       OW_Reset( WIRE_PORT );
       OW_WriteByte( WIRE_PORT, SKIPROM );  // Skip ROM Code matching
       OW_WriteByte( WIRE_PORT, READSCRATCHPAD );  // Read ScratchPad from DS18B20

       for( i=0; i<9; i++ )
       {
         // Read the values inside of the ScratchPad array in the debugger window
         ScratchPad[i] = OW_ReadByte( WIRE_PORT );
       }
     }


     OW_Reset( WIRE_PORT );
     OW_WriteByte( WIRE_PORT, SKIPROM );         // Skip ROM Code matching
     OW_WriteByte( WIRE_PORT, CONVERTTEMP );     // Read ROM Code from DS18B20
     OW_Reset( WIRE_PORT );
     OW_WriteByte( WIRE_PORT, SKIPROM );         // Skip ROM Code matching
     OW_WriteByte( WIRE_PORT, READSCRATCHPAD );  // Read ScratchPad from DS18B20

     LowByte  = OW_ReadByte( WIRE_PORT );
     HighByte = OW_ReadByte( WIRE_PORT );

     // Thanks again "Mr. Anderson" for this code
     TReading = ( HighByte << 8 ) + LowByte;
     SignBit = TReading & 0x8000;  // test most sig bit
     if ( 1 == SignBit ) // negative
     {
       TReading = (TReading ^ 0xffff) + 1; // 2's comp
     }
     Tc_100 = ( 6 * TReading ) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

     Whole = Tc_100 / 100;  // separate off the whole and fractional portions
     Fract = Tc_100 % 100;

     // **********************************************************************************************************
     // ***** This won't work so I am commenting it out (zeke) *****
     // ***** A serial ring buffer and interrupt servicing routines is needed to make this work *****
     // *****
     // ***** Read the "Whole" and "Fract" values with your debugger *****
     // **********************************************************************************************************
     // this will print the tempature in an int8 over serial every 1 second.
     // TimerA_UART_tx( Whole );
     // TimerA_UART_tx( Fract );

     // **********************************************************************************************************
     // insert a breakpoint here and observe the variables in the debugger watch window
     // **********************************************************************************************************
     delayMicroseconds( 1000000 );
   }
}

int OW_Reset( int Pin )
{
 int presence;

 delayMicroseconds( 0 );  // delay for 0us
 digitalWrite( Pin, LOW );
 pinMode( Pin, OUTPUT );
 delayMicroseconds( 480 );  // delay for 480us
 pinMode( Pin, INPUT );
 delayMicroseconds( 70 );  // delay for 70us

 if( 0 == digitalRead( WIRE_PORT ) )
 {
   presence = TRUE;      // Presense pulse detected
 }
 else
 {
   presence = FALSE;     // ds18b20 is not there
 }

 delayMicroseconds( 410 );  // delay for 410us

 return ( presence );        // return the sampled presence pulse result  
}

// Peter Anderson wrote this
void OW_WriteByte( int Pin, char d )
{
 char n;
 for(n=8; n!=0; n--)
 {
   if ( (d & 0x01) == 1 )
   {
     digitalWrite( Pin, LOW );
     pinMode( Pin, OUTPUT );
     delayMicroseconds( 5 );
     pinMode( Pin, INPUT );
     delayMicroseconds( 60 );
   }
   else
   {
     digitalWrite( Pin, LOW );
     pinMode( Pin, OUTPUT );
     delayMicroseconds( 60 );
     pinMode( Pin, INPUT );
   }
   d = d >> 1;
 }
}

// Peter Anderson wrote this
char OW_ReadByte( int pin )
{
 char d, n, b;

 for ( n=0; n<8; n++ )
 {
   digitalWrite( pin, LOW );
   pinMode( pin, OUTPUT);
   delayMicroseconds( 5 );
   pinMode( pin, INPUT );
   delayMicroseconds( 5 );
   b = digitalRead( pin );
   delayMicroseconds( 50 );
   d = (d >> 1) | (b << 7); // shift d to right and insert b in most sig bit position
 }
 return(d);
}

//------------------------------------------------------------------------------
// Arduino like digitalRead, pinMode, and digitalWrite helper functions.
//------------------------------------------------------------------------------
char digitalRead( char Pin )
{
 // Read P1IN and mask it with the 1wPin then shift it to the LSB position
 return ( (P1IN &  (1 << Pin) ) >> Pin );
}

void pinMode( int pin, int out )
{          
 if( 1 == out )
 {
   P1DIR |= (1 << pin);
 } 
 else
 {
   P1DIR &= (~(1 << pin));
 } 
}

void digitalWrite(int Pin, int Bit)
{
 if ( 1 == ( Bit ) )
 {
   P1OUT |= ( 1 << Pin );      // if the Bit is HIGH then drive the 1wBus HIGH 
 } 
 else
 {
   P1OUT &= ( ~(1 << Pin) );   // if the Bit is LOW then drive the 1wBus LOW   
 }
}

//------------------------------------------------------------------------------
// Function configures Timer_A for full-duplex UART operation
//------------------------------------------------------------------------------
void TimerA_UART_init(void)
{
 TACCTL0 = OUT;                          // Set TXD Idle as Mark = '1'
 TACCTL1 = SCS + CM1 + CAP + CCIE;       // Sync, Neg Edge, Capture, Int
 TACTL = TASSEL_2 + MC_2;                // SMCLK, start in continuous mode
}

//------------------------------------------------------------------------------
// Outputs one byte using the Timer_A UART
//------------------------------------------------------------------------------
void TimerA_UART_tx(unsigned char byte)
{
 while (TACCTL0 & CCIE);                 // Ensure last char got TX'd
 TACCR0 = TAR;                           // Current state of TA counter
 TACCR0 += UART_TBIT;                    // One bit time till first bit
 TACCTL0 = OUTMOD0 + CCIE;               // Set TXD on EQU0, Int
 txData = byte;                          // Load global variable
 txData |= 0x100;                        // Add mark stop bit to TXData
 txData <<= 1;                           // Add space start bit
}

//------------------------------------------------------------------------------
// Timer_A UART - Transmit Interrupt Handler
//------------------------------------------------------------------------------
#pragma vector = TIMERA0_VECTOR
__interrupt void Timer_A0_ISR(void)
{
 static unsigned char txBitCnt = 10;

 TACCR0 += UART_TBIT;                    // Add Offset to CCRx
 if (txBitCnt == 0)                      // All bits TXed?
 {                    
   TACCTL0 &= ~CCIE;                   // All bits TXed, disable interrupt
   txBitCnt = 10;                      // Re-load bit counter
 }
 else 
 {
   if (txData & 0x01) 
   {
     TACCTL0 &= ~OUTMOD2;              // TX Mark '1'
   }
   else 
   {
     TACCTL0 |= OUTMOD2;               // TX Space '0'
   }
   txData >>= 1;
   txBitCnt--;
 }
}     

//------------------------------------------------------------------------------
// Timer_A UART - Receive Interrupt Handler
//------------------------------------------------------------------------------
#pragma vector = TIMERA1_VECTOR
__interrupt void Timer_A1_ISR(void)
{
 static unsigned char rxBitCnt = 8;
 static unsigned char rxData = 0;

 switch ( __even_in_range(TAIV, TAIV_TAIFG) )  // Use calculated branching
 {
   case TAIV_TACCR1:                           // TACCR1 CCIFG - UART RX
     TACCR1 += UART_TBIT;                 // Add Offset to CCRx
     if (TACCTL1 & CAP)                    // Capture mode = start bit edge
     {                 
       TACCTL1 &= ~CAP;                 // Switch capture to compare mode
       TACCR1 += UART_TBIT_DIV_2;       // Point CCRx to middle of D0
     }
     else 
     {
       rxData >>= 1;
       if (TACCTL1 & SCCI)             // Get bit waiting in receive latch
       {
         rxData |= 0x80;
       }
       rxBitCnt--;
       if (rxBitCnt == 0)              // All bits RXed?
       {    
         rxBuffer = rxData;           // Store in global variable
         rxBitCnt = 8;                // Re-load bit counter
         TACCTL1 |= CAP;              // Switch compare to capture mode
         __bic_SR_register_on_exit(LPM0_bits);  // Clear LPM0 bits from 0(SR)
       }
     }
   break;
 }
}

 

And here's ds18b20.h

#ifndef DS18B20_H_
#define DS18B20_H_


// 'tick' values 
// Compute these from DalSemi AN126 xls worksheet
//int A,B,C,D,E,F,G,H,I,J;
#define tA 6
#define tB 64
#define tC 60
#define tD 10
#define tE 9
#define tF 55
#define tG 0
#define tH 480
#define tI 70
#define tJ 410

// 1-Wire ROM Command Codes
#define SEARCHROM   0xF0
#define READROM     0x33
#define MATCHROM    0x55
#define SKIPROM     0xCC
#define ALARMSEARCH 0xEC

// DS18B20 Function Commands
#define CONVERTTEMP     0x44
#define WRITESCRATCHPAD 0x4E
#define READSCRATCHPAD  0xBE
#define COPYSCRATCHPAD  0x48
#define RECALLEE        0xB8
#define READPOWERSUPPLY 0xB4

#endif /*DS18B20_H_*/

 

Again, make sure you calibrate the DCO for 16MHz if you're using a value line device.

 

Enjoy!

Link to post
Share on other sites

Hmmm...

 

I guess I should have stated that I do not use the serial communications. It's not set up properly.

 

The variables Whole and Fract are hexadecimal values and therefore need to be prepared before serial transmission.

 

Specifically, they have to be converted into ASCII representation or else they will look like crap on your terminal program (unless it can display raw hex values). Still, if a serial terminal received 0x0d or 0x0a then your cursor would jump around.

 

The way I'm checking the ds18b20 values is with my debugger. I stop the program at the delayMicroseconds(1000000) and then look at the value of the local variables in the watch window.

 

In order to make the serial transmission work, a serial port TX ring buffer and supporting interrupt routines would have to be created.

 

I will comment out the serial tx calls in my main loop so that I don't mislead people.

Link to post
Share on other sites

I'm not sure if the program is properly reading your ds18b20.

 

This is what I see:

post-955-135135495601_thumb.png

 

Look at the Tc_100 value. The value of Whole is the first two digits and Fract is the last two digits.

 

It's important to note that the ds18b20 has to have a strong pullup during the temperature conversion process.

 

I did this by wiring the Vdd pin to 3.6V because it was easier for me. This means the ds18b20 is not in parasitic mode.

 

If you run it in parasitic mode then you have to apply a strong pullup during the conversion step. This is figure 4 on page 6 of the ds18b20 datasheet.

post-955-135135495614_thumb.png

 

How do you have your ds18b20 hooked up?

Link to post
Share on other sites

Okay, just for you Touch, I buffed the serial port TX routines. I'm assuming that you only have RealTerm to debug stuff.

 

If the ds18b20 gives a reading of 0x016c then:

1. Tc_100 = 0d2275 (22.75'C)

2. Whole = 0d22 = 0x16

3. Fract = 0d75 = 0x4b

 

When RealTerm is in raw hex mode, you should be see the following repeat every one second:

<0x01><0x06><0x04><0x0b><0x32><0x32><0x37><0x35><0x20>

 

You should get sensible results as long as your ds18b20 is being read properly.

#include 
#include "ds18b20.h"
#include "types.h"

#define UART_TXD   0x02             // TXD on P1.1 (Timer0_A.OUT0)
#define UART_RXD   0x04             // RXD on P1.2 (Timer0_A.CCI1A)
#define UART_TBIT_DIV_2 (16000000 / (9600 * 2))
#define UART_TBIT (16000000 / 9600)

#define delayMicroseconds(n) __delay_cycles(n<<4)

// The One Wire bus is connected to this pin
#define WIRE_PORT 7 //Remember you need a 4.7k pullup resistor here.

#define LOW 0
#define HIGH 1
#define INPUT 0
#define OUTPUT 1   
#define FALSE 0
#define TRUE 1   


//Zeke's mod's
int  OW_Reset( int Pin );
void OW_WriteByte(int Pin, char d);
char OW_ReadByte(int Pin);

// Routines written by Peter H Anderson
// http://www.phanderson.com/arduino/ds18b20_1.html
char digitalRead( char Pin );
void pinMode( int Pin, int Out );
void digitalWrite( int Pin, int Bit );

// Software UART routines
void TimerA_UART_init( void );
UINT8 UART_putHexByte( UINT8 data);
UINT8 UART_PutDec32( UINT32 data);
void TimerA_UART_tx( UINT8 byte );

unsigned int  txData;    // UART internal variable for TX
unsigned char rxBuffer;  // Received UART character


void main(void)
{
//  int temp = 0;
 int i;
 int ROMCode[8];
 int ScratchPad[9];
 int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

  WDTCTL = WDTPW + WDTHOLD;               // Stop watchdog timer
  BCSCTL1 = CALBC1_16MHZ;
  DCOCTL  = CALDCO_16MHZ;

  P1OUT = UART_RXD;                       // RXD as IN
  P1SEL = UART_TXD + UART_RXD;            // Timer function for TXD/RXD pins
  P1DIR = UART_TXD;   

  TimerA_UART_init();
  __enable_interrupt();


  while ( 1 )
  {      
     if ( 1 == OW_Reset( WIRE_PORT ) )
     {
       OW_WriteByte( WIRE_PORT, 0x33 );  // Read ROM Code from DS18B20

       for( i=0; i<8; i++ )
       {
         // Read the values inside of the ROMCode array in the debugger window
         ROMCode[i] = OW_ReadByte( WIRE_PORT );
       }
     }

     if ( 1 == OW_Reset( WIRE_PORT ) )
     {
       OW_WriteByte( WIRE_PORT, SKIPROM );  // Skip ROM Code matching
       OW_WriteByte( WIRE_PORT, CONVERTTEMP );  // Read ROM Code from DS18B20
       OW_Reset( WIRE_PORT );
       OW_WriteByte( WIRE_PORT, SKIPROM );  // Skip ROM Code matching
       OW_WriteByte( WIRE_PORT, READSCRATCHPAD );  // Read ScratchPad from DS18B20

       for( i=0; i<9; i++ )
       {
         // Read the values inside of the ScratchPad array in the debugger window
         ScratchPad[i] = OW_ReadByte( WIRE_PORT );
       }
     }


     OW_Reset( WIRE_PORT );
     OW_WriteByte( WIRE_PORT, SKIPROM );         // Skip ROM Code matching
     OW_WriteByte( WIRE_PORT, CONVERTTEMP );     // Read ROM Code from DS18B20
     OW_Reset( WIRE_PORT );
     OW_WriteByte( WIRE_PORT, SKIPROM );         // Skip ROM Code matching
     OW_WriteByte( WIRE_PORT, READSCRATCHPAD );  // Read ScratchPad from DS18B20

     LowByte  = OW_ReadByte( WIRE_PORT );
     HighByte = OW_ReadByte( WIRE_PORT );

     // Thanks again "Mr. Anderson" for this code
     TReading = ( HighByte << 8 ) + LowByte;
     SignBit = TReading & 0x8000;  // test most sig bit
     if ( 1 == SignBit ) // negative
     {
       TReading = (TReading ^ 0xffff) + 1; // 2's comp
     }
     Tc_100 = ( 6 * TReading ) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

     Whole = Tc_100 / 100;  // separate off the whole and fractional portions
     Fract = Tc_100 % 100;

     //this will print the tempature in an int8 over serial every 1 second.
     UART_putHexByte( Whole );   // Transmit the hex value
     UART_putHexByte( Fract );  
     UART_PutDec32( Tc_100 );    // Transmit the decimal value
     TimerA_UART_tx( ' ' );   // Transmit a space character

     // insert a breakpoint here and observe the variables in the watch window
     delayMicroseconds( 1000000 );
   }
}

int OW_Reset( int Pin )
{
 int presence;

 delayMicroseconds( 0 );  // delay for 0us
 digitalWrite( Pin, LOW );
 pinMode( Pin, OUTPUT );
 delayMicroseconds( 480 );  // delay for 480us
 pinMode( Pin, INPUT );
 delayMicroseconds( 70 );  // delay for 70us

 if( 0 == digitalRead( WIRE_PORT ) )
 {
   presence = TRUE;      // Presense pulse detected
 }
 else
 {
   presence = FALSE;     // ds18b20 is not there
 }

 delayMicroseconds( 410 );  // delay for 410us

 return ( presence );        // return the sampled presence pulse result  
}

// Peter Anderson wrote this
void OW_WriteByte( int Pin, char d )
{
 char n;
 for(n=8; n!=0; n--)
 {
   if ( (d & 0x01) == 1 )
   {
     digitalWrite( Pin, LOW );
     pinMode( Pin, OUTPUT );
     delayMicroseconds( 5 );
     pinMode( Pin, INPUT );
     delayMicroseconds( 60 );
   }
   else
   {
     digitalWrite( Pin, LOW );
     pinMode( Pin, OUTPUT );
     delayMicroseconds( 60 );
     pinMode( Pin, INPUT );
   }
   d = d >> 1;
 }
}

// Peter Anderson wrote this
char OW_ReadByte( int pin )
{
 char d, n, b;

 for ( n=0; n<8; n++ )
 {
   digitalWrite( pin, LOW );
   pinMode( pin, OUTPUT);
   delayMicroseconds( 5 );
   pinMode( pin, INPUT );
   delayMicroseconds( 5 );
   b = digitalRead( pin );
   delayMicroseconds( 50 );
   d = (d >> 1) | (b << 7); // shift d to right and insert b in most sig bit position
 }
 return(d);
}

//------------------------------------------------------------------------------
// Arduino like digitalRead, pinMode, and digitalWrite helper functions.
//------------------------------------------------------------------------------
char digitalRead( char Pin )
{
 // Read P1IN and mask it with the 1wPin then shift it to the LSB position
 return ( (P1IN &  (1 << Pin) ) >> Pin );
}

void pinMode( int pin, int out )
{          
 if( 1 == out )
 {
   P1DIR |= (1 << pin);
 } 
 else
 {
   P1DIR &= (~(1 << pin));
 } 
}

void digitalWrite(int Pin, int Bit)
{
 if ( 1 == ( Bit ) )
 {
   P1OUT |= ( 1 << Pin );      // if the Bit is HIGH then drive the 1wBus HIGH 
 } 
 else
 {
   P1OUT &= ( ~(1 << Pin) );   // if the Bit is LOW then drive the 1wBus LOW   
 }
}

UINT8 UART_putHexByte(UINT8 data)
{
 unsigned char nibble;

 nibble = (data>>4) & 0x0F;

 if (nibble<10)
 { 
   nibble=nibble+'0';
 } 
 else
 { 
   nibble = nibble-10+'a';
 }

 TimerA_UART_tx( nibble );

 nibble = data & 0x0F;

 if (nibble<10) 
 {
   nibble = nibble+'0'; 
 }
 else 
 {
   nibble = nibble-10+'a';
 }

 TimerA_UART_tx( nibble );

 return 1;
}

UINT8 UART_PutDec32(UINT32 data)
{
 UINT32 divisor, result, remainder;
 UINT8 leading;

 leading=1;

 remainder = data;

 for(divisor = 1000000000; divisor > 0; divisor /= 10) 
 {
   result = remainder / divisor;
   remainder %= divisor;

   if (result) 
     leading=0;

   if (!leading||(divisor==1))
     TimerA_UART_tx((UINT8)(result) + '0');
 }

 return 1;
}

//------------------------------------------------------------------------------
// Function configures Timer_A for full-duplex UART operation
//------------------------------------------------------------------------------
void TimerA_UART_init(void)
{
 TACCTL0 = OUT;                          // Set TXD Idle as Mark = '1'
 TACCTL1 = SCS + CM1 + CAP + CCIE;       // Sync, Neg Edge, Capture, Int
 TACTL = TASSEL_2 + MC_2;                // SMCLK, start in continuous mode
}

//------------------------------------------------------------------------------
// Outputs one byte using the Timer_A UART
//------------------------------------------------------------------------------
void TimerA_UART_tx(unsigned char byte)
{
 while (TACCTL0 & CCIE);                 // Ensure last char got TX'd
 TACCR0 = TAR;                           // Current state of TA counter
 TACCR0 += UART_TBIT;                    // One bit time till first bit
 TACCTL0 = OUTMOD0 + CCIE;               // Set TXD on EQU0, Int
 txData = byte;                          // Load global variable
 txData |= 0x100;                        // Add mark stop bit to TXData
 txData <<= 1;                           // Add space start bit
}

//------------------------------------------------------------------------------
// Timer_A UART - Transmit Interrupt Handler
//------------------------------------------------------------------------------
#pragma vector = TIMERA0_VECTOR
__interrupt void Timer_A0_ISR(void)
{
 static unsigned char txBitCnt = 10;

 TACCR0 += UART_TBIT;                    // Add Offset to CCRx
 if (txBitCnt == 0)                      // All bits TXed?
 {                    
   TACCTL0 &= ~CCIE;                   // All bits TXed, disable interrupt
   txBitCnt = 10;                      // Re-load bit counter
 }
 else 
 {
   if (txData & 0x01) 
   {
     TACCTL0 &= ~OUTMOD2;              // TX Mark '1'
   }
   else 
   {
     TACCTL0 |= OUTMOD2;               // TX Space '0'
   }
   txData >>= 1;
   txBitCnt--;
 }
}     

//------------------------------------------------------------------------------
// Timer_A UART - Receive Interrupt Handler
//------------------------------------------------------------------------------
#pragma vector = TIMERA1_VECTOR
__interrupt void Timer_A1_ISR(void)
{
 static unsigned char rxBitCnt = 8;
 static unsigned char rxData = 0;

 switch ( __even_in_range(TAIV, TAIV_TAIFG) )  // Use calculated branching
 {
   case TAIV_TACCR1:                           // TACCR1 CCIFG - UART RX
     TACCR1 += UART_TBIT;                 // Add Offset to CCRx
     if (TACCTL1 & CAP)                    // Capture mode = start bit edge
     {                 
       TACCTL1 &= ~CAP;                 // Switch capture to compare mode
       TACCR1 += UART_TBIT_DIV_2;       // Point CCRx to middle of D0
     }
     else 
     {
       rxData >>= 1;
       if (TACCTL1 & SCCI)             // Get bit waiting in receive latch
       {
         rxData |= 0x80;
       }
       rxBitCnt--;
       if (rxBitCnt == 0)              // All bits RXed?
       {    
         rxBuffer = rxData;           // Store in global variable
         rxBitCnt = 8;                // Re-load bit counter
         TACCTL1 |= CAP;              // Switch compare to capture mode
         __bic_SR_register_on_exit(LPM0_bits);  // Clear LPM0 bits from 0(SR)
       }
     }
   break;
 }
}

 

This is types.h. You'll need it.

#ifndef TYPES_H_
#define TYPES_H_

//** Exportable Constants and Types ******************************************/

typedef unsigned char UINT8;    /* Type for  8 bit unsigned integer */
typedef unsigned char UCHAR;    /* Type for  8 bit unsigned integer */
typedef unsigned int  UINT16;   /* Type for 16 bit unsigned integer */
typedef unsigned long UINT32;   /* Type for 32 bit unsigned integer */

typedef signed char          CHAR;     /* Type for  8 bit signed integer */
typedef signed char          INT8;     /* Type for  8 bit signed integer */
typedef signed int           INT16;    /* Type for 16 bit signed integer */
typedef signed long          INT32;    /* Type for 32 bit signed integer */

//typedef float         FLOAT32;  /* Type for 32 bit floating point */
//typedef double        FLOAT64;  /* Type for 64 bit floating point */

//typedef enum
//{
//    FALSE = 0,
//    TRUE  = 1
//} BOOL, MBOOL;

#endif /*TYPES_H_*/

 

Does it go?

Link to post
Share on other sites

Okay, I found all my serial port gear.

 

Here's a screen cap of realterm with the code running:

 

post-955-135135495624_thumb.png

 

I forgot that realterm does not format the raw data like I suggested above.

 

I see ASCII encoded data in that string:

17122318

 

Where:

17 = 0x17

12 = 0x12

2318 = 23.18'C

 

Do you get something like this?

Link to post
Share on other sites

Alright, I gave your newest code a try.

 

I am hooking it up using a 4.7k pullup resistor from VCC to DQ. it's not in parasitic power mode.

 

Heres the results I got:

032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 032b343 0332350 033e362 0344368 0344368 033e362 034b375 0344368 0351381 034b375 0344368 033e362 033e362 0338356 0338356 0338356 0338356 0338356 0338356 0332350 0332350 0332350 0332350 0332350 0332350 0332350 0332350 032b343 032b343 032b343 0332350 0344368 033e362 0338356 0338356 0332350 0332350 0332350 0344368 0344368 034b375 0344368 033e362 033e362 0338356 0338356 0338356 0338356 0338356 

 

The changes you see in the results are simply caused breathing on the sensor to change the temperature. I've tried all of my sensors to see if I had a bad one with the same results, I don't think all of my sensors could be bad.

 

Thanks for taking your time to debug my problems!

post-950-135135495629_thumb.jpg

Link to post
Share on other sites

Touch,

 

Let's simplify this.

 

Modify the main loop so only these lines are transmitting out the serial port:

 

      UART_PutDec32( Tc_100 );    // Transmit the decimal value
     TimerA_UART_tx( 0x0A );   // Transmit a space character
     TimerA_UART_tx( 0x0D );

 

This is what I get:

post-955-135135495948_thumb.png

 

It's 21.75'C in my room.

 

What's yours look like?

Link to post
Share on other sites

I'm getting 331~, that is obliviously incorrect because its not only missing some bits, but its not 90F~ degrees in my room!

 

After studying the datasheets, I believe I may have been sent the wrong version of chips. I noticed that the DS1820/DS18S20 is ONLY a 9bit chip, and I'm getting a 9 bit output, the DS18B20's have a configurable resolution however. Furthermore, the DS1820/DS18S20 have longer conversion times, and that could be why I'm getting some funky readings randomly.

 

Question, what are your chips stamped with? Mine just says DS1820.

 

Thanks!

 

EDIT: Yep, just confirmed based on the address of my device that it is a DS18S20, looks like I got sent the wrong ones. Oh well, time to get it working. I wonder why its reporting the temperature so far off though, looking at the datasheets there's not much difference other than the temperature resolution.

Link to post
Share on other sites

Since you have a ds18s20, the math for the temperature conversion is different.

 

It's different because the bit resolution is 0.5'C per bit (9 bit mode). The ds18b20 is 0.125'C per bit (12 bit mode).

 

If we adjust the conversion math then you'll get the correct results.

 

First, add these to the top of your file:

 #define DS18B20 0x28
#define DS18S20 0x10

 

Then adjust the temperature conversions procedure to this instead:

 if( ROMCode[7] == DS18B20 )   
 {
   Tc_100 = ( 6 * TReading ) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25
 }
 else if ( ROMCode[7] == DS18S20 ) 
 {
   Tc_100 = ( 5 * TReading );    // multiply by (100 * 0.05) or 5
 }

 

It's not the best code since I assume it's one or the other sensor (not wise).

 

The family code is derived from the LSByte of the ROM Code. In the case of my code, ROMCode[7].

 

You could also do this:

switch ( ROMCode[7] )
{
 case DS18B20:
   Tc_100 = ( 6 * TReading ) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25
   break;

 case DS18S20:
   Tc_100 = ( 5 * TReading );    // multiply by (100 * 0.05) or 5
    break;

 default:
   Tc_100 = 0;
   break;
}

 

That will take care of the condition when you pull out your temp sensor while the unit is still running.

 

What do you get now?

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...