Code optimisation, reading temp from DS1820 (picc)

Thread Starter

coldpenguin

Joined Apr 18, 2010
165
Hello all,
Can anyone help me with a problem? I am trying to write some code, I am using the lite version of PICC.
It is extremely irritating when it says I can compile this 400 words better if you pay $1000, I am a hobbyist, so can't afford that. I am considering porting to SDCC to get around this 'warning'

My problem, I am running out of space, I think that I could fit the whole rest of the program in maybe 50-100 words.
This routine, is taking 450 words.

Idea is I have stored the addresses in local eeprom, I am passing the routine a char with a number of the sensor, and an array of chars, 3 digits long, each digit will store a digit of the number to be displayed.

The conversion routine is based upon some code from Christian Stadler (found online, can't find the website now)
The code effectively multiplies up the number by 256 during the conversion, to allow for full accuracy. I want to get one decimal place put into digits[2]

The 'main' waste of space is the division, which is taking >100 words.
I have left digits[0] and [1] intact below, and commented out 'attempts' around digits[2].

MatchRom, Write and Reset appear to be reasonably optimised, my main 'waste' of code is in the arithmetic.
So can anyone suggest a better way of doing the maths, or whether using SDCC might save me the space I need? (The PICC I think it not trying to optimise).

Rich (BB code):
void gettemp(unsigned char sensornum,unsigned char (*digits)){

  D_Reset();
  D_MatchRom(0x0e+8*sensornum);
  D_Write(0xbe);
  unsigned char temp[8];
  unsigned char r=0;
  while(r<8){
    temp[r]=D_Read();
    r++;
  }
  unsigned int hres=0;
  unsigned int tres=0;
  tres =temp[1]<<8;
  tres |=temp[0];
  if(0x02 !=sensornum){
    hres=tres<<4;
  }else{
    tres >>= 1;
    tres <<= 8;
    tres -= 0x100>>2;
    hres =0x10-temp[6];
    hres <<=4;
    hres +=tres;
  }
//div_t ty=div(hres,2);

  digits[0]=(hres>>8)/10;
  digits[1]=(hres>>8)-digits[0]*10;

//hres-=(digits[0]*10)<<8;
//hres-=(digits[1])<<8;
//hres *=10;

  digits[2]=hres%256;
//((hres)>>6)&0b00000111;
//int t=10*hres>>8;

}
 

Thread Starter

coldpenguin

Joined Apr 18, 2010
165
Try the Hi-tech C compiler in lite mode. No code size limitations at all
http://www.microchip.com/stellent/i...Id=1406&dDocName=en534868&redirects=compilers
Sorry, that was the compiler I meant.
The limitations are not from the compiler as such (apart from the fact that it is 'adding' [or rather not removing] 400 words of optimisation).
The PIC I am using, is limited to 1024 words, so 100 used on / is a lot, and 450 used in this one routine is massive! (although I guess this routine does do a reasonable amount)


Rich (BB code):
Executing: "C:\Program Files (x86)\HI-TECH Software\PICC\9.83\bin\picc.exe" -owatercool.cof -mwatercool.map --summary=default,-psect,-class,+mem,-hex --output=default,-inhx032 watercool.p1 --chip=16F84A -P --runtime=default,+clear,+init,-keep,+osccal,-download,-resetbits,-stackcall,+clib --opt=default,+asm,-debug,+speed,-space,9 --warn=0 --double=24 --float=24 --addrqual=ignore -g --asmlist "--errformat=Error   [%n] %f; %l.%c %s" "--msgformat=Advisory[%n] %s" "--warnformat=Warning [%n] %f; %l.%c %s" 
HI-TECH C Compiler for PIC10/12/16 MCUs (Lite Mode)  V9.83
Copyright (C) 2011 Microchip Technology Inc.
(1273) Omniscient Code Generation not available in Lite mode (warning)

Memory Summary:
    Program space        used   3B1h (   945) of   400h words   ( 92.3%)
    Data space           used    37h (    55) of    44h bytes   ( 80.9%)
    EEPROM space         used     0h (     0) of    40h bytes   (  0.0%)
    Configuration bits   used     1h (     1) of     1h word    (100.0%)
    ID Location space    used     0h (     0) of     4h bytes   (  0.0%)


Running this compiler in PRO mode, with Omniscient Code Generation enabled,
produces code which is typically 40% smaller than in Lite mode.
The HI-TECH C PRO compiler output for this code could be 378 words smaller.
See http://microchip.htsoft.com/portal/pic_pro for more information.

Loaded C:\Users\penguin\Syncdir\Microchip\Watercool\watercool.cof.
 
Last edited:

Thread Starter

coldpenguin

Joined Apr 18, 2010
165
Will you be able to post the full code. What do want to do with the result from DS1820
This should be the full code, sorry but I don't program with indents. (I didn't post it before as I thought that the maths is using more memory than I would have wanted)
I took the 1wire.c from a site a couple of years back, am not sure which one. The short circuit detection can be removed, but that doesn't help much

The output from the DS1820 is displayed on an LED digit display, and will later end up controlling a perlier (basically turn port on, let transistor deal with peltier), and if I can fit it, to check a hall sensor is detecting an AC current
Rich (BB code):
#ifndef _XTAL_FREQ
     // Unless specified elsewhere, 4MHz system frequency is assumed
#define XTAL_FREQ 500KHZ //12000000
#endif
#include <pic.h>
#include "../delay.h"
#include <stdlib.h>

unsigned char gete(unsigned char address);
#define sleep()        asm("sleep")
#define _D_MATCHROM_
#define _D_READROM_
#define D_PIN RA0
#define D_TRIS TRISA0
#include "../1wire.c"
__CONFIG( FOSC_HS & WDTE_OFF);

unsigned char gete(unsigned char address){
   EEADR=address;
   RD=1; 
   return(EEDATA);
}

void gettemp(unsigned char sensornum,unsigned char (*digits)){

D_Reset();
//D_Write(0xcc);
D_MatchRom(0x0e+8*sensornum);
D_Write(0xbe);
unsigned char temp[8];
unsigned char r=0;
while(r<8){
temp[r]=D_Read();
r++;
}
unsigned int hres=0;
unsigned int tres=0;
tres =temp[1]<<8;
tres |=temp[0];
if(0x02 !=sensornum){
hres=tres<<4;
}else{
tres >>= 1;
tres <<= 8;
tres -= 0x100>>2;
hres =0x10-temp[6];
hres <<=4;
//hres /=0x10;

//hres >>=4;
hres +=tres;

}
//div_t ty=div(hres,2);

digits[0]=(hres>>8)/10;
digits[1]=(hres>>8)-digits[0]*10;
//hres-=(digits[0]*10)<<8;
//hres-=(digits[1])<<8;
//hres *=10;
digits[2]=hres%256;
//((hres)>>6)&0b00000111;
//int t=10*hres>>8;

}
output(unsigned char * o,unsigned char i){

unsigned char j=0;
while(j<4){
/*unsigned char cnt=0;
switch (j){
case 0: PORTA=gete(0x00);
break;
case 1: PORTA=gete(0x01); 
break;
case 2: PORTA=gete(0x02);
break;
default: PORTA=gete(0x03);
}*/
PORTA=gete(j);
        if(i>125 && j==1){
            PORTB=o[j]-0b10000000;
        }else{
            PORTB=o[j];
        }

/*unsigned char cnt=0;
cnt=0;
while(cnt<4){
cnt++;
}*/
#asm
NOP
NOP
NOP
#endasm
//asm("NOP;");
//asm("NOP;");
//asm("NOP;");

        PORTB=0xFF;
        PORTA=0x00;
j++;
    }


}


void main()    {
unsigned char o[4];  
unsigned char temps[3][3];

o[0]=0;
/*while(o[0]<3){      // this saved 48!
temps[o[0]][0]=0;
temps[o[0]][1]=0;
temps[o[0]][2]=0;
o[0]++;
}
o[0]=0;*/
TRISA=0b00000000;
TRISB=0b00000000;
PORTA=0b00000000;

unsigned char y=0x00;
unsigned char u=0;
unsigned char p=0;
D_Reset();
D_Write(0xcc);
D_Write(0x44);
while(1){
o[3]=0b11111111-(0b00000001<<u);
o[0]=gete(0x04+temps[0]);
o[1]=gete(0x04+temps[1]);
o[2]=gete(0x04+temps[2]);
unsigned char k=0;
while(k<10){
            unsigned char i=0;
            while(i<250){
                i++;
                output(o,i);
            }
            k++;
        }

        y++;
        if(y>7){
y=0;
while(y<3){
gettemp(y,temps[y]);
y++;
}
D_Reset();
D_Write(0xcc);
D_Write(0x44);
y=0;
}
        u++;
        if(u>2) u=0;

}
}



#asm
     psect eedata, delta=2, abs, ovrld
     ORG 2100H   ; starting point of EEPROM on 16F84
//ports
     DW 0x08,0x04,0x0c,0x00;
//numbers
      dw 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90;
     DW 0x28,0x99, 0xce,0x8d,0x02,0x00,0x00,0xb2 ; 
     DW 0x28,0x47, 0xa6,0x8d,0x02,0x00,0x00,0x4a ; 
     DW 0x10,0xbc,53H, 0xf5,01H,0x08,00H,0x77 ; 

#endasm
     
//delay.h

#ifndef DELAY_ROUTINE       //-- Check if already loaded!!!


 #define    MHZ    *1000            /* number of kHz in a MHz */
 #define    KHZ    *1            /* number of kHz in a kHz */

 #define    DelayUs(x) unsigned char _dcnt;  \
              _dcnt =1; \
              while(--_dcnt != 0) \
                  continue; 

//}

//#define    DelayUs(x)     for(unsigned char _dcnt=x;_dcnt>0;--_dcnt){}
/**/

 extern void DelayMs(unsigned char);
 extern void Pause(unsigned char);       //-- Approx delay in seconds
#endif


//1wire.c
#define D_RiseSpace 10       // Rise Time + Minimum Space (3uS+1uS absolute min)

#ifndef D_PIN
 #error D_PIN Must Be Defined for 1-wire Bus I/O
#endif

#ifndef D_TRIS
 #error D_TRIS Must be defined for 1-wire Bus I/O
#endif

bit  D_Presence;
bit  D_ShortCircuit;
unsigned char  D_Error;
bit  D_Data;


//****************************************************************************
//D_Reset  -- Resets the 1-wire bus and checks for presence & short cct
//****************************************************************************
void D_Reset(void)
{
 char count=20;
 //-- Reset the status bits
 D_Error=0;

 //-- Ensure Correct port pin settings
 D_TRIS=1;
 D_PIN=0;

 //-- Start the reset Pulse
 D_TRIS=0;          //-- Pull Line Low to start reset pulse
while(count>0){count--;
  DelayUs(5);      //-- 480uS Delay
 }
 D_TRIS=1;          //-- Release the line
 DelayUs(60);       //-- Delay to about centre of presence pulse
 D_Presence=D_PIN;  //-- Get Presence status 1=None 0=something there

// for(
count=41;
while(count>0){
//count--) //-- (480-60)uS delay till end
 
  DelayUs(10);
count--;
 }

 D_ShortCircuit=D_PIN;  //-- Check for short circuit on bus pin.

 if(D_ShortCircuit==0)  //-- If short circuit then indicate an error
 {
  D_Error=1;
 }

 if(D_Presence==1)      //-- If no device detected indicate an error
 {
  D_Error+=2;
 }

 DelayUs(D_RiseSpace);    //-- Rise time + Min Space

}
//******************END OF D_Reset


//****************************************************************************
// D_Write
//****************************************************************************
void D_Write(Data)
{
 char count=8;
// for(;
while(count>0){
//;count--)
 //{
  D_Data= Data & 0x01;    //-- Get LSB

  //-- Write the bit to the port
  D_PIN=0;
  D_TRIS=0;               //-- Lower the port
  DelayUs(5);             //-- Time slot start time
  D_TRIS=D_Data;          //-- Output the data to the port
  DelayUs(50);            //-- Finish Timeslot
  DelayUs(5);

  D_TRIS=1;               //-- Ensure Release of Port Pin

  //-- Delay Between Bits
  DelayUs(D_RiseSpace);             //-- Recovery time between Bits

  //-- Prep Next Bit
  Data=Data>>1;           //-- Shift next bit into place
  count--;
 }
 DelayUs(D_RiseSpace);    //-- Rise time + Min Space
}
//******************END OF D_Write

//****************************************************************************
// D_Read
//****************************************************************************
char D_Read(void)
{
 char count=8,data=0;
 //for(;
while(count>0){
//count--)
 //{
  //-- Write the bit to the port
  D_PIN=0;
  D_TRIS=0;               //-- Lower the port
//  DelayUs(5);             //-- Time slot start time
  DelayUs(3);             //-- Time slot start time
  D_TRIS=1;               //-- Release port for reading
//  DelayUs(5);             //-- Get close to center of timeslot
  DelayUs(9);             //-- Get close to center of timeslot
  D_Data=D_PIN;           //-- Read the data bit in
  DelayUs(55);            //-- Finish the timeslot



  //-- Put data into the byte
  data = data >> 1;        //-- Shift previous bits across
  if(D_Data==1)            //-- If data was high then add High bit to data
  {
   data +=0x80;
  }
  //-- Delay Between Bits
  DelayUs(D_RiseSpace);             //-- Recovery time between Bits
count--;
 }
 DelayUs(D_RiseSpace);    //-- Rise time + Min Space
 return(data);
}
//******************END OF D_Read


//**************************************************************************
//D_MatchRom - Matches the ROM Code to device
//**************************************************************************
#ifdef _D_MATCHROM_
void D_MatchRom(unsigned char position)
{
 char count;
 D_Write(0x55);          //-- Match Rom
                         //-- Send the Address ROM Code.
 //for(count=0;count<8;count++)
 count=0;
while(count<8){
  D_Write(gete(position));
  position++;
count++;
 }
}
#endif
//****************** END OF D_SendAddress

//**************************************************************************
//D_ReadRom - Reads the ROM Code from a device
//**************************************************************************
#ifdef _D_READROM_
void D_ReadRom(char *address)
{
 char count=0;
 D_Write(0x33);          //-- Read Rom
                         //-- Read in the ROM code from the Device
 //for(count=0;count<8;count++)
 while(count<8){
  address[count]=D_Read();
  address++;
count++;
 }
}
#endif
//****************** END OF D_ReadRom

//**************************************************************************
//
//**************************************************************************

//****************** END OF

 

Thread Starter

coldpenguin

Joined Apr 18, 2010
165
If the compiler is using a standard division routine it could use a lot of space.
Dividing by a constant can often be optimised by using powers of 2, for example dividing by 10 is approximately 26/256, so you add together 1/16, 1/32 and 1/128 of the source.
There's a code generator here but it's for assembler:
http://www.piclist.com/techref/piclist/codegen/constdivmul.htm
Thanks for that, I was wondering whether I use a power of two as an optimisation.
I believe my digits[2] currently displays digits 0-8 instead of 1-10, but it is difficult to test.

Currently two DS18b20s show 20.1 and 20.2, and the DS18s20 shows 21.4
The b20s are on long leads, whereas the s20 is in the breadboard, which could explain a slight difference in temp)
 

t06afre

Joined May 11, 2009
5,934
Perhaps it is better to use MPLAB to create a zip file of your project. And which PIC do you use? And also what is the formula to convert the DS1820 reading to a temprature?
 

Thread Starter

coldpenguin

Joined Apr 18, 2010
165
Perhaps it is better to use MPLAB to create a zip file of your project. And which PIC do you use? And also what is the formula to convert the DS1820 reading to a temprature?
Ok, done project package as zip and attached it.
The pic is a 16f84a

Formula to convert is:
read 8 bytes from DS1820
LSB then MSB are the first two bytes of the temperature, times 2
So I create an INT (two bytes, rather than a char), increase the MSB by 2^8, add to INT + LSB
Then the value divided by 2 would be the temp, to the nearest half a degree.
To calculate closer, remove the decimal, subtract 0.25, then add (clock-counts - cycles remaining)/(clock-counts).
These are bytes 7 and 6
However, byte 7 is always 16 (0x10)
That is for the DS182s0 (sensor 2)

For the DS18b20 then the full resolution is in the MSB and LSB

http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf
http://datasheets.maxim-ic.com/en/ds/DS18S20.pdf

Basically sensor 2 is the s20, the other two are b20, for 'portability' I should check that gete(sensornum*8+0x0e) !=0x10 however I was trying to debug a problem, and removing the extra complication seemed easier.

crystal freq is 4mhz, although code freq had to be changed to get delays correct
 

Attachments

Markd77

Joined Sep 7, 2009
2,806
Strange chip.
After looking at the datasheet I'd be tempted to use a case statement or whatever creates an efficient lookup table in C.
Presumably COUNT_REMAIN is 0-15 so these would be the part after the decimal point (you have to subtract 1 from the integer part of the temperature for the last 3 entries).
COUNT_REMAIN | Decimal
0| 75
1| 69
2| 63
3| 56
4| 50
5| 44
6| 38
7| 31
8| 25
9| 19
10| 13
11| 6
12| 0
13| 94
14| 88
15| 81
 

Thread Starter

coldpenguin

Joined Apr 18, 2010
165
1wire.c
Rich (BB code):
#define D_RiseSpace 10       // Rise Time + Minimum Space (3uS+1uS absolute min)

#ifndef D_PIN
 #error D_PIN Must Be Defined for 1-wire Bus I/O
#endif

#ifndef D_TRIS
 #error D_TRIS Must be defined for 1-wire Bus I/O
#endif

bit  D_Presence;
bit  D_ShortCircuit;
unsigned char  D_Error;
bit  D_Data;


//****************************************************************************
//D_Reset  -- Resets the 1-wire bus and checks for presence & short cct
//****************************************************************************
void D_Reset(void)
{
 char count=20;
 //-- Reset the status bits
 D_Error=0;

 //-- Ensure Correct port pin settings
 D_TRIS=1;
 D_PIN=0;

 //-- Start the reset Pulse
 D_TRIS=0;          //-- Pull Line Low to start reset pulse
while(count>0){count--;
  DelayUs(5);      //-- 480uS Delay
 }
 D_TRIS=1;          //-- Release the line
 DelayUs(60);       //-- Delay to about centre of presence pulse
 D_Presence=D_PIN;  //-- Get Presence status 1=None 0=something there

// for(
count=41;
while(count>0){
//count--) //-- (480-60)uS delay till end
 
  DelayUs(10);
count--;
 }

 D_ShortCircuit=D_PIN;  //-- Check for short circuit on bus pin.

 if(D_ShortCircuit==0)  //-- If short circuit then indicate an error
 {
  D_Error=1;
 }

 if(D_Presence==1)      //-- If no device detected indicate an error
 {
  D_Error+=2;
 }

 DelayUs(D_RiseSpace);    //-- Rise time + Min Space

}
//******************END OF D_Reset


//****************************************************************************
// D_Write
//****************************************************************************
void D_Write(Data)
{
 char count=8;
// for(;
while(count>0){
//;count--)
 //{
  D_Data= Data & 0x01;    //-- Get LSB

  //-- Write the bit to the port
  D_PIN=0;
  D_TRIS=0;               //-- Lower the port
  DelayUs(5);             //-- Time slot start time
  D_TRIS=D_Data;          //-- Output the data to the port
  DelayUs(50);            //-- Finish Timeslot
  DelayUs(5);

  D_TRIS=1;               //-- Ensure Release of Port Pin

  //-- Delay Between Bits
  DelayUs(D_RiseSpace);             //-- Recovery time between Bits

  //-- Prep Next Bit
  Data=Data>>1;           //-- Shift next bit into place
  count--;
 }
 DelayUs(D_RiseSpace);    //-- Rise time + Min Space
}
//******************END OF D_Write

//****************************************************************************
// D_Read
//****************************************************************************
char D_Read(void)
{
 char count=8,data=0;
 //for(;
while(count>0){
//count--)
 //{
  //-- Write the bit to the port
  D_PIN=0;
  D_TRIS=0;               //-- Lower the port
//  DelayUs(5);             //-- Time slot start time
  DelayUs(3);             //-- Time slot start time
  D_TRIS=1;               //-- Release port for reading
//  DelayUs(5);             //-- Get close to center of timeslot
  DelayUs(9);             //-- Get close to center of timeslot
  D_Data=D_PIN;           //-- Read the data bit in
  DelayUs(55);            //-- Finish the timeslot



  //-- Put data into the byte
  data = data >> 1;        //-- Shift previous bits across
  if(D_Data==1)            //-- If data was high then add High bit to data
  {
   data +=0x80;
  }
  //-- Delay Between Bits
  DelayUs(D_RiseSpace);             //-- Recovery time between Bits
count--;
 }
 DelayUs(D_RiseSpace);    //-- Rise time + Min Space
 return(data);
}
//******************END OF D_Read


//**************************************************************************
//D_MatchRom - Matches the ROM Code to device
//**************************************************************************
#ifdef _D_MATCHROM_
void D_MatchRom(unsigned char position)
{
 char count;
 D_Write(0x55);          //-- Match Rom
                         //-- Send the Address ROM Code.
 //for(count=0;count<8;count++)
 count=0;
while(count<8){
  D_Write(gete(position));
  position++;
count++;
 }
}
#endif
//****************** END OF D_SendAddress

//**************************************************************************
//D_ReadRom - Reads the ROM Code from a device
//**************************************************************************
#ifdef _D_READROM_
void D_ReadRom(char *address)
{
 char count=0;
 D_Write(0x33);          //-- Read Rom
                         //-- Read in the ROM code from the Device
 //for(count=0;count<8;count++)
 while(count<8){
  address[count]=D_Read();
  address++;
count++;
 }
}
#endif
//****************** END OF D_ReadRom

//**************************************************************************
//
//**************************************************************************

//****************** END OF
 

Thread Starter

coldpenguin

Joined Apr 18, 2010
165
Strange chip.
After looking at the datasheet I'd be tempted to use a case statement or whatever creates an efficient lookup table in C.
Thanks, I did try that however the words used, seems more than a little bit of code I just managed:

128 words
Rich (BB code):
if(temp[6]>12) tres--;
...
switch(temp[6]){
case 0:digits[2]=7;break;
case 1:;
case 2:digits[2]=6;break;
case 3:;
case 4:digits[2]=5;break;
case 5:digits[2]=4;break;
case 6:;
case 7:digits[2]=3;break;
case 8:digits[2]=2;break;
case 9:digits[2]=1;
case 10:digits[2]=1;break;
case 11:;
case 12:digits[2]=0;break;
case 13:digits[2]=9;break;
case 14:;
default:digits[2]=8;break;
}
116 words
Rich (BB code):
if(temp[6]>12) tres--;
digits[2]=10+(10*((12-temp[6])))>>4;
if(digits[2]>9) digits[2]-=10;
not good, but better than nothing.
Now the next challenge is, looking at the divisor generators, they produce short code (I think it was 28 words), but could be a degree out, which is not nice.
Rich (BB code):
digits[0]=(tres)/10;
digits[1]=tres-digits[0]*10;
 

John P

Joined Oct 14, 2008
2,026
You will do much much better by repeatedly subtracting 10 from the original quantity, while counting loops as you go. This process will also give you a remainder at the end, which is the units digit.
 

Markd77

Joined Sep 7, 2009
2,806
You could put the packed BCD version of the decimal in the lookup table instead of an integer, then you just have to extract the nibbles.
 

Thread Starter

coldpenguin

Joined Apr 18, 2010
165
You will do much much better by repeatedly subtracting 10 from the original quantity, while counting loops as you go. This process will also give you a remainder at the end, which is the units digit.
Strange, last night whilst I was sleeping I came up with a thought similar to that. In theory, worst case scenario would be 10 loops (and then we are talking boiling water!) and I should have the first two digits calculated.

You could put the packed BCD version of the decimal in the lookup table instead of an integer, then you just have to extract the nibbles.
I think I understand what you mean, but I think that might just push the problem down the line when the code will need to work out whether it should enable the cooling or not.
 

WBahn

Joined Mar 31, 2012
30,087
If you aren't pushed for speed, you could try something real basic, such as:

Rich (BB code):
// Convert V (0<=V<100) into two digits, d[1]d[0]
d[1]=0;
d[0] = v;
while (d[0] > 10)
{
    v -= 10;
    d[1]++;
}
That should be pretty easy on code space.
 

t06afre

Joined May 11, 2009
5,934
Your code is messy. Not easy to see what is going on. Next time if you ask for help. At least take the time to make proper comments. It helped somewhat to replace the delay functions with proper Hi-Tech C delay functions (__delay_us() ). And by rearranging the code. You do not need to include anything else than htc.h file. Will it also be correct to assume what you will only handle temperatures equal or greater than zero.
Rich (BB code):
#define _XTAL_FREQ 4000000 //12000000
#include <htc.h>
//#include "../delay.h"
//#include <stdlib.h>
unsigned char gete(unsigned char address);
#define sleep()        asm("sleep")
#define _D_MATCHROM_
#define _D_READROM_
#define D_PIN RA0
#define D_TRIS TRISA0
//#include "1wire.c"
__CONFIG( FOSC_HS & WDTE_OFF);
unsigned char gete(unsigned char address){
   EEADR=address;
   RD=1; 
   return(EEDATA);
}
//1wire.c
#define D_RiseSpace 10       // Rise Time + Minimum Space (3uS+1uS absolute min)
#ifndef D_PIN
 #error D_PIN Must Be Defined for 1-wire Bus I/O
#endif
#ifndef D_TRIS
 #error D_TRIS Must be defined for 1-wire Bus I/O
#endif
bit  D_Presence;
bit  D_ShortCircuit;
unsigned char  D_Error;
bit  D_Data;
 
//****************************************************************************
//D_Reset  -- Resets the 1-wire bus and checks for presence & short cct
//****************************************************************************
void D_Reset(void)
{
 char count=20;
 //-- Reset the status bits
 D_Error=0;
 //-- Ensure Correct port pin settings
 D_TRIS=1;
 D_PIN=0;
 //-- Start the reset Pulse
 D_TRIS=0;          //-- Pull Line Low to start reset pulse
while(count>0){count--;
  __delay_us(5);      //-- 480uS Delay
 }
 D_TRIS=1;          //-- Release the line
 __delay_us(60);       //-- Delay to about centre of presence pulse
 D_Presence=D_PIN;  //-- Get Presence status 1=None 0=something there
// for(
count=41;
while(count>0){
//count--) //-- (480-60)uS delay till end
 
  __delay_us(10);
count--;
 }
 D_ShortCircuit=D_PIN;  //-- Check for short circuit on bus pin.
 if(D_ShortCircuit==0)  //-- If short circuit then indicate an error
 {
  D_Error=1;
 }
 if(D_Presence==1)      //-- If no device detected indicate an error
 {
  D_Error+=2;
 }
 __delay_us(D_RiseSpace);    //-- Rise time + Min Space
}
//******************END OF D_Reset
 
//****************************************************************************
// D_Write
//****************************************************************************
void D_Write(Data)
{
 char count=8;
// for(;
while(count>0){
//;count--)
 //{
  D_Data= Data & 0x01;    //-- Get LSB
  //-- Write the bit to the port
  D_PIN=0;
  D_TRIS=0;               //-- Lower the port
  __delay_us(5);             //-- Time slot start time
  D_TRIS=D_Data;          //-- Output the data to the port
  __delay_us(50);            //-- Finish Timeslot
  __delay_us(5);
  D_TRIS=1;               //-- Ensure Release of Port Pin
  //-- Delay Between Bits
  __delay_us(D_RiseSpace);             //-- Recovery time between Bits
  //-- Prep Next Bit
  Data=Data>>1;           //-- Shift next bit into place
  count--;
 }
 __delay_us(D_RiseSpace);    //-- Rise time + Min Space
}
//******************END OF D_Write
//****************************************************************************
// D_Read
//****************************************************************************
char D_Read(void)
{
 char count=8,data=0;
 //for(;
while(count>0){
//count--)
 //{
  //-- Write the bit to the port
  D_PIN=0;
  D_TRIS=0;               //-- Lower the port
//  __delay_us(5);             //-- Time slot start time
  __delay_us(3);             //-- Time slot start time
  D_TRIS=1;               //-- Release port for reading
//  __delay_us(5);             //-- Get close to center of timeslot
  __delay_us(9);             //-- Get close to center of timeslot
  D_Data=D_PIN;           //-- Read the data bit in
  __delay_us(55);            //-- Finish the timeslot
 
  //-- Put data into the byte
  data = data >> 1;        //-- Shift previous bits across
  if(D_Data==1)            //-- If data was high then add High bit to data
  {
   data +=0x80;
  }
  //-- Delay Between Bits
  __delay_us(D_RiseSpace);             //-- Recovery time between Bits
count--;
 }
 __delay_us(D_RiseSpace);    //-- Rise time + Min Space
 return(data);
}
//******************END OF D_Read
 
//**************************************************************************
//D_MatchRom - Matches the ROM Code to device
//**************************************************************************
#ifdef _D_MATCHROM_
void D_MatchRom(unsigned char position)
{
 char count;
 D_Write(0x55);          //-- Match Rom
                         //-- Send the Address ROM Code.
 //for(count=0;count<8;count++)
 count=0;
while(count<8){
  D_Write(gete(position));
  position++;
count++;
 }
}
#endif
//****************** END OF D_SendAddress
//**************************************************************************
//D_ReadRom - Reads the ROM Code from a device
//**************************************************************************
#ifdef _D_READROM_
void D_ReadRom(char *address)
{
 char count=0;
 D_Write(0x33);          //-- Read Rom
                         //-- Read in the ROM code from the Device
 //for(count=0;count<8;count++)
 while(count<8){
  address[count]=D_Read();
  address++;
count++;
 }
}
#endif
//****************** END OF D_ReadRom
//**************************************************************************
//
//**************************************************************************
//****************** END OF
void gettemp(unsigned char sensornum,unsigned char (*digits)){
D_Reset();
//D_Write(0xcc);
D_MatchRom(0x0e+8*sensornum);
D_Write(0xbe);
unsigned char temp[8];
unsigned char r=0;
while(r<8){
temp[r]=D_Read();
r++;
}
unsigned int hres=0;
unsigned int tres=0;
tres =temp[1]<<8;
tres |=temp[0];
if(0x02 !=sensornum){
hres=tres<<4;
}else{
tres >>= 1;
tres <<= 8;
tres -= 0x100>>2;
hres =0x10-temp[6];
hres <<=4;
//hres /=0x10;
//hres >>=4;
hres +=tres;
}
//div_t ty=div(hres,2);
digits[0]=(hres>>8)/10;
digits[1]=(hres>>8)-digits[0]*10;
//hres-=(digits[0]*10)<<8;
//hres-=(digits[1])<<8;
//hres *=10;
digits[2]=hres%256;
//((hres)>>6)&0b00000111;
//int t=10*hres>>8;
}
output(unsigned char * o,unsigned char i){
unsigned char j=0;
while(j<4){
/*unsigned char cnt=0;
switch (j){
case 0: PORTA=gete(0x00);
break;
case 1: PORTA=gete(0x01); 
break;
case 2: PORTA=gete(0x02);
break;
default: PORTA=gete(0x03);
}*/
PORTA=gete(j);
        if(i>125 && j==1){
            PORTB=o[j]-0b10000000;
        }else{
            PORTB=o[j];
        }
/*unsigned char cnt=0;
cnt=0;
while(cnt<4){
cnt++;
}*/
#asm
NOP
NOP
NOP
#endasm
//asm("NOP;");
//asm("NOP;");
//asm("NOP;");
        PORTB=0xFF;
        PORTA=0x00;
j++;
    }
 
}
 
void main()    {
unsigned char o[4];  
unsigned char temps[3][3];
o[0]=0;
/*while(o[0]<3){      // this saved 48!
temps[o[0]][0]=0;
temps[o[0]][1]=0;
temps[o[0]][2]=0;
o[0]++;
}
o[0]=0;*/
TRISA=0b00000000;
TRISB=0b00000000;
PORTA=0b00000000;
unsigned char y=0x00;
unsigned char u=0;
unsigned char p=0;
D_Reset();
D_Write(0xcc);
D_Write(0x44);
while(1){
o[3]=0b11111111-(0b00000001<<u);
o[0]=gete(0x04+temps[0]);
o[1]=gete(0x04+temps[1]);
o[2]=gete(0x04+temps[2]);
unsigned char k=0;
while(k<10){
            unsigned char i=0;
            while(i<250){
                i++;
                output(o,i);
            }
            k++;
        }
        y++;
        if(y>7){
y=0;
while(y<3){
gettemp(y,temps[y]);
y++;
}
D_Reset();
D_Write(0xcc);
D_Write(0x44);
y=0;
}
        u++;
        if(u>2) u=0;
}
}
 
#asm
     psect eedata, delta=2, abs, ovrld
     ORG 2100H   ; starting point of EEPROM on 16F84
//ports
     DW 0x08,0x04,0x0c,0x00;
//numbers
      dw 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90;
     DW 0x28,0x99, 0xce,0x8d,0x02,0x00,0x00,0xb2 ; 
     DW 0x28,0x47, 0xa6,0x8d,0x02,0x00,0x00,0x4a ; 
     DW 0x10,0xbc,53H, 0xf5,01H,0x08,00H,0x77 ; 
#endasm
 
 
 
Top