![]() | ![]() | ![]() |
| | |||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
| | LinkBack | Thread Tools | Display Modes |
| | (permalink) |
| Hi, I'm pretty new to this lark. I'm tryin to do a simple adc on a 12F675 and then built on the program from there. The Circuit: 5V (5.5V MAX) regulator connected to Vdd & Vss 5V LED connected over Vdd & Vss 0.1 microfarad decoupling cap over the Vdd & Vss pins GP0/AN0 connected to a 500K Potentiometer (Also connected to Vss and Vdd) GP1 connected to 5V LED (red) GP2 connected to 5V LED (green) 10bit adc so 0V = 0 & 5.5V = 1023 Very simple! I am writing in assembly using MPLAB IDE, I went through my program and narrowed the problem down to the adc results. I setup a little test to blink out the results held in each bit of the ADRESL and ADRESH files When ADCON0,ADFM is set (results right justified) my test revealed bits 2-7 of ADRESH are always clear (as expected) so you would expect that bits 0 & 1 of ADRESH and bits 0-7 of ADRESL would contain the results Instead I got the following: V@AN0 ARESH ADRESL DEC RESULT EXPECTED DEC RESULT 0.0V 00000000 00000000 0 0 0.5V 00000000 00000000 0 93 1.0V 00000000 00000000 0 186 1.5V 00000001 00000001 257 279 2.0V 00000001 00000001 257 372 2.5V 00000001 00000001 257 465 3.0V 00000010 00000010 514 558 3.5V 00000010 00000010 514 651 4.0V 00000010 00000010 514 744 4.5V 00000011 00000011 771 837 5.0V 00000011 00000011 771 930 5.5V 00000011 00000011 771 1023 It seem odd that ARESH is the same as ADRESL, also the relusts aren't waht I expected, can anyone make any sense of these results? So next I changed to ADCON0,ADFM clear (results left justified) my test revealed bits 0-5 of ADRESL aren't always clear as you would expect (Note that on the data sheet P42 it says for ADFM=0 bits 0-5 of ADRESL read as 0) My results are below: V@AN0 ARESH ADRESL DEC RESULT EXPECTED DEC RESULT 0.0V 00000100 00000100 1028 0 0.5V 00011100 00011100 7196 93 1.0V 00110000 00110000 12336 186 1.5V 01001000 01001000 18504 279 2.0V 01011100 01011100 23644 372 2.5V 01111100 01111100 31868 465 3.0V 10001100 10001100 35980 558 3.5V 10100110 10100110 42662 651 4.0V 10111001 10111001 47545 744 4.5V 11001100 11001100 52428 837 5.0V 11100100 11100100 58596 930 5.5V 11110001 11110001 61937 1023 Again ARESH is the same as ADRESL, is this correct? shouldn't bits 0-5 of ADRESL always be 0? If only bits 0-7 of ADRESH and bits 6 & 7 of ADRESL are used the following decimal equivalents are obtained: V@AN0 ARESH ADRESL DEC RESULT EXPECTED DEC RESULT 0.0V 00000100 00 16 0 0.5V 00011100 00 112 93 1.0V 00110000 00 192 186 1.5V 01001000 01 289 279 2.0V 01011100 01 369 372 2.5V 01111100 01 497 465 3.0V 10001100 10 562 558 3.5V 10100110 10 666 651 4.0V 10111001 10 742 744 4.5V 11001100 11 819 837 5.0V 11100100 11 915 930 5.5V 11110001 11 967 1023 This would apper to be correct! but to summarise: What is happening with the results for ADFM = 1 incorrect Why are the results of ADRESH and ADRESL the same for ADFM = 1 of 0 Why aren't the bits 0-5 of ADRESL 0 when ADFM = 0 Hope someone can shed some light as I'm tearing my hair out! Cheers | |
| |
| | (permalink) |
| I wonder if you're experiencing banking problems? Are you switching banks correctly between ADRESL and ADRESH? It's a "gotcha" that seems to catch everyone at one time or another... | |
| |
| | (permalink) | |
| Quote:
Sorry On the more serious side, a 500K pot is MUCH, MUCH too high a value - try 5K or 10K instead. | ||
| |
| | (permalink) |
| 500k is quite high, try 5k | |
| |
| | (permalink) |
| Thanks for the fast replies! I should have posted ages ago in stead on banging my head on the wall Ok Thanks for pointing that out mike, I hadn't even thought of changing banks..... (as I said beginner to this) I pressume dropping the pot value is to increase the input current? does this then have an effect on the accuracy? I will give it bash and let you guys know what happens. The girlfriend is on her way over so my 'fun' time is limited haha | |
| |
| | (permalink) | ||
| Quote:
Quote:
| |||
| |
| | (permalink) |
| Ok, a tad harsh, she is fun I've just started lookin at my program again.....paying attention to bank locations Maybe a stupid question at the end but here goes..... Below is an extract from the start of my program: ; EQUATES SECTION TMR0 EQU 01H ; TMR0 is file 1. TRISIO EQU 85H ; TRISIO, the PORTA I/O selection is file 85H GPIO EQU 05H ; GENERAL I/O PORT is file 5. STATUS EQU 03H ; STATUS is file 3. ZEROBIT EQU 2 ; ZEROBIT is bit 2 of STATUS CARRY EQU 0 ; CARRY is bit 0 of STATUS ANSEL EQU 9FH ; ANALOGUE SELECT REGISTER is file 9EH ADCON0 EQU 1FH ; A/D CONTROL RESISTER is file 1FH GO EQU 1 ; GO/DONE is bit 1 of ADCON0 ADRESH EQU 1EH ; The A/D RESULT upper ADRESL EQU 9EH ; The A/D RESULT lower OPTION_R EQU 81H ; OPTION register is file 81H CMCON EQU 19H ; COMPARATOR CONTROL REGISTER is file 19H OSCAL EQU 90H ; OSCILLATOR CALIBRATION REGISTER is file 90H COUNT EQU 20H ; User RAM location. Here the STAUS REGISTER is only refered to the bank0 location of 03H and not the BANK1 location of 83H (Can you see where I'm going here Below is an extract from the setup part of my program: ;CONFIGURATION SECTION START BSF STATUS,5 ;Turns to Bank1 MOVLW B'00111001' ;GP 1 & 2 set as OP all others IP MOVWF TRISIO MOVLW B'00010001' CLRF ANSEL ;A/D Clock FOSC/8, (GP0) Set as analogue MOVLW B'00000111' ;Prescaler is /256 MOVWF OPTION_R ;TIMER pulses every 1/3906.25 secs CALL 3FFH MOVWF OSCAL ;Calibrates 4MHz oscillator BCF STATUS,5 ;Turn to Bank0 MOVLW B'00000111' MOVWF CMCON ;Turns off comparator MOVLW B'00000001' MOVWF ADCON0 ;left justified, Ref Vdd, AN0, ADC on CLRF GPIO ;Clears GP Here when I select BANK1 I use 'BSF STATUS,5' (which I linked to file 03H) which is fine as the data sheet says bit 5 is clear on POR/BOD, therefore initially I am in BANK0. Now going by what was said about ensuring files I call up are in the bank I'm working in........ Surely to change back to BANK0 when in BANK1 I would need to clear bit 5 of the STATUS REGISTER......but 03H is no longer the STATUS REGISTER, it is now 83H..... Does the extract from my program work? It's the same method I have used before when messing about with simple digital Input/output programs and they have all worked fine. Does it not matter what address I use to call up the STATUS REGISTER regardless of which bank I am in. If so am I correct in saying this doesn't apply to any of the other addresses, ie ADRESH & ADRESL? Cheers! | |
| |
| | (permalink) |
| Get rid of the equates section and use Code: #include <p12F675.inc> Some registers like STATUS are in all banks. Also try STATUS, RP0 (it makes it easier to read) Can you zip and attach the entire program? Last edited by blueroomelectronics; 25th November 2007 at 04:51 PM. | |
| |
| | (permalink) |
| Thanks, I'll just tidy it up and stick it on.....there isn't much to it though.... I understand from P8 of the datasheet that STATUS is in both banks but my point was it has a different address depending on which bank I am in. So the way I understand it..... if i'm in BANK0 is use address 03H if I'm in BANK1 I use address 83H Calling up 03H in BANK1...... 03H isn't STATUS in BANK1.... am I barking up the wrong tree here? you say to use 'STATUS,RP0' is this because 'STATUS,5' is ambigous to 'people' reading the program? Also you say get rid of the equates section, I had this so I could use the name tags assigned to files ie 'BSF STATUS,RP0' instead of 'BSF 03H,5' You say to insert: #include <p12F675.inc> Do I just put this as a line of code exactly as it is above, what does it do and can I still use commands like 'BSF STATUS,RP0'? Thanks guys you're legends! | |
| |
| | (permalink) | ||
| Quote:
Quote:
If you don't use the equate labels (like Status etc.) many people won't bother reading your posts, it's too much like hard work. When you post code surround it with the 'code' tags (see the 'go advanced' screen). | |||
| |
| | (permalink) | |
| Ok it's kind of working now! The .asm is attached... fell a bit embaressed after all this..... anyway have a look.... Ah all is clear on the STATUS thing, so effectively the status is the same file regardless of which bank you're in (if not, never mind! I think I see your point now). Quote:
I haven't taken out the equates section but it seems to be doing the adc now although it switches on the LED ate 1.29V whic I think is wrong. 5.65V max 10 bit adc (5.65/1023)*250 = 1.38V Maybe it's just down to my cheapy £4.99 Maplin multimeter...... Another point.... when I go above 1.29V the LED goes on and off randomly but I assume this is because I have ignored the contents of the two bits in ADRESH..... so ADRESL fluctuates above and below 250 (B'11111010'). | ||
| |
| | (permalink) |
| Code: CALL RLEDOFF ;Turn LED on subroutine CALL RLEDON ;Turn LED off subroutine | |
| |
| | (permalink) |
| Code: ; HEADER84A.ASM for 12F675. ;The OPTION Register is set to /256 to give timing pulses of 1/3906.25 of a second ;when using the internal 4MHz RC. ;********************************************************* ; EQUATES SECTION #include <p12F675.inc> COUNT EQU 20H ; USER RAM 'COUNT' ;********************************************************* LIST P=12F675 ;we are using the 12F629. ORG 0 ;the start address in memory is 0 GOTO START ;goto start! ;********************************************************************** ; Configuration Bits __CONFIG H'3F84' ;Oscillator - Internal RC ;WDT - off ;PUT - on ;Master Clear Enable - Internal ;BOD - of ;Code Protection - off ;Data EE Read Protect - off ;********************************************************* ;SUBROUTINE SECTION. ; P01 second delay. DELAY CLRF TMR0 ;START TMR0. LOOPA MOVF TMR0,W ;READ TMR0 INTO W. SUBLW .39 ;TIME - 39 BTFSS STATUS,Z ;Check TIME-W = 0 GOTO LOOPA ;Time is not = 3906 RETLW 0 ;Time is 39, return. ; P1 second delay. DELAYP1 MOVLW .10 ;Move 10 into W. MOVWF COUNT ;Set COUNT=10 TIMEB CALL DELAY ;Wait 0.01 seconds. DECFSZ COUNT ;COUNT-1, skip if 0 GOTO TIMEB ;Count is not = 10 RETLW 0 ;Count is = 10, return. ; P5 second delay. DELAYP5 MOVLW .50 ;Move 50 into W. MOVWF COUNT ;Set COUNT=50 TIMEC CALL DELAY ;Wait 0.01 seconds. DECFSZ COUNT ;COUNT-1, skip if 0 GOTO TIMEC ;Count is not = 50 RETLW 0 ;Count is = 50, return. ; 1 second delay. DELAY1 MOVLW .100 ;Move 100 into W. MOVWF COUNT ;Set COUNT=100 TIMED CALL DELAY ;Wait 0.01 seconds. DECFSZ COUNT ;COUNT-1, skip if 0 GOTO TIMED ;Count is not = 100 RETLW 0 ;Count is = 100, return. ;RED LED on RLEDON BCF STATUS,RP0 ;Turn to Bank0 BSF GPIO,1 ;Turn on red LED GOTO RUN ;Restart ADC ;RED LED off RLEDOFF BCF STATUS,RP0 ;Turn to Bank0 BCF GPIO,1 ;Turn off red LED GOTO RUN ;Restart ADC ;********************************************************* START BSF STATUS,RP0 ;Turns to Bank1 MOVLW B'00111001' ;GP 1 & 2 set as OP all others IP MOVWF TRISIO MOVLW B'00010001' CLRF ANSEL ;A/D Clock FOSC/8, AN0(GP0) Set as analogue MOVLW B'00000111' ;Prescaler is /256 MOVWF OPTION_REG ;TIMER pulses every 1/3906.25 secs CALL 3FFH MOVWF OSCCAL ;Calibrates 4MHz oscillator BCF STATUS,RP0 ;Turn to Bank0 MOVLW B'00000111' MOVWF CMCON ;Turns off comparator MOVLW B'10000001' MOVWF ADCON0 ;Result right justified, Ref Vdd, Select AN0, ADC on CLRF GPIO ;Clears GP ;********************************************************* ;Program starts now. BEGIN BSF GPIO,1 ;Test flash sequence BSF GPIO,2 CALL DELAYP1 BCF GPIO,1 BCF GPIO,2 CALL DELAYP1 BSF GPIO,1 BSF GPIO,2 CALL DELAYP1 BCF GPIO,1 BCF GPIO,2 CALL DELAY1 RUN BSF ADCON0,GO ;Start A/D conversion WAIT BTFSC ADCON0,GO GOTO WAIT ;Wait until A/D conversion is complete BSF STATUS,RP0 ;Switch to Bank1 MOVF ADRESL,W ;Move A/D conversion result to working directory SUBLW .250 ;(L-W) Subtract result from .250 (i.e. 1.41V, 1023=5.76V) BTFSC STATUS,C ;Check CARRY BIT (SET for +ve, CLEAR for -ve i.e. clear for result>literal ) CALL RLEDOFF ;Turn LED on subroutine CALL RLEDON ;Turn LED off subroutine END ;This must always come at the end of your code | |
| |
| | (permalink) |
| Hi again!..... changed my multimeter battery and the meter now give the following values 5V regulator output = 5.01V so expected input voltage to turn on LED 10 bit adc (5.01/1023)*250 = 1.22V I measured the voltage to turn on the LED and its 1.13V A bit more reasonable now | |
| |
| Bookmarks |
| Thread Tools | |
| Display Modes | |
| |
| | ||||
| Title | Starter | Forum | Replies | Latest |
| Analog to Digital Converter (ADC) | simonmada | Electronic Projects Design/Ideas/Reviews | 15 | 15th November 2007 04:31 AM |
| PIC 16F877A ADC matters | mokh | Micro Controllers | 7 | 3rd November 2007 08:02 AM |
| HS1101 capacitive humidity sensor; need nearly linear voltage to feed to a 1-wire ADC | FirefighterBlu3 | Electronic Projects Design/Ideas/Reviews | 5 | 20th October 2007 12:06 AM |
| Problem with multiple ADC using pic16f877 | andyto | Micro Controllers | 15 | 24th September 2007 11:48 PM |
| 16F877 Timer0 Interrupt Affecting ADC | sebana | Micro Controllers | 13 | 12th September 2007 10:43 AM |