Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Analogue To Digital issues

Status
Not open for further replies.

DarkSilver

Newbie level 4
Joined
Jul 23, 2010
Messages
5
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
Linkoping, Sweden
Activity points
1,322
Hi

I'm currently working on a little macro/subroutine library for PIC microcontrollers, so that I can work more fluently in the future. However, I've run into an issue that I just can't solve.
What I want to do is to read the value from an analogue to digital conversion, use that value to blink LEDs at various speeds(just for testing purposes). The thing is that it keeps blinking at a constant rate, no matter what value my ADC has. I've tried to replace the ADC reading with a normal variable instead and it worked flawlessly. I also know that the ADC works, since I can display it's value on PORTC.
The thing is that I just can't figure out what is wrong, so I can't fix it. :cry:

Here is the Assembly code:
Code:
;**********************************************************************
; Project name: Basics
; Author: Dennis Fredriksson
; Creation date: 2010-07-09
; Project stage: Alpha
;**********************************************************************
; Processor: PIC 16F690
; Pin-assignment:
;		- None
;**********************************************************************
; Comments:
;		None so far
;**********************************************************************

;**********************************************************************
; Compiler setup
;**********************************************************************
    list      p=16F690
    #include <p16F690.inc>

    errorlevel  -302

;**********************************************************************
; Pic configuration
;**********************************************************************
    __CONFIG   _CP_OFF & _CPD_OFF & _BOR_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _FCMEN_OFF & _IESO_OFF 

;**********************************************************************
; Variables
;**********************************************************************
INT_VAR	UDATA_SHR     
vDC1	res	1
vDC2 	res	1
vDC3	res	1
vAdc	res 1
vTest	res	1

;**********************************************************************
; Macros/functions
;**********************************************************************

; RegSet - Sets a specific register bit to 1
;	reg: the destination register
;	bit: the bit to be set to 1 in the destination register
RegSet		MACRO	reg, bit
	banksel	reg
	bsf		reg, bit
	endm

; RegClear - Sets a specific register bit to 0
;	reg: the destination register
;	bit: the bit to be set to 0 in the destination register
RegClear	MACRO	reg, bit
	banksel	reg
	bcf		reg, bit
	endm
; RegEdit - Gives a specific register some data
;	reg: the destination register
; 	dat: the 8-bit data going to the destination register
RegEdit		MACRO	reg, dat
	banksel	reg
	movlw	dat
	movwf	reg
	endm

; RegEditF - ; Gives a specific register some data from another register
; 	regD: the destination register
; 	regO: the origin register, which data is sent to the destination register
RegEditF	MACRO	regD, regO
	banksel	regO
	movfw	regO
	banksel	regD
	movwf	regD
	endm

; DelayMs - Adds a delay for X micro seconds
; 	ms: the amount of micro seconds
DelayMs		MACRO	ms
	movlw	ms
	call 	sDelay10
	endm

; DelayMsF - Adds a delay for X micro seconds, data taken from a register
; 	reg: origin register, in which the amount of micro seconds is stored
DelayMsF		MACRO	reg
	movfw	reg
	call 	sDelay10
	endm

; A2DConv - Preforms an A/D conversion
; 	Requires hardware setup prior to usage(see ADCON0, ADCON1 and ANSEL), PIC specific
A2DConv		MACRO
	call	sAdcCon
	endm

; IfEqual - Do an if A = B check
;	reg: the origin register (A)
;	cmp: the number to compare to (B)
;	sub: the subroutine to call if true
IfEqual		MACRO	reg, cmp, sub
	movfw	reg
	sublw	cmp
	btfsc	STATUS, Z
	call	sub
	nop
	endm

; IfNotEqual - Do an if A != B check
;	reg: the origin register (A)
;	cmp: the number to compare to (B)
;	sub: the subroutine to call if true
IfNotEqual		MACRO	reg, cmp, sub
	movfw	reg
	sublw	cmp
	btfss	STATUS, Z
	call	sub
	nop
	endm

; IfGreater - Do an if A > B check
;	reg: the origin register (A)
;	cmp: the number to compare to (B)
;	sub: the subroutine to call if true
IfGreater	MACRO	reg, cmp, sub
	movfw	reg
	sublw	cmp
	btfss	STATUS, C
	call	sub
	nop
	endm

; IfLesser - Do an if A < B check
;	reg: the origin register (A)
;	cmp: the number to compare to (B)
;	sub: the subroutine to call if true
IfLesser	MACRO	reg, cmp, sub
	movfw	reg
	sublw	cmp
	btfsc	STATUS, C
	call	sub
	nop
	endm

;**********************************************************************
; Main program starts here
;**********************************************************************
	org 0

;**********************************************************************
; Main program setup
;**********************************************************************
Start
	RegEdit		TRISC, 0x00
	RegEdit		TRISA, 0xFF
	RegEdit		ADCON1,	0x10
	RegEdit		ANSEL, 0xFF
	RegEdit		ADCON0,	0x01
	RegEdit		vTest, .10

;**********************************************************************
; Main loop
;**********************************************************************
MainLoop
	A2DConv

	RegEdit		PORTC, 0xFF
	DelayMsF	vAdc
	RegEdit		PORTC, 0x00
	DelayMsF	vAdc

	goto    MainLoop

;**********************************************************************
; Subroutines
;**********************************************************************
sDelay10 ; Adds a delay that lasts X times 10 milliseconds
	movwf	vDC3
sDelay2
	movlw	.13
	movwf	vDC2
	clrf	vDC1
sDelay1
	decfsz	vDC1, f
	goto	sDelay1
	decfsz	vDC2, f
	goto	sDelay1
	decfsz	vDC3, f
	goto	sDelay2

	return

sAdcCon ; The A/D conversion subroutine
	nop
	nop
	nop
	nop
	nop
	bsf		ADCON0, GO
	btfss	ADCON0, GO
	goto $-1
	banksel	ADRESH
	swapf	ADRESH, w
	movwf	vAdc

	return

;**********************************************************************
; End directive
;**********************************************************************
	end

I use the PicKit 2 as programmer and I use the low pin board that comes with it as a testing platform.

Any help is gladly accepted.

Regards, DarkSilver
 

your code stores the adc results in vAdc and then flips portc based on the value of vAdc.

I would try a few things:

1) in the main loop, right after you did the adc, assign a hard value to vAdc, like "RegEdit vAdc, 200" and see if you can observe blinking on portc. and also vary the value assigned to vAdc (200 in this case) to see if you get variable blinking speed.

2) if you don't, focus on the delay routines, mcu initialization, fuse settings, or hardware.

3) if you do, focus on the adc routines.

good luck.
 

1) I've already tried that and it works like a charm. There is nothing wrong with the delay routines or the MCU settings.
3) I guess that there is something wrong with the value being returned from the ADC, but I'm not sure what is wrong with it.

But thanks for your help :)
 

check the adc settings against the datasheet to make sure that they are correct.
 

I checked my settings with the pic16f690 datasheet and it was all correct. I did some testing and placed the ADC macro outside of the main loop. It partially worked, it would allow me to change the blink rate(on/off via the PicKit 2 Programmer), but at the same time, it seemed a little bit random. Sometimes it would stick with the same blink rate, even if I changed it's value and only after a few tries would it change.
Any ideas?
 

it seemed a little bit random

that sounds like you didn't wait long enough for tacq.

RegEdit ADCON1, 0x10

check with the datasheet to see if you can indeed take the speed.

RegEdit ANSEL, 0xFF
RegEdit ADCON0, 0x01

the ansel setting and adcon0 settings are incompatible.

nop
nop
nop
nop
nop

this may not be sufficient timingwise.

Added after 1 minutes:

what I typically do in c is to have two routines, adc_init() initialize the adc, and adc_read(unsigned char ch) would select the channel specified by ch and return the adc results.

it is fairly straight forward. assembly shouldn't be much different.
 

    DarkSilver

    Points: 2
    Helpful Answer Positive Rating
I'm telling you, there is nothing wrong with the readings. I can prefectly fine send the result from the ADC to PORTC and see how it does a good reading after another. Despite that, I cannot use the returned value to cause a delay.

I've tried all settings for the ADCON1, without any visible improvments.

Why would the ANSEL and ADCON0 settings be incompatible?

:| This is driving me nuts
 

OK. there is nothing wrong with the readings.
 

    DarkSilver

    Points: 2
    Helpful Answer Positive Rating
Yay! Thanks a lot millwood, I finally got it working. Will comparing my code with the examples that came with PicKit2, I noticed a difference between their A2D example and the VSRotate example. They apparently work on a different basis.
So by replacing
Code:
sAdcCon ; The A/D conversion subroutine
	nop
	nop
	nop
	nop
	nop
	bsf		ADCON0, GO
	btfss	ADCON0, GO
	goto 	$-1
	banksel	ADRESH
	swapf     ADRESH, w
	addlw	.1
	movwf	vAdc

	return
with
Code:
sAdcCon ; The A/D conversion subroutine
	nop
	nop
	nop
	nop
	nop
	bsf		ADCON0, GO
	btfss	ADCON0, GO
	goto 	$-1
	banksel	ADRESH
	movf     ADRESH, w
	addlw	.1
	movwf	vAdc

	return
it worked :) I'll take on your idea of having a seperate reading subroutine
Sorry for being a bit harsh, but it got the better of me :oops:
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top