This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Storing ADC values in C8051F206 memory

Dear all,

I am new to C8051 assembly language programming. To start off, my supervisor has tasked me to acquire DC signals into the ADC and store them in memory locations. The next phase will be interfacing with LCD.

I have fixed a DC variable voltage source from 0-3V into P1.7 of C8051F206 development board which I have configured as analog input. I will be using Port 3 for output.

I have tried to step through my program and I was able to see the values change at memory location 40H as I adjusted the input voltage for one time. When I tried to step through the second time, the system halted.

Could you share with me what I could do to allow the program run continuously and stores incoming dc values in several memory locations as I tuned my input voltage source?

My mediocre source code is as follow:

*************
;-Header File-
;*************
$include (c8051f200.inc)

ORG 0000H
LJMP CONFIG
ORG 0100H


;***************
;-Configuration-
;***************

CONFIG: MOV PRT0MX,#004H ; PRT0MX: Initial Reset Value
        MOV PRT1MX,#000H ; PRT1MX: Initial Reset Value
        MOV PRT2MX,#000H ; PRT2MX: Initial Reset Value
        MOV P2MODE,#0FFH ; Set Port 2 as Input
        MOV P0MODE,#0FFH ; Set Port 0 as Input
        MOV P1MODE,#000H ; Set Port 1 as Analog input
        MOV PRT3CF,#000H ; Set Port 3 as Output
        CLR RS1
        CLR RS0

;*******************
;-ADC configuration-
;*******************
MOV AMX0SL,#2FH  ; Select Port 1.7 for analog use
MOV ADC0CF,#80H  ; 16 system clocks and 1 amp gain
MOV ADC0CN,#0C1H ; ADC Control
MOV REF0CN,#03H  ; Use VDD as reference voltage


;***************
;-Main Function-
;***************
MAIN:   ACALL CONVERT    ; Call subroutine "CONVERT"


;*******************************************
;-Convert Analog Signals to Digital Signals-
;*******************************************
CONVERT:        CLR ADCINT
SETB ADBUSY     ; Start Conversion

;******
;-Poll-
;******
POLL: JNB ADCINT,POLL  ; Poll to see whether conversion is done


;***********************************
;-Store data in memory location-
;***********************************
STORE:          MOV A,ADC0H
                MOV 40H,A

                RET

                END           ; End of Program

Thank you for your advice in advance!

Parents
  • Thanks Russ. In fact, I do not need RET at the moment since I am not calling any more subroutines after CONVERT.

    However, I am still unable store different values in successive memory locations as I adjust my input voltage source. Is there any interrupts, polling, etc needed so that every time I tune my input voltage, the new value is stored in the next memory location?

Reply
  • Thanks Russ. In fact, I do not need RET at the moment since I am not calling any more subroutines after CONVERT.

    However, I am still unable store different values in successive memory locations as I adjust my input voltage source. Is there any interrupts, polling, etc needed so that every time I tune my input voltage, the new value is stored in the next memory location?

Children
  • Thanks Russ. In fact, I do not need RET at the moment since I am not calling any more subroutines after CONVERT.

    Yes, you do. You are calling CONVERT with an ACALL. Therefore, the CONVERT subroutine should end with a RET, as in your original post.

    The next question is, what happens after the RET is executed? You really need to think about the three questions I gave in my previous message, before you go on to worry about the A/D converter, or how to store values in memory, or anything else.

    Hint: What does it mean for a program running on a microcontroller to "end"?

    -- Russ

  • Another hint: Since you are new to assembly language, you may not understand that END is an assembler directive, and not a processor instruction. You can read about END in the assembler documentation. Once you understand what it does, then once again as yourself, "what does it mean for the execution of a program running on a microcontroller to 'end'?"

  • ACALL pushes the address of the instruction that follows ACALL in this case it is CLR ADCINT on to the stack, least-significant-byte first, most-significant-byte second. The Program Counter is then updated so that program execution continues at the indicated address.

    After the RET is first executed, it pops the return address off the stack into the instruction pointer then resumes execution at the location.

    As RET is executed for the second time, there is no subroutine called, thus it proceeds to end.

    Please correct me if I am wrong. Thanks.

  • I am trying to store a 12-bit data. My data in ADC0H:ADC0L are right justified with ADCOCN set to #0C0H. Why is there an error in my following code when I tried to move ADC0L ? Thanks.

    ;***********************************
    ;-Store 8 sets of 12-bit data-
    ;***********************************
    MOV R1,#8
    MOV R0,#40H
    MOV R2,#60H
    
    STORE:          MOV @R0,ADC0H
                     INC R0
                    MOV @R2,ADC0L
                      INC R2
                    DJNZ R1,STORE
    
    
    

  • "As RET is executed for the second time, there is no subroutine called, thus it proceeds to end."

    Now you need to consider the 2nd question - what actually happens at 'END'?

    Hint: as Russ said, 'END' is not a processor instruction; it simply provides some information to the Assembler.

    See: http://www.keil.com/support/man/docs/a51/a51_st_end.htm

  • What happens when you run your car, and compes to a stop sign saying "End of Road" and you continue to drive your car at the same speed?

  • ACALL pushes the address of the instruction that follows ACALL in this case it is CLR ADCINT on to the stack, least-significant-byte first, most-significant-byte second. The Program Counter is then updated so that program execution continues at the indicated address.

    Correct!

    After the RET is first executed, it pops the return address off the stack into the instruction pointer then resumes execution at the location.

    Correct, except it would be better to say "As the RET ... is executed" (not after). The RET instruction is what pops the address from the stack and jumps to that address.

    As RET is executed for the second time, there is no subroutine called, thus it proceeds to end.

    This is where you are having a problem. When RET is executed for the second time, it does exactly the same as the first time: it pops two bytes from the stack and the jumps to that location. However, because no subroutine was called the second time, the numbers that RET gets from the stack the second time are junk! As a result, it jumps to some unknown location and that's when your program crashes.

    So, if you want the program to run continuously, you need to code it so that the ACALL is run over and over again, forever. Or, if you want it to run one time and then stop, you need to write explicit code to make it stop (or at least appear to stop).

    One more time, END is not an instruction that the processor can execute. It is a directive to the assembler. You must understand this. Only bad things will happen if your program ever reaches the END statement.

    -- Russ

  • This is a frequent pitfall for beginners; eg, see

    www.8052.com/.../read.phtml