11 years, 5 months ago.

Convert a Hex value variable to a Decimal value variable

I'm stuck (again!), can anybody help me to convert a hex value to a decimal value?

set[0]=0x00; 100'

set[1]=0x00; 10'

set[2]=0x00; sec

set[3]=0x20; min

set[4]=0x18; hr

set[5]=0x06; day

set[6]=0x24; date

set[7]=0x11; month

set[8]=0x12; year

i2c.write(0xD0,set,9); Set rtc registers

The above part code will set my i2c RTC clock chip to the correct time manualy specifying the 0x00 values to the relavent time registers. However if I then use the "set" function further in my program using data from some code I use for the DCF77 atomic clock I find that it appears to store a Hex value instead.

For example;

set[2]=(lcd_sec);

i2c.write(0xD0,set,9);

If I read this back out from the rtc to the display I have wrong values when the seconds go past 15

For instance if the lcd_sec counts to 18 the seconds are then read back from the RTC chip as 12, 16 gives me 10, 17 gives me 11 and so on.

Is ther a simple way to convert 'lcd_sec' to the correct decimal values?

Many thanks

Paul

5 Answers

11 years, 5 months ago.

There are a couple of comments:

set[0]=0x00; //100'   => this is actually the address for the first RTC register that you write to
set[1]=0x00; //10'    => this is actually the value for register 0, it contains 100' and 10'
set[2]=0x00; //sec    => this is actually the value for register 1, it contains sec
set[3]=0x20; //min    => this is actually the value for register 2, it contains min
set[4]=0x18; //hr
set[5]=0x06; //day
set[6]=0x24; //date
set[7]=0x11; //month
set[8]=0x12; //year
i2c.write(0xD0,set,9); //Send address of first register (0) and then send 8 rtc registers values

Second comment:

float echo3 = (10 * (cmd[2] >> 4)) + (cmd[2] & 15);  

Doesnt make much sense to convert the time to float. The time data is always an integer. I assume you have read back 8 registers (0 thru 7) from the RTC and cmd[0] is holding the value from register[0]. So cmd[2] contains minutes?

The real problem may be that your lcd_sec count from the DCF source is counting as an integer. You probably print that to check the value using something like:

printf("DCF sec is %d\n\r", lcd_sec);

So it looks fine, perhaps indicating 'DCF sec is 18'. The binary value will then be 0x12. When you use that to set the clock it will be interpreted as '12' in BCD. When you read back that value from the clock and print it using your above conversioncode it will show as '12'.

You need to convert your binary counter lcd_sec into BCD before using it to set the clock. Something like

bcdval = ((lcd_sec/10) << 4) + (lcd_sec % 10);

Not most optimal code, but should work.

Accepted Answer
11 years, 5 months ago.

What type is lcd_sec? Since you write it with the i2c it must be just a char, but a char cannot be decimal/hexadecimal, it is just a value. What does that DFC code return for 15? If it is 'F', it must return a string.

11 years, 5 months ago.

DCF transmits time in binary coded decimal (BCD) format. So 10 decimal will be sent as 0x10 (rather than as 0x0A). This makes it easier to show time on a display. The RTC values may be in regular hex format. You need to find out which formats are used and convert between them. Note that some RTCs can also support BCD output.

Conversion is relatively easy by separating the upper and lower 4 bits of the BCD value and doing some calculations:

Hexval = ((bcdval>>4) * 10) + (bcdval & 0x0f);

Paul Staron
poster
11 years, 5 months ago.

Thank you for your answers.

Can I explain a little further.

The RTC chip uses a BCD output that I have code ( float echo3 = (10 * (cmd[2] >> 4)) + (cmd[2] & 15); )to convert each register and then display using printf command.

lcd-sec is a variable or value incremented by the DCF77 seconds pulse and displays the correct number when printing this to the display using the printf command.

After the program has correctly obtained the correct time, I write this back to the RTC clock chip registers to set it. I then read the RTC clock data out and thats when I find the RTC chip stored values printed on the display are incorrect.

Manualy setting the RTC chip registers using the code in my question above, I get the correct time data stored.

I'm not sure what "set[3]=0x20;" is doing.

I assume its a storing a decimal value 20 in the set[3] variable and not 32 if it were Hex.

However if I write that to the RTC chip "minutes" register, read it back and display it using printf command I get "20" which is what I want and not 32.

The RTC chip is a type M41T81

I'm sure its a simple solution for you guys.

Many thanks

Paul

Paul Staron
poster
11 years, 5 months ago.

That works just fine Wim, many thanks.

I used float because I lifted some code from another program off Mbed that worked, I will have to tidy that bit up.

Kind regards

Paul