HEX/DEC math problem

Status
Not open for further replies.

brodin

New Member
I am using a DS1307 for timekeeping. The device i am constructing is supposed to count the number of hours to a specific date. I have succeded with the communication between the RTC and my PIC16F88.

But i have a problem. The time is stored with HEX representation. The time 13:54 would be 0x13 and 0x54 in the memory of the RTC.

The thing is that i want to figure out the difference in hours. I have two byte variables Hour and xHour. The first is the current hour and xHour is the setup hour to which i am counting down.

BTW i am programming in PicBasic Plus, but i suppose it's just the theory of how to do this that matters.


Example to show my problem:

Hour = 14
xHour = 23

Diff = xHour - Hour

And the result i want is 9. But the result i get is 15 (35 - 20).
I would need to convert the Hour and xHour to decimal representation and then subtract. But how do i do this? Or is there another way of doing this without converting to decimal?
 
If you do a search on BCD arithmetic you should find some useful explanations. **broken link removed**

PICs have got a useful flag for BCD maths - the half carry (or digit carry) bit (DC). When subtracting, the DC bit acts as a borrow and so if it's clear you need to subtract 6 from the result. For your example you would do the following,

Code:
            movlw     23h
            movwf     Acc
            movlw     14h
            movwf     AccHi
            movfw     AccHi
            subwf     Acc,W
            btfss     STATUS,DC
            addlw    100h-6;      add -6 is same as subtracting 6
    ; W will now = 9 (23-14 = 9 not 4 as in your example)

Note that if your result was higher than 10 then it will still be in hex(BCD) format.

HTH

Mike.
 
P.S.
If you want to convert to binary then you need to subtract the high digit * 6

I.E. 23h - 2*6 = 17h = 23d

In Code
Code:
                movlw   23h
                movwf   Acc

                movfw   Acc
                andlw   0f0h;           = high digit (HD) * 16
                bcf     STATUS,C
                movwf   Temp
                rrf     Temp,F;         /2 = HD * 8
                rrf     Temp,F;         /2 = HD * 4
                movfw   Temp;           W = HD * 4
                rrf     Temp,F;         /2 = HD * 2
                addwf   Temp,W;         W = HD*2 + HD*4 = HD*6
                subwf   Acc,W
     ; W now contains the binary equivalent of Acc

HTH

Mike.
 
Whoops, just noticed your using basic. In that case I would just convert everything to binary along the lines of.

Answer = Temp-(Temp >> 4) * 6

Or

Answer = Temp-(Temp/16) * 6

Where Temp is your BCD value.

Mike.
 
Are you sure you're decoding the data properly, because according to this datasheet, it is not hexadecimal or decimal, but a mix of the two. For Minutes bits 0-3 are standard binary (encodes a value from 0 to 16), while bits 4-6 are tens of minutes (bit 7 is always 0). So if I interpret it correctly, the following C code would convert that to a byte you could do standard math on:

Code:
unsigned char ConvertTime(unsigned char cSource) {
  unsigned char cOut=cSource & 0x0f;
  cOut+=10 * (cSource >> 4 );
  return cOut;
}

The same routine could be used to decode seconds, minutes, months and years.

The hour is encoded even stranger, and has to be interpreted differently whether the 24 hour time bit is set or not.

Code:
unsigned char ConvertHour(unsigned char cSource) {
  unsigned char cOut;

  //Test bit 6
  if (cSource & 0x40) {
    //12 hour time
    cOut=ConvertTime(cSource & 0x1f);
    //Test bit 5 (PM)
    if (cSource & 0x20)
      cOut+=12;
    else {
      //Special case for 12 AM
      if (cSource == 12)
        cSource = 0;
    }
    return cOut;
  } else {
    //24 hour time
    return ConvertTime(cSource & 0x3f);
  }
}

That should return the hour in 24 hour time, so you can do standard math against it.

I've never actually worked with one of those chips before, so this is all just based on my interpretation of the datasheet, having just read it for the first time.

Dan East
 
Whoops, just noticed your using basic. In that case I would just convert everything to binary along the lines of.

Answer = Temp-(Temp >> 4) * 6

Or

Answer = Temp-(Temp/16) * 6

Where Temp is your BCD value.

Mike.


Thanks Mike, that worked perfect!
 
brodin said:
The time is stored with HEX representation. The time 13:54 would be 0x13 and 0x54 in the memory of the RTC.

Perhaps I am missing something here. But are you sure of the above?

hexadecimal "13" means "19" in decimal.

Isn't "packed BCD"?

Cuold you please elaborate?
 
Pommie said:
Whoops, just noticed your using basic. In that case I would just convert everything to binary along the lines of.

Answer = Temp-(Temp >> 4) * 6

Or

Answer = Temp-(Temp/16) * 6

Where Temp is your BCD value.

Mike.


And if i want to do it the other way around. From decimal to hexadecimal?
 
Assuming that your basic uses integer maths then

Answer = Temp + (Temp/10)*6

Should work.

Mike.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…