2

Arduino project using the 'Arduino language' (C++ wrapper) -

I have an 8-char array which gives 24Hr clock in the form {'H','H',':','M','M',':','S,'S'} and I need to convert this to BCD. I thought I understood the idea well enough but I get an unexpected result.

As a base example I'd like to convert {'1','2'} to BCD - the theory is on the left and my code result is on the right of the image below. I suspect the issue is with buff[0] being a 'number char', I tried atoi(buff[0]) but this still failed (I had the same result):

How may I do this correctly? My baseline code is:

char buff[8] = {'1','2',':','3','4',':','5','5'};    
uint8_t HourTens  = buff[0] && 0b11110000; // && 0xF0, should be 1
uint8_t HourUnits = buff[1] && 0b00001111; // && 0x0F, should be 2
uint8_t HourBCD   = HourTens + HourUnits;

Serial.println( buff );
Serial.print("'"); Serial.print( buff[0] ); Serial.print( "', HourTens:  " );   Serial.println( HourTens );
Serial.print("'"); Serial.print( buff[1] ); Serial.print( "', HourUnits: " ); Serial.println( HourUnits );
Serial.print( "HourBCD: " ); Serial.println( HourBCD );
Serial.println("***");

enter image description here

herohuyongtao
  • 49,413
  • 29
  • 133
  • 174
Harry Lime
  • 2,167
  • 8
  • 31
  • 53
  • isn't a char 8 bits? Also shouldn't you be using bitwise AND instead of logical AND (& vs &&) – Nick Beeuwsaert Mar 16 '14 at 16:27
  • possible duplicate of [Decimal to BCD conversion](http://stackoverflow.com/questions/1408361/decimal-to-bcd-conversion) – OldProgrammer Mar 16 '14 at 16:27
  • line correction: uint8_t HourBCD = (HourTens<<4) + HourUnits; – Harry Lime Mar 16 '14 at 16:29
  • Hi raser, I just tried & and I got: '1', HourTens: 48 (oh dear) – Harry Lime Mar 16 '14 at 16:31
  • @JakeFrench: looks like you are doing '1' to ascii (decimal 49, binary `0b00110001`) and the and is only saving the first 4 bits (`0b00110001 & 0b11110000 = 0b00110000`), whereas with `&&` you are checking if both `buff`[0] and 0xF0 are not zero (they are both true) hence the 1 – Nick Beeuwsaert Mar 16 '14 at 16:38

1 Answers1

2

The problem with your code is that the data in the buff is ASCII characters, not the individual binary digits. You need to subtract '0' from each digit before performing a conversion to BCD:

uint8_t HourTens  = (buff[0] - '0'); // && 0xF0, will be 1

Note that each element takes its own byte, so you don't need to mask anything.

uint8_t HourBCD = ((buff[0] - '0') << 4) | (buff[1] - '0');

Also note that since the digits are from zero to nine, all you need to do is to shift the upper digit by four to get a valid BCD representation.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • many thanks dasblinkenlight that worked fine - though I don't understand why sub '0' gives individual binary digits, could you explain? cheers – Harry Lime Mar 16 '14 at 16:41
  • @JakeFrench Look at the ASCII codes of digits in the table, they are consecutive. The value of `'0'` works like an "offset" of the range of ASCII digits, so subtracting it gives you the digit's value. – Sergey Kalinichenko Mar 16 '14 at 16:45