Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Trying to convert binary to ascii

Status
Not open for further replies.

ChriX

Member
I posted a long time ago about the DS1820 sensors, I could never get the timing right so gave up on them. I managed to get the things to respond this time around though, and have been firing the byte that comes from the DS1820 into the serial port of my pc so I can see it on hyperterminal.

A problem has arisen when trying to convert the byte given by the sensor into ascii characters to send back to the PC. For now I have been rotating right to cut off the bit that represents .5 for simplicity, but I still can't get my head around how to do it. I've been trying to convert to BCD, then adding 30h to each nibble to convert the ascii character. I can find loads of code, but nothing that actually explains how to do it, I find reading other people's assembly really hard for some reason (unless commented well).

I'll try and explain the way I have been doing it. I've got a loop with a count (starting at 8 ), and bit 0 is tested. If it is set, subroutines are called with data tables that contain the amount of ones and the amount of tens for the value of that bit. I.e. 1 in the tens table and 6 in the ones table for bit 4, then I use the wcount value to jump to the appropriate position in the table, and add up all the ones and all the tens in the byte.

Code:
ADDONES
  movf WCOUNT,W
  addwf PCL,F
  dt 8,4,2,6,8,4,2,1		; amount of ones for each bit value (backwards)
							; 1,2,4,8,16,32,64,128

ADDTENS
  movf WCOUNT,W
  addwf PCL,F
  dt 2,6,3,1,0,0,0,0		; amount of tens for each bit value (backwards)

BTOBCD
  movlw 0x08				
  movwf WCOUNT				; Move 8 into wcount to limit the amount of times we go round
  movlw 0x00
BTOBCDL
  btfsc BCDTEMP,0			; Test bit in BCDTEMP
	call ADDONES			; if it is set, go to the addones thing and get the amount of ones
  addwf BCDONES,F			; add the returned table value to the bcdones reg
  movlw 0x00
  btfsc BCDTEMP,0			; do the same for the tens
	call ADDTENS
  addwf BCDTENS,F
  movlw 0x00
  rrf BCDTEMP,1				; rotate bcdtemp right one, chop off the bit we've done
  decfsz WCOUNT,1			; decrement wcount, so that a different table value is returned
	goto BTOBCDL			; if not 0 all bits not done so go back

  movf BCDONES,W
  movwf TEMP
  movlw 0x0A				; subtract 10 from bcdones, if it goes negative don't increment
  subwf BCDONES,F
  btfss STATUS,C
	incf BCDTENS
  btfss STATUS,C			;
    clrf BCDONES

  movlw 0x30				; add 30h to each register to turn it into ascii
  addwf BCDONES,F
  movlw 0x30
  addwf BCDTENS,F

  return

The routine BTOBCD should be called with the byte you want to change in BCDTEMP. The routine is incomplete because I can't get it to respond how I want even removing all the subtract ten from the ones and add to the tens section. If I put the binary for one in BCDTEMP, the sub returns with the ascii for 0 and 7 the first time it's called, then 0 and 8 the second time.

Hope I have provided enough info for some help, as I am really running out of ideas! If my idea of doing it is complete and utter rubbish let me know!

Thanks. :)
 
You've not made yourself very clear?.

I'm not sure what you actually want to send to the PC?.

Are you wanting to send decimal values?, in which case why mention binary at all?. Or do you want to send binary?.

Obviously in either case you need to send it as a series of ASCII characters that will display on the PC under Hyperterminal (or similar).

So assuming it's an eight bit value, and as high as possible, do you want to send it as:

Decimal: '255'

Binary: '11111111'

Hexadecimal: 'FF'

There are routines in my tutorials for both decimal and hex, and binary is very trivial to do.
 
I mean that I want to send the ascii characters that represent the binary value, i.e. 2 and 1 for 00010101. I can send a string of 1s and 0s fine, just can't convert.

Say I get 00010001 from the temperature sensor, I want to send this to the pc as the ascii characters 1 and 7, and i'm having a hard time getting to ascii characters from the binary value.
 
I've seen this happen a few times; people get confused between the number systems and how it all works.

Okay, so you're reading a value from your sensor and you want to see that value in Hyperterminal, right?

Some things that you need to understand first...

Terminal programs only deal with one byte at a time. And the data sent/received is in binary. If you send the value 48 to Hyperterminal you don't get to see "48" on the screen, because terminal programs convert the binary numbers to ASCII and the value 48 in ASCII is the character "0". To see the value "48" on the screen you have to send two separate bytes: 52 and 56. (ASCII codes are here: www.asciitable.com)

So first ask yourself how the value is coming from the sensor. Is it a single byte having the range 0-255? Or is it a multiple byte value where each byte contains a decimal place? Let's work through each case. Your situation may be neither of these, but this will give you an idea how things work.

If the value coming from the sensor is a single binary value in the range 0-255 and you want to see this exact number in Hyperterminal then you need to do some conversion. You want to break apart the value into three separate values (one for each digit), convert that to its ASCII character, and send it.

So if the sensor value is 48 then you want to divide this by 100 (ignoring any remainder) and you have your first digit (in this case, 0). Multiply this number by 100 and subtract from the original number, then divide by 10 and you have the second digit. Multiply this by 10 and subtract from the previous iteration and you have the final digit. It'll look like this:

value = 48
firstdigit = value / 100
value = value - firstdigit*100
seconddigit = value / 10
value = value - seconddigit*10
thirddigit = value

You now have:
firstdigit = 0
seconddigit = 4
thirdigit = 8

But if you send these to Hyperterminal you will only see the ASCII characters of those values. Since zero is ASCII 48 you just add 48 to each digit and then send them.

The second case - reading each decimal digit from the sensor - is even easier and you'll already know by the first example how to do it.

Mike
 
I'm competent with the number systems and how it works, I can make whatever I want appear how I want it on hyperterminal, the only problem i'm having is converting the data from the sensor to something that I want.

If the value coming from the sensor is a single binary value in the range 0-255 and you want to see this exact number in Hyperterminal then you need to do some conversion. You want to break apart the value into three separate values (one for each digit), convert that to its ASCII character, and send it.

That is exactly what i'm trying to do and having problems with! I think your explanation on how to do it will have helped though so I am going to get that going now (or at least try).

Thanks very much for your help!
 
ChriX said:
I mean that I want to send the ascii characters that represent the binary value, i.e. 2 and 1 for 00010101. I can send a string of 1s and 0s fine, just can't convert.

Say I get 00010001 from the temperature sensor, I want to send this to the pc as the ascii characters 1 and 7, and i'm having a hard time getting to ascii characters from the binary value.

So you receive 00010001 from your sensor and shift it into 1 byte (register) so that it contains the value 17 in binary (11 in Hex). You want to send a "1" followed by a "7" to the PC so that hyperterminal displays 17.

The following should achieve that.

Code:
WriteDecimal  clrf	Decimal10
Count10s		incf	Decimal10,F
				  addlw	0f6h;		-10
				  btfsc	STATUS,C
				  goto	Count10s
				  movwf	Units
				  movfw	Decimal10
				  addlw	2fh
				  call	SendByte
				  movfw	Units
				  addlw	30h+0ah		
SendByte

THe above will send the value that is in the W register on entry.

Note that the code calls sendbyte to send the 10s part and then "follows through" to send the units part. Therefore your send to PC routine should start where the SendByte label is.

HTH

Mike.
 
Iy you need the hundreds bit as well, then

Code:
WriteDecimal    clrf	Decimal100
Count100s       incf	Decimal100,F
                addlw	100h-100;	-100
                btfsc	STATUS,C
                goto	Count100s
                addlw	100
                clrf	Decimal10
Count10s        incf	Decimal10,F
                addlw	0f6h;		-10
                btfsc	STATUS,C
                goto	Count10s
                movwf	Units
                movfw	Decimal100
                addlw	2fh
                call	SendByte
                movfw	Decimal10
                addlw	2fh
                call	SendByte
                movfw	Units
                addlw	30h+0ah
SendByte

Mike.
 
ChriX said:
I mean that I want to send the ascii characters that represent the binary value, i.e. 2 and 1 for 00010101. I can send a string of 1s and 0s fine, just can't convert.

Say I get 00010001 from the temperature sensor, I want to send this to the pc as the ascii characters 1 and 7, and i'm having a hard time getting to ascii characters from the binary value.

I must admit, this totally confused me again!, you don't explain it well!.

But having read the follow up posts, it's clear you want to display the DECIMAL value of the number.

There are plenty of routines you can use to do this, my tutorials include the one that I use - it's a 16 bit routine, but you can just zero the upper byte. Calling the routine converts the original binary/hexadecimal number into seperate decimal digits in five GPR's, ones, tens, hundreds etc. You would only need to use the values in the bottom three, then simply convert then to ASCII and send them out the serial port.

Check my analogue tutorials and serial tutorials (and for that matter LCD tutorials) all of which do almost exactly what you need.
 
Pommie:

That little code snippet works perfectly, thanks very much! No idea why I didn't think of doing it like that. It's like what I had written but a much simpler version.

Thanks again for everyones help.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top