Code optimisation, reading temp from DS1820 (picc)

Discussion in 'Programmer's Corner' started by coldpenguin, May 7, 2012.

  1. coldpenguin

    Thread Starter Active Member

    Apr 18, 2010
    165
    9
    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).

    Code ( (Unknown Language)):
    1.  
    2. void gettemp(unsigned char sensornum,unsigned char (*digits)){
    3.  
    4.   D_Reset();
    5.   D_MatchRom(0x0e+8*sensornum);
    6.   D_Write(0xbe);
    7.   unsigned char temp[8];
    8.   unsigned char r=0;
    9.   while(r<8){
    10.     temp[r]=D_Read();
    11.     r++;
    12.   }
    13.   unsigned int hres=0;
    14.   unsigned int tres=0;
    15.   tres =temp[1]<<8;
    16.   tres |=temp[0];
    17.   if(0x02 !=sensornum){
    18.     hres=tres<<4;
    19.   }else{
    20.     tres >>= 1;
    21.     tres <<= 8;
    22.     tres -= 0x100>>2;
    23.     hres =0x10-temp[6];
    24.     hres <<=4;
    25.     hres +=tres;
    26.   }
    27. //div_t ty=div(hres,2);
    28.  
    29.   digits[0]=(hres>>8)/10;
    30.   digits[1]=(hres>>8)-digits[0]*10;
    31.  
    32. //hres-=(digits[0]*10)<<8;
    33. //hres-=(digits[1])<<8;
    34. //hres *=10;
    35.  
    36.   digits[2]=hres%256;
    37. //((hres)>>6)&0b00000111;
    38. //int t=10*hres>>8;
    39.  
    40. }
     
  2. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
  3. coldpenguin

    Thread Starter Active Member

    Apr 18, 2010
    165
    9
    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)


    Code ( (Unknown Language)):
    1. 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"
    2. HI-TECH C Compiler for PIC10/12/16 MCUs (Lite Mode)  V9.83
    3. Copyright (C) 2011 Microchip Technology Inc.
    4. (1273) Omniscient Code Generation not available in Lite mode (warning)
    5.  
    6. Memory Summary:
    7.     Program space        used   3B1h (   945) of   400h words   ( 92.3%)
    8.     Data space           used    37h (    55) of    44h bytes   ( 80.9%)
    9.     EEPROM space         used     0h (     0) of    40h bytes   (  0.0%)
    10.     Configuration bits   used     1h (     1) of     1h word    (100.0%)
    11.     ID Location space    used     0h (     0) of     4h bytes   (  0.0%)
    12.  
    13.  
    14. Running this compiler in PRO mode, with Omniscient Code Generation enabled,
    15. produces code which is typically 40% smaller than in Lite mode.
    16. The HI-TECH C PRO compiler output for this code could be 378 words smaller.
    17. See http://microchip.htsoft.com/portal/pic_pro for more information.
    18.  
    19. Loaded C:\Users\penguin\Syncdir\Microchip\Watercool\watercool.cof.
    20.  
     
    Last edited: May 7, 2012
  4. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    Will you be able to post the full code. What do want to do with the result from DS1820
     
  5. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    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
     
  6. coldpenguin

    Thread Starter Active Member

    Apr 18, 2010
    165
    9
    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
    Code ( (Unknown Language)):
    1.  
    2.    
    3. #ifndef _XTAL_FREQ
    4.      // Unless specified elsewhere, 4MHz system frequency is assumed
    5. #define XTAL_FREQ 500KHZ //12000000
    6. #endif
    7. #include <pic.h>
    8. #include "../delay.h"
    9. #include <stdlib.h>
    10.  
    11. unsigned char gete(unsigned char address);
    12. #define sleep()        asm("sleep")
    13. #define _D_MATCHROM_
    14. #define _D_READROM_
    15. #define D_PIN RA0
    16. #define D_TRIS TRISA0
    17. #include "../1wire.c"
    18. __CONFIG( FOSC_HS & WDTE_OFF);
    19.  
    20. unsigned char gete(unsigned char address){
    21.    EEADR=address;
    22.    RD=1;
    23.    return(EEDATA);
    24. }
    25.  
    26. void gettemp(unsigned char sensornum,unsigned char (*digits)){
    27.  
    28. D_Reset();
    29. //D_Write(0xcc);
    30. D_MatchRom(0x0e+8*sensornum);
    31. D_Write(0xbe);
    32. unsigned char temp[8];
    33. unsigned char r=0;
    34. while(r<8){
    35. temp[r]=D_Read();
    36. r++;
    37. }
    38. unsigned int hres=0;
    39. unsigned int tres=0;
    40. tres =temp[1]<<8;
    41. tres |=temp[0];
    42. if(0x02 !=sensornum){
    43. hres=tres<<4;
    44. }else{
    45. tres >>= 1;
    46. tres <<= 8;
    47. tres -= 0x100>>2;
    48. hres =0x10-temp[6];
    49. hres <<=4;
    50. //hres /=0x10;
    51.  
    52. //hres >>=4;
    53. hres +=tres;
    54.  
    55. }
    56. //div_t ty=div(hres,2);
    57.  
    58. digits[0]=(hres>>8)/10;
    59. digits[1]=(hres>>8)-digits[0]*10;
    60. //hres-=(digits[0]*10)<<8;
    61. //hres-=(digits[1])<<8;
    62. //hres *=10;
    63. digits[2]=hres%256;
    64. //((hres)>>6)&0b00000111;
    65. //int t=10*hres>>8;
    66.  
    67. }
    68. output(unsigned char * o,unsigned char i){
    69.  
    70. unsigned char j=0;
    71. while(j<4){
    72. /*unsigned char cnt=0;
    73. switch (j){
    74. case 0: PORTA=gete(0x00);
    75. break;
    76. case 1: PORTA=gete(0x01);
    77. break;
    78. case 2: PORTA=gete(0x02);
    79. break;
    80. default: PORTA=gete(0x03);
    81. }*/
    82. PORTA=gete(j);
    83.         if(i>125 && j==1){
    84.             PORTB=o[j]-0b10000000;
    85.         }else{
    86.             PORTB=o[j];
    87.         }
    88.  
    89. /*unsigned char cnt=0;
    90. cnt=0;
    91. while(cnt<4){
    92. cnt++;
    93. }*/
    94. #asm
    95. NOP
    96. NOP
    97. NOP
    98. #endasm
    99. //asm("NOP;");
    100. //asm("NOP;");
    101. //asm("NOP;");
    102.  
    103.         PORTB=0xFF;
    104.         PORTA=0x00;
    105. j++;
    106.     }
    107.  
    108.  
    109. }
    110.  
    111.  
    112. void main()    {
    113. unsigned char o[4];  
    114. unsigned char temps[3][3];
    115.  
    116. o[0]=0;
    117. /*while(o[0]<3){      // this saved 48!
    118. temps[o[0]][0]=0;
    119. temps[o[0]][1]=0;
    120. temps[o[0]][2]=0;
    121. o[0]++;
    122. }
    123. o[0]=0;*/
    124. TRISA=0b00000000;
    125. TRISB=0b00000000;
    126. PORTA=0b00000000;
    127.  
    128. unsigned char y=0x00;
    129. unsigned char u=0;
    130. unsigned char p=0;
    131. D_Reset();
    132. D_Write(0xcc);
    133. D_Write(0x44);
    134. while(1){
    135. o[3]=0b11111111-(0b00000001<<u);
    136. o[0]=gete(0x04+temps[u][0]);
    137. o[1]=gete(0x04+temps[u][1]);
    138. o[2]=gete(0x04+temps[u][2]);
    139. unsigned char k=0;
    140. while(k<10){
    141.             unsigned char i=0;
    142.             while(i<250){
    143.                 i++;
    144.                 output(o,i);
    145.             }
    146.             k++;
    147.         }
    148.  
    149.         y++;
    150.         if(y>7){
    151. y=0;
    152. while(y<3){
    153. gettemp(y,temps[y]);
    154. y++;
    155. }
    156. D_Reset();
    157. D_Write(0xcc);
    158. D_Write(0x44);
    159. y=0;
    160. }
    161.         u++;
    162.         if(u>2) u=0;
    163.  
    164. }
    165. }
    166.  
    167.  
    168.  
    169. #asm
    170.      psect eedata, delta=2, abs, ovrld
    171.      ORG 2100H   ; starting point of EEPROM on 16F84
    172. //ports
    173.      DW 0x08,0x04,0x0c,0x00;
    174. //numbers
    175.       dw 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90;
    176.      DW 0x28,0x99, 0xce,0x8d,0x02,0x00,0x00,0xb2 ;
    177.      DW 0x28,0x47, 0xa6,0x8d,0x02,0x00,0x00,0x4a ;
    178.      DW 0x10,0xbc,53H, 0xf5,01H,0x08,00H,0x77 ;
    179.  
    180. #endasm
    181.      
    182. //delay.h
    183.  
    184. #ifndef DELAY_ROUTINE       //-- Check if already loaded!!!
    185.  
    186.  
    187.  #define    MHZ    *1000            /* number of kHz in a MHz */
    188.  #define    KHZ    *1            /* number of kHz in a kHz */
    189.  
    190.  #define    DelayUs(x) unsigned char _dcnt;  \
    191.               _dcnt =1; \
    192.               while(--_dcnt != 0) \
    193.                   continue;
    194.  
    195. //}
    196.  
    197. //#define    DelayUs(x)     for(unsigned char _dcnt=x;_dcnt>0;--_dcnt){}
    198. /**/
    199.  
    200.  extern void DelayMs(unsigned char);
    201.  extern void Pause(unsigned char);       //-- Approx delay in seconds
    202. #endif
    203.  
    204.  
    205. //1wire.c
    206. #define D_RiseSpace 10       // Rise Time + Minimum Space (3uS+1uS absolute min)
    207.  
    208. #ifndef D_PIN
    209.  #error D_PIN Must Be Defined for 1-wire Bus I/O
    210. #endif
    211.  
    212. #ifndef D_TRIS
    213.  #error D_TRIS Must be defined for 1-wire Bus I/O
    214. #endif
    215.  
    216. bit  D_Presence;
    217. bit  D_ShortCircuit;
    218. unsigned char  D_Error;
    219. bit  D_Data;
    220.  
    221.  
    222. //****************************************************************************
    223. //D_Reset  -- Resets the 1-wire bus and checks for presence & short cct
    224. //****************************************************************************
    225. void D_Reset(void)
    226. {
    227.  char count=20;
    228.  //-- Reset the status bits
    229.  D_Error=0;
    230.  
    231.  //-- Ensure Correct port pin settings
    232.  D_TRIS=1;
    233.  D_PIN=0;
    234.  
    235.  //-- Start the reset Pulse
    236.  D_TRIS=0;          //-- Pull Line Low to start reset pulse
    237. while(count>0){count--;
    238.   DelayUs(5);      //-- 480uS Delay
    239.  }
    240.  D_TRIS=1;          //-- Release the line
    241.  DelayUs(60);       //-- Delay to about centre of presence pulse
    242.  D_Presence=D_PIN;  //-- Get Presence status 1=None 0=something there
    243.  
    244. // for(
    245. count=41;
    246. while(count>0){
    247. //count--) //-- (480-60)uS delay till end
    248.  
    249.   DelayUs(10);
    250. count--;
    251.  }
    252.  
    253.  D_ShortCircuit=D_PIN;  //-- Check for short circuit on bus pin.
    254.  
    255.  if(D_ShortCircuit==0)  //-- If short circuit then indicate an error
    256.  {
    257.   D_Error=1;
    258.  }
    259.  
    260.  if(D_Presence==1)      //-- If no device detected indicate an error
    261.  {
    262.   D_Error+=2;
    263.  }
    264.  
    265.  DelayUs(D_RiseSpace);    //-- Rise time + Min Space
    266.  
    267. }
    268. //******************END OF D_Reset
    269.  
    270.  
    271. //****************************************************************************
    272. // D_Write
    273. //****************************************************************************
    274. void D_Write(Data)
    275. {
    276.  char count=8;
    277. // for(;
    278. while(count>0){
    279. //;count--)
    280.  //{
    281.   D_Data= Data & 0x01;    //-- Get LSB
    282.  
    283.   //-- Write the bit to the port
    284.   D_PIN=0;
    285.   D_TRIS=0;               //-- Lower the port
    286.   DelayUs(5);             //-- Time slot start time
    287.   D_TRIS=D_Data;          //-- Output the data to the port
    288.   DelayUs(50);            //-- Finish Timeslot
    289.   DelayUs(5);
    290.  
    291.   D_TRIS=1;               //-- Ensure Release of Port Pin
    292.  
    293.   //-- Delay Between Bits
    294.   DelayUs(D_RiseSpace);             //-- Recovery time between Bits
    295.  
    296.   //-- Prep Next Bit
    297.   Data=Data>>1;           //-- Shift next bit into place
    298.   count--;
    299.  }
    300.  DelayUs(D_RiseSpace);    //-- Rise time + Min Space
    301. }
    302. //******************END OF D_Write
    303.  
    304. //****************************************************************************
    305. // D_Read
    306. //****************************************************************************
    307. char D_Read(void)
    308. {
    309.  char count=8,data=0;
    310.  //for(;
    311. while(count>0){
    312. //count--)
    313.  //{
    314.   //-- Write the bit to the port
    315.   D_PIN=0;
    316.   D_TRIS=0;               //-- Lower the port
    317. //  DelayUs(5);             //-- Time slot start time
    318.   DelayUs(3);             //-- Time slot start time
    319.   D_TRIS=1;               //-- Release port for reading
    320. //  DelayUs(5);             //-- Get close to center of timeslot
    321.   DelayUs(9);             //-- Get close to center of timeslot
    322.   D_Data=D_PIN;           //-- Read the data bit in
    323.   DelayUs(55);            //-- Finish the timeslot
    324.  
    325.  
    326.  
    327.   //-- Put data into the byte
    328.   data = data >> 1;        //-- Shift previous bits across
    329.   if(D_Data==1)            //-- If data was high then add High bit to data
    330.   {
    331.    data +=0x80;
    332.   }
    333.   //-- Delay Between Bits
    334.   DelayUs(D_RiseSpace);             //-- Recovery time between Bits
    335. count--;
    336.  }
    337.  DelayUs(D_RiseSpace);    //-- Rise time + Min Space
    338.  return(data);
    339. }
    340. //******************END OF D_Read
    341.  
    342.  
    343. //**************************************************************************
    344. //D_MatchRom - Matches the ROM Code to device
    345. //**************************************************************************
    346. #ifdef _D_MATCHROM_
    347. void D_MatchRom(unsigned char position)
    348. {
    349.  char count;
    350.  D_Write(0x55);          //-- Match Rom
    351.                          //-- Send the Address ROM Code.
    352.  //for(count=0;count<8;count++)
    353.  count=0;
    354. while(count<8){
    355.   D_Write(gete(position));
    356.   position++;
    357. count++;
    358.  }
    359. }
    360. #endif
    361. //****************** END OF D_SendAddress
    362.  
    363. //**************************************************************************
    364. //D_ReadRom - Reads the ROM Code from a device
    365. //**************************************************************************
    366. #ifdef _D_READROM_
    367. void D_ReadRom(char *address)
    368. {
    369.  char count=0;
    370.  D_Write(0x33);          //-- Read Rom
    371.                          //-- Read in the ROM code from the Device
    372.  //for(count=0;count<8;count++)
    373.  while(count<8){
    374.   address[count]=D_Read();
    375.   address++;
    376. count++;
    377.  }
    378. }
    379. #endif
    380. //****************** END OF D_ReadRom
    381.  
    382. //**************************************************************************
    383. //
    384. //**************************************************************************
    385.  
    386. //****************** END OF
    387.  
    388. [/u][/u][/u]
     
  7. coldpenguin

    Thread Starter Active Member

    Apr 18, 2010
    165
    9
    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)
     
  8. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    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?
     
  9. coldpenguin

    Thread Starter Active Member

    Apr 18, 2010
    165
    9
    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
     
  10. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    Can you post the 1wire.c file also
     
  11. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    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
     
  12. coldpenguin

    Thread Starter Active Member

    Apr 18, 2010
    165
    9
    1wire.c
    Code ( (Unknown Language)):
    1.  
    2.  
    3. #define D_RiseSpace 10       // Rise Time + Minimum Space (3uS+1uS absolute min)
    4.  
    5. #ifndef D_PIN
    6.  #error D_PIN Must Be Defined for 1-wire Bus I/O
    7. #endif
    8.  
    9. #ifndef D_TRIS
    10.  #error D_TRIS Must be defined for 1-wire Bus I/O
    11. #endif
    12.  
    13. bit  D_Presence;
    14. bit  D_ShortCircuit;
    15. unsigned char  D_Error;
    16. bit  D_Data;
    17.  
    18.  
    19. //****************************************************************************
    20. //D_Reset  -- Resets the 1-wire bus and checks for presence & short cct
    21. //****************************************************************************
    22. void D_Reset(void)
    23. {
    24.  char count=20;
    25.  //-- Reset the status bits
    26.  D_Error=0;
    27.  
    28.  //-- Ensure Correct port pin settings
    29.  D_TRIS=1;
    30.  D_PIN=0;
    31.  
    32.  //-- Start the reset Pulse
    33.  D_TRIS=0;          //-- Pull Line Low to start reset pulse
    34. while(count>0){count--;
    35.   DelayUs(5);      //-- 480uS Delay
    36.  }
    37.  D_TRIS=1;          //-- Release the line
    38.  DelayUs(60);       //-- Delay to about centre of presence pulse
    39.  D_Presence=D_PIN;  //-- Get Presence status 1=None 0=something there
    40.  
    41. // for(
    42. count=41;
    43. while(count>0){
    44. //count--) //-- (480-60)uS delay till end
    45.  
    46.   DelayUs(10);
    47. count--;
    48.  }
    49.  
    50.  D_ShortCircuit=D_PIN;  //-- Check for short circuit on bus pin.
    51.  
    52.  if(D_ShortCircuit==0)  //-- If short circuit then indicate an error
    53.  {
    54.   D_Error=1;
    55.  }
    56.  
    57.  if(D_Presence==1)      //-- If no device detected indicate an error
    58.  {
    59.   D_Error+=2;
    60.  }
    61.  
    62.  DelayUs(D_RiseSpace);    //-- Rise time + Min Space
    63.  
    64. }
    65. //******************END OF D_Reset
    66.  
    67.  
    68. //****************************************************************************
    69. // D_Write
    70. //****************************************************************************
    71. void D_Write(Data)
    72. {
    73.  char count=8;
    74. // for(;
    75. while(count>0){
    76. //;count--)
    77.  //{
    78.   D_Data= Data & 0x01;    //-- Get LSB
    79.  
    80.   //-- Write the bit to the port
    81.   D_PIN=0;
    82.   D_TRIS=0;               //-- Lower the port
    83.   DelayUs(5);             //-- Time slot start time
    84.   D_TRIS=D_Data;          //-- Output the data to the port
    85.   DelayUs(50);            //-- Finish Timeslot
    86.   DelayUs(5);
    87.  
    88.   D_TRIS=1;               //-- Ensure Release of Port Pin
    89.  
    90.   //-- Delay Between Bits
    91.   DelayUs(D_RiseSpace);             //-- Recovery time between Bits
    92.  
    93.   //-- Prep Next Bit
    94.   Data=Data>>1;           //-- Shift next bit into place
    95.   count--;
    96.  }
    97.  DelayUs(D_RiseSpace);    //-- Rise time + Min Space
    98. }
    99. //******************END OF D_Write
    100.  
    101. //****************************************************************************
    102. // D_Read
    103. //****************************************************************************
    104. char D_Read(void)
    105. {
    106.  char count=8,data=0;
    107.  //for(;
    108. while(count>0){
    109. //count--)
    110.  //{
    111.   //-- Write the bit to the port
    112.   D_PIN=0;
    113.   D_TRIS=0;               //-- Lower the port
    114. //  DelayUs(5);             //-- Time slot start time
    115.   DelayUs(3);             //-- Time slot start time
    116.   D_TRIS=1;               //-- Release port for reading
    117. //  DelayUs(5);             //-- Get close to center of timeslot
    118.   DelayUs(9);             //-- Get close to center of timeslot
    119.   D_Data=D_PIN;           //-- Read the data bit in
    120.   DelayUs(55);            //-- Finish the timeslot
    121.  
    122.  
    123.  
    124.   //-- Put data into the byte
    125.   data = data >> 1;        //-- Shift previous bits across
    126.   if(D_Data==1)            //-- If data was high then add High bit to data
    127.   {
    128.    data +=0x80;
    129.   }
    130.   //-- Delay Between Bits
    131.   DelayUs(D_RiseSpace);             //-- Recovery time between Bits
    132. count--;
    133.  }
    134.  DelayUs(D_RiseSpace);    //-- Rise time + Min Space
    135.  return(data);
    136. }
    137. //******************END OF D_Read
    138.  
    139.  
    140. //**************************************************************************
    141. //D_MatchRom - Matches the ROM Code to device
    142. //**************************************************************************
    143. #ifdef _D_MATCHROM_
    144. void D_MatchRom(unsigned char position)
    145. {
    146.  char count;
    147.  D_Write(0x55);          //-- Match Rom
    148.                          //-- Send the Address ROM Code.
    149.  //for(count=0;count<8;count++)
    150.  count=0;
    151. while(count<8){
    152.   D_Write(gete(position));
    153.   position++;
    154. count++;
    155.  }
    156. }
    157. #endif
    158. //****************** END OF D_SendAddress
    159.  
    160. //**************************************************************************
    161. //D_ReadRom - Reads the ROM Code from a device
    162. //**************************************************************************
    163. #ifdef _D_READROM_
    164. void D_ReadRom(char *address)
    165. {
    166.  char count=0;
    167.  D_Write(0x33);          //-- Read Rom
    168.                          //-- Read in the ROM code from the Device
    169.  //for(count=0;count<8;count++)
    170.  while(count<8){
    171.   address[count]=D_Read();
    172.   address++;
    173. count++;
    174.  }
    175. }
    176. #endif
    177. //****************** END OF D_ReadRom
    178.  
    179. //**************************************************************************
    180. //
    181. //**************************************************************************
    182.  
    183. //****************** END OF
    184.  
    185.  
     
  13. coldpenguin

    Thread Starter Active Member

    Apr 18, 2010
    165
    9
    Thanks, I did try that however the words used, seems more than a little bit of code I just managed:

    128 words
    Code ( (Unknown Language)):
    1.  
    2. if(temp[6]>12) tres--;
    3. ...
    4. switch(temp[6]){
    5. case 0:digits[2]=7;break;
    6. case 1:;
    7. case 2:digits[2]=6;break;
    8. case 3:;
    9. case 4:digits[2]=5;break;
    10. case 5:digits[2]=4;break;
    11. case 6:;
    12. case 7:digits[2]=3;break;
    13. case 8:digits[2]=2;break;
    14. case 9:digits[2]=1;
    15. case 10:digits[2]=1;break;
    16. case 11:;
    17. case 12:digits[2]=0;break;
    18. case 13:digits[2]=9;break;
    19. case 14:;
    20. default:digits[2]=8;break;
    21. }
    116 words
    Code ( (Unknown Language)):
    1.  
    2. if(temp[6]>12) tres--;
    3. digits[2]=10+(10*((12-temp[6])))>>4;
    4. if(digits[2]>9) digits[2]-=10;
    5.  
    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.
    Code ( (Unknown Language)):
    1.  
    2. digits[0]=(tres)/10;
    3. digits[1]=tres-digits[0]*10;
    4.  
     
  14. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    Last edited: May 7, 2012
  15. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    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.
     
  16. bertus

    Administrator

    Apr 5, 2008
    15,648
    2,347
    Markd77 likes this.
  17. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    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.
     
  18. coldpenguin

    Thread Starter Active Member

    Apr 18, 2010
    165
    9
    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.

    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.
     
  19. WBahn

    Moderator

    Mar 31, 2012
    17,748
    4,796
    If you aren't pushed for speed, you could try something real basic, such as:

    Code ( (Unknown Language)):
    1.  
    2. // Convert V (0<=V<100) into two digits, d[1]d[0]
    3. d[1]=0;
    4. d[0] = v;
    5. while (d[0] > 10)
    6. {
    7.     v -= 10;
    8.     d[1]++;
    9. }
    10.  
    That should be pretty easy on code space.
     
  20. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    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.
    Code ( (Unknown Language)):
    1.    
    2. #define _XTAL_FREQ 4000000 //12000000
    3. #include <htc.h>
    4. //#include "../delay.h"
    5. //#include <stdlib.h>
    6. unsigned char gete(unsigned char address);
    7. #define sleep()        asm("sleep")
    8. #define _D_MATCHROM_
    9. #define _D_READROM_
    10. #define D_PIN RA0
    11. #define D_TRIS TRISA0
    12. //#include "1wire.c"
    13. __CONFIG( FOSC_HS & WDTE_OFF);
    14. unsigned char gete(unsigned char address){
    15.    EEADR=address;
    16.    RD=1;
    17.    return(EEDATA);
    18. }
    19. //1wire.c
    20. #define D_RiseSpace 10       // Rise Time + Minimum Space (3uS+1uS absolute min)
    21. #ifndef D_PIN
    22.  #error D_PIN Must Be Defined for 1-wire Bus I/O
    23. #endif
    24. #ifndef D_TRIS
    25.  #error D_TRIS Must be defined for 1-wire Bus I/O
    26. #endif
    27. bit  D_Presence;
    28. bit  D_ShortCircuit;
    29. unsigned char  D_Error;
    30. bit  D_Data;
    31.  
    32. //****************************************************************************
    33. //D_Reset  -- Resets the 1-wire bus and checks for presence & short cct
    34. //****************************************************************************
    35. void D_Reset(void)
    36. {
    37.  char count=20;
    38.  //-- Reset the status bits
    39.  D_Error=0;
    40.  //-- Ensure Correct port pin settings
    41.  D_TRIS=1;
    42.  D_PIN=0;
    43.  //-- Start the reset Pulse
    44.  D_TRIS=0;          //-- Pull Line Low to start reset pulse
    45. while(count>0){count--;
    46.   __delay_us(5);      //-- 480uS Delay
    47.  }
    48.  D_TRIS=1;          //-- Release the line
    49.  __delay_us(60);       //-- Delay to about centre of presence pulse
    50.  D_Presence=D_PIN;  //-- Get Presence status 1=None 0=something there
    51. // for(
    52. count=41;
    53. while(count>0){
    54. //count--) //-- (480-60)uS delay till end
    55.  
    56.   __delay_us(10);
    57. count--;
    58.  }
    59.  D_ShortCircuit=D_PIN;  //-- Check for short circuit on bus pin.
    60.  if(D_ShortCircuit==0)  //-- If short circuit then indicate an error
    61.  {
    62.   D_Error=1;
    63.  }
    64.  if(D_Presence==1)      //-- If no device detected indicate an error
    65.  {
    66.   D_Error+=2;
    67.  }
    68.  __delay_us(D_RiseSpace);    //-- Rise time + Min Space
    69. }
    70. //******************END OF D_Reset
    71.  
    72. //****************************************************************************
    73. // D_Write
    74. //****************************************************************************
    75. void D_Write(Data)
    76. {
    77.  char count=8;
    78. // for(;
    79. while(count>0){
    80. //;count--)
    81.  //{
    82.   D_Data= Data & 0x01;    //-- Get LSB
    83.   //-- Write the bit to the port
    84.   D_PIN=0;
    85.   D_TRIS=0;               //-- Lower the port
    86.   __delay_us(5);             //-- Time slot start time
    87.   D_TRIS=D_Data;          //-- Output the data to the port
    88.   __delay_us(50);            //-- Finish Timeslot
    89.   __delay_us(5);
    90.   D_TRIS=1;               //-- Ensure Release of Port Pin
    91.   //-- Delay Between Bits
    92.   __delay_us(D_RiseSpace);             //-- Recovery time between Bits
    93.   //-- Prep Next Bit
    94.   Data=Data>>1;           //-- Shift next bit into place
    95.   count--;
    96.  }
    97.  __delay_us(D_RiseSpace);    //-- Rise time + Min Space
    98. }
    99. //******************END OF D_Write
    100. //****************************************************************************
    101. // D_Read
    102. //****************************************************************************
    103. char D_Read(void)
    104. {
    105.  char count=8,data=0;
    106.  //for(;
    107. while(count>0){
    108. //count--)
    109.  //{
    110.   //-- Write the bit to the port
    111.   D_PIN=0;
    112.   D_TRIS=0;               //-- Lower the port
    113. //  __delay_us(5);             //-- Time slot start time
    114.   __delay_us(3);             //-- Time slot start time
    115.   D_TRIS=1;               //-- Release port for reading
    116. //  __delay_us(5);             //-- Get close to center of timeslot
    117.   __delay_us(9);             //-- Get close to center of timeslot
    118.   D_Data=D_PIN;           //-- Read the data bit in
    119.   __delay_us(55);            //-- Finish the timeslot
    120.  
    121.   //-- Put data into the byte
    122.   data = data >> 1;        //-- Shift previous bits across
    123.   if(D_Data==1)            //-- If data was high then add High bit to data
    124.   {
    125.    data +=0x80;
    126.   }
    127.   //-- Delay Between Bits
    128.   __delay_us(D_RiseSpace);             //-- Recovery time between Bits
    129. count--;
    130.  }
    131.  __delay_us(D_RiseSpace);    //-- Rise time + Min Space
    132.  return(data);
    133. }
    134. //******************END OF D_Read
    135.  
    136. //**************************************************************************
    137. //D_MatchRom - Matches the ROM Code to device
    138. //**************************************************************************
    139. #ifdef _D_MATCHROM_
    140. void D_MatchRom(unsigned char position)
    141. {
    142.  char count;
    143.  D_Write(0x55);          //-- Match Rom
    144.                          //-- Send the Address ROM Code.
    145.  //for(count=0;count<8;count++)
    146.  count=0;
    147. while(count<8){
    148.   D_Write(gete(position));
    149.   position++;
    150. count++;
    151.  }
    152. }
    153. #endif
    154. //****************** END OF D_SendAddress
    155. //**************************************************************************
    156. //D_ReadRom - Reads the ROM Code from a device
    157. //**************************************************************************
    158. #ifdef _D_READROM_
    159. void D_ReadRom(char *address)
    160. {
    161.  char count=0;
    162.  D_Write(0x33);          //-- Read Rom
    163.                          //-- Read in the ROM code from the Device
    164.  //for(count=0;count<8;count++)
    165.  while(count<8){
    166.   address[count]=D_Read();
    167.   address++;
    168. count++;
    169.  }
    170. }
    171. #endif
    172. //****************** END OF D_ReadRom
    173. //**************************************************************************
    174. //
    175. //**************************************************************************
    176. //****************** END OF
    177. void gettemp(unsigned char sensornum,unsigned char (*digits)){
    178. D_Reset();
    179. //D_Write(0xcc);
    180. D_MatchRom(0x0e+8*sensornum);
    181. D_Write(0xbe);
    182. unsigned char temp[8];
    183. unsigned char r=0;
    184. while(r<8){
    185. temp[r]=D_Read();
    186. r++;
    187. }
    188. unsigned int hres=0;
    189. unsigned int tres=0;
    190. tres =temp[1]<<8;
    191. tres |=temp[0];
    192. if(0x02 !=sensornum){
    193. hres=tres<<4;
    194. }else{
    195. tres >>= 1;
    196. tres <<= 8;
    197. tres -= 0x100>>2;
    198. hres =0x10-temp[6];
    199. hres <<=4;
    200. //hres /=0x10;
    201. //hres >>=4;
    202. hres +=tres;
    203. }
    204. //div_t ty=div(hres,2);
    205. digits[0]=(hres>>8)/10;
    206. digits[1]=(hres>>8)-digits[0]*10;
    207. //hres-=(digits[0]*10)<<8;
    208. //hres-=(digits[1])<<8;
    209. //hres *=10;
    210. digits[2]=hres%256;
    211. //((hres)>>6)&0b00000111;
    212. //int t=10*hres>>8;
    213. }
    214. output(unsigned char * o,unsigned char i){
    215. unsigned char j=0;
    216. while(j<4){
    217. /*unsigned char cnt=0;
    218. switch (j){
    219. case 0: PORTA=gete(0x00);
    220. break;
    221. case 1: PORTA=gete(0x01);
    222. break;
    223. case 2: PORTA=gete(0x02);
    224. break;
    225. default: PORTA=gete(0x03);
    226. }*/
    227. PORTA=gete(j);
    228.         if(i>125 && j==1){
    229.             PORTB=o[j]-0b10000000;
    230.         }else{
    231.             PORTB=o[j];
    232.         }
    233. /*unsigned char cnt=0;
    234. cnt=0;
    235. while(cnt<4){
    236. cnt++;
    237. }*/
    238. #asm
    239. NOP
    240. NOP
    241. NOP
    242. #endasm
    243. //asm("NOP;");
    244. //asm("NOP;");
    245. //asm("NOP;");
    246.         PORTB=0xFF;
    247.         PORTA=0x00;
    248. j++;
    249.     }
    250.  
    251. }
    252.  
    253. void main()    {
    254. unsigned char o[4];  
    255. unsigned char temps[3][3];
    256. o[0]=0;
    257. /*while(o[0]<3){      // this saved 48!
    258. temps[o[0]][0]=0;
    259. temps[o[0]][1]=0;
    260. temps[o[0]][2]=0;
    261. o[0]++;
    262. }
    263. o[0]=0;*/
    264. TRISA=0b00000000;
    265. TRISB=0b00000000;
    266. PORTA=0b00000000;
    267. unsigned char y=0x00;
    268. unsigned char u=0;
    269. unsigned char p=0;
    270. D_Reset();
    271. D_Write(0xcc);
    272. D_Write(0x44);
    273. while(1){
    274. o[3]=0b11111111-(0b00000001<<u);
    275. o[0]=gete(0x04+temps[u][0]);
    276. o[1]=gete(0x04+temps[u][1]);
    277. o[2]=gete(0x04+temps[u][2]);
    278. unsigned char k=0;
    279. while(k<10){
    280.             unsigned char i=0;
    281.             while(i<250){
    282.                 i++;
    283.                 output(o,i);
    284.             }
    285.             k++;
    286.         }
    287.         y++;
    288.         if(y>7){
    289. y=0;
    290. while(y<3){
    291. gettemp(y,temps[y]);
    292. y++;
    293. }
    294. D_Reset();
    295. D_Write(0xcc);
    296. D_Write(0x44);
    297. y=0;
    298. }
    299.         u++;
    300.         if(u>2) u=0;
    301. }
    302. }
    303.  
    304. #asm
    305.      psect eedata, delta=2, abs, ovrld
    306.      ORG 2100H   ; starting point of EEPROM on 16F84
    307. //ports
    308.      DW 0x08,0x04,0x0c,0x00;
    309. //numbers
    310.       dw 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90;
    311.      DW 0x28,0x99, 0xce,0x8d,0x02,0x00,0x00,0xb2 ;
    312.      DW 0x28,0x47, 0xa6,0x8d,0x02,0x00,0x00,0x4a ;
    313.      DW 0x10,0xbc,53H, 0xf5,01H,0x08,00H,0x77 ;
    314. #endasm
    315.  
    316.  
    317. [/u][/u][/u]
     
Loading...