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.

pic16f877 AD conversion

Status
Not open for further replies.

quentennis

New Member
Hi all

I'm currently trying to do a ADC with my pic16f877A microcontroller. But when i'm programming and testing it, i always get the same value. So I read several times the datasheet, and I figured out maybe i've forgotten sth on my board.

On the datasheet, it is said : "The maximum recommended impedance for analog sources is 2.5 kΩ." But i don't really understand what this sentence means. Do I have to add a resistance between my analog signal and my AD pin ? Or am I wrong ?

Thank you for your help
 
The thing that normally stumps people when they first use the ADC on a pic is the acquisition delay. After you select the channel number and turn on the ADC, you need a small delay to allow the holding capacitor to charge.

If you post your code we can probably spot your problem.

Mike.
 
Here is my code.

ADCON1VAL EQU B'00000000' ; PORTA in digital mode
BANK1 ; select BANK1
movlw ADCON1VAL ; load ADCON1VAL in w register
movwf ADCON1 ; load ADCON1VAL in ADCON1 register
BANK0 ; select BANK0

ADCON0VAL1 EQU B'10000001' ; ADC on RA0
movlw ADCON0VAL1 ; load ADCON0VAL1 in w reg
movwf ADCON0 ; load ADCON0VAL1 in ADCON0
TEMP25 ; 25 µs temporisation
bsf ADCON0,GO ; start digital conversion
waitconv1
btfsc ADCON0,GO ; conversion done ?
goto waitconv1 ; no, wait until it's done
movlw ADRESH ; load conversion in w
movwf conv1 ; save conversion value in conv1


movf conv1,w ; load conversion in w reg
movwf TXREG ; send to PC via RS232

rien
nop
nop
nop
goto rien



and here is my macro for the 25µs temporisation (i use a 20MHz quartz) :

TEMP25 macro
LOCAL attend
movlw 41
movwf cpt

attend
decfsz cpt, f
goto attend
nop
nop

endm
 
Last edited:
Code:
ADCON0VAL1 equ	B'10000001'	; ADC on RA0
	movlw	ADCON0VAL1	; load ADCON0VAL1 in w reg
	movwf	ADCON0		; load ADCON0VAL1 in ADCON0 
TEMP25				; 25 µs temporisation 
	bsf	ADCON0,GO	; start digital conversion
waitconv1 
	btfsc	ADCON0,GO	; conversion done ? 
	goto	waitconv1	; no, wait until it's done
	movlw	ADRESH		; load conversion in w 
	movwf	conv1		; save conversion value in conv1


	movf	conv1,w		; load conversion in w reg
	movwf	TXREG		; send to PC via RS232

rien
	nop
	nop
	nop
	goto	rien



and	here	is my macro for the 25µs temporisation (i use a 20MHz quartz) : 

TEMP25	macro
	local	attend
	movlw	41 
	movwf	cpt

attend
	decfsz	cpt, f
	goto	attend
	nop
	nop

	endm

Used Mikes tidy.!:)
 
OOps... Sorry for not adding wraps for my code !! Thanks ericgibbs.
To Pommie : I've edited my code few minutes ago because you're right, i had forgotten to mention ADCON1 register !
 
Your code looks correct. Have you set A0 to input? What is your analogue source?

Can you set a breakpoint after the conversion to ensure it is not the RS232 that is messing up.

Mike.
 
I already went to your tutorials Nigel, actually, you made a good job, it's much better than the datasheet.
I've tried to debug my code, by setting breakpoints as advised by Pommie, and thanks to that, i've found my mistake !
Instead of doing
Code:
movf ADRESH,w
i did
Code:
movlw ADRESH
The result of my conversion was good, but when I tried to retrieve the value in my variable conv1, i didn't get the right result, as i didn't use the right instruction !
Now I think it's gonna work well !

Thanks all =)
 
I already went to your tutorials Nigel, actually, you made a good job, it's much better than the datasheet.
I've tried to debug my code, by setting breakpoints as advised by Pommie, and thanks to that, i've found my mistake !
Instead of doing
Code:
movf ADRESH,w
i did
Code:
movlw ADRESH
The result of my conversion was good, but when I tried to retrieve the value in my variable conv1, i didn't get the right result, as i didn't use the right instruction !
Now I think it's gonna work well !

Thanks all =)

No wonder you got the same resule all the time! :p
 
I already went to your tutorials Nigel, actually, you made a good job, it's much better than the datasheet.
I've tried to debug my code, by setting breakpoints as advised by Pommie, and thanks to that, i've found my mistake !
Instead of doing
Code:
movf ADRESH,w
i did
Code:
movlw ADRESH
The result of my conversion was good, but when I tried to retrieve the value in my variable conv1, i didn't get the right result, as i didn't use the right instruction !
Now I think it's gonna work well !

Thanks all =)

Yes, I think you found your error. Lol. It's surprising how often that is the error and no one spots it, everyone is always looking for more complex reasons.

Mike.
 
And now, i've got another problem with this ADC !! Really weird...
I know I get the right result to my ADC because when i connect pin RA0 to vcc in debug mode, ADRESH is '11111111', and when i connect it to vss, ADRESH is '00000000'. Then, I try to send this value to a computer, using USART. Then I send the value to TXREG, and when I connect hyperterminal to see what's happening, I get a weird character, which is absolutely not what I was expecting ( actually '11111111'). And I know USART is well configured, because everytime I reset the pic, I get a 'A' character with hyperterminal.

Does someone have a clue ?

Thanks all
 
I thought you'd read my tutorials? - try again, and check the A2D one that does just what you're trying to do - you need to convert what you send to ASCII, and probably to decimal first as well, plus CR/LF.
 
If you send binary then you will get strange results. You should convert the binary into characters that hyperterminal can display. I normally convert to hex and send that. My routine to do this is,

Code:
SendHex		movwf	HexTemp
		swapf	HexTemp,W
		call	WriteLoNibble
		movfw	HexTemp
WriteLoNibble	andlw	0fh
		addlw	.256-.10 ; 	if a-f then carry set
		btfsc	STATUS,C
		addlw	7
		addlw	"0"+.10
		goto	SendByte

SendByte should check the interrupt flag to ensure the previous byte has been sent.

Mike.
 
I thought you'd read my tutorials? - try again, and check the A2D one that does just what you're trying to do - you need to convert what you send to ASCII, and probably to decimal first as well, plus CR/LF.

Maybe i've missed this part... I'm gonna have a look right now. =) What do you mean by CR/LF ?

@ Pommie : could you please explain a bit your code ? That would be nice, as i'm just a beginner in assembler. Thanks
 
Maybe i've missed this part... I'm gonna have a look right now. =) What do you mean by CR/LF ?

hi,
At the end of a 'text' string, sent via the RS232 it sometimes requires that you append CRLF [ carriage return , Line Feed] codes.

EG: string 0x0D 0x0A which is CR [0x0D] and the LF [0x0A]

The receiver then knows its the end of the text and will display the text.
 
Last edited:
If you send binary then you will get strange results. You should convert the binary into characters that hyperterminal can display. I normally convert to hex and send that. My routine to do this is,

Code:
SendHex		movwf	HexTemp
		swapf	HexTemp,W
		call	WriteLoNibble
		movfw	HexTemp
WriteLoNibble	andlw	0fh
		addlw	.256-.10 ; 	if a-f then carry set
		btfsc	STATUS,C
		addlw	7
		addlw	"0"+.10
		goto	SendByte

SendByte should check the interrupt flag to ensure the previous byte has been sent.

Mike.

I don't really understand why i have to check the interrupt flag. Is it in order to avoid loosing data ? And in your program, you call a subroutine, but there's no 'return' at the end !
 
I don't really understand why i have to check the interrupt flag. Is it in order to avoid loosing data ? And in your program, you call a subroutine, but there's no 'return' at the end !

hi,
Just in case Mike is tied up.

You check the intrf so that you dont overwrite the character in the transmit buffer, before its sent.

The RETURN will be at the end of the 'SendByte' transmit subr.
 
Last edited:
The code above convert a binary number into the ascii equivalent hexadecimal number.

For example, if the ADC routine returned 0x07 and you sent this to hyperterminal then your PC would beep. This is because code 7 is the beep character. The above routine converts the 7 into two new codes, 0x30 and 0x37 which are the codes for characters "0" and "7" and so hyperterminal displays "07". If the ADC returned 11100110 (0xe6) then hyperteminal would display "E6". If you prefer it in decimal then Nigel has routines on his site.

Mike.
Edit, just realised I missed the second page of posts, doh.
 
Last edited:
Ok, thanks for your comments Pommie. But I've got a question : Do your code first convert the 4 MSB or 4 LSB ? Because it would be easier to begin with the first MSB, so that to send the converted value to RS232

Thanks
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top