Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > Other Programming > Assembly Language
Password Reminder
Register
Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read
Welcome to the p2p.wrox.com Forums.

You are currently viewing the Assembly Language section of the Wrox Programmer to Programmer discussions. This is a community of tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developers’ questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
 
 
Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old April 9th, 2008, 03:41 AM
Registered User
 
Join Date: Apr 2008
Location: , , .
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
Default a.c. 50Hz voltage measurement trouble

I have written code in assembly language which can read a voltage and current and display it on my LCD with scaling factors for the application I need. Its fine but I cant figure out how to store numbers and use interrupts in asm. The inputs are from voltage and current transducer circuits including summer amps etc, that I have made so the input range is unipolar 0-5 volts to suit the PIC18F452 microcontroller I am using. The ac inputs need to be sampled 20 times per 50Hz cycle, that being 1000 samples
a second. The samples need to be squared, summed, the mean found and finally the square root is found to get the rms values. I am having great difficulty in doing this.So I need to make the timer read the samples 20 times per second, then store the samples. Thats the basic bit I need, and am stuck with.
Any ideas would be good. the ra0 ACD input on the PIC is fine for the voltage, which is the single part I am working on now. So in summary, I need to store the input at ra0, and at the end of the 20 stored values, just divide the total of the 20 samples by 20. Its really
simplified down but this is as far as I have managed to get on my own.

This is the working code so far, which shows the instantaneous voltage and current in real time.
-------------------------------------------------------

    list p=18f452
    #include p18f452.inc


;Program Configuration Registers
        __CONFIG _CONFIG1H, _OSCS_OFF_1H & _EC_OSC_1H
        __CONFIG _CONFIG2L, _BOR_OFF_2L & _PWRT_ON_2L
        __CONFIG _CONFIG2H, _WDT_OFF_2H
        __CONFIG _CONFIG3H, _CCP2MX_OFF_3H
        __CONFIG _CONFIG4L, _STVR_OFF_4L & _LVP_OFF_4L & _DEBUG_OFF_4L
        __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L & _CP2_OFF_5L & _CP3_OFF_5L
        __CONFIG _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
        __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L & _WRT2_OFF_6L & _WRT3_OFF_6L
        __CONFIG _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H
        __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L & _EBTR2_OFF_7L & _EBTR3_OFF_7L
        __CONFIG _CONFIG7H, _EBTRB_OFF_7H

    #define scroll_dir TRISA,4
    #define scroll PORTA,4 ;Push-button RA4 on PCB
    #define select_dir TRISB,0
    #define select PORTB,0 ;Push-button RB0 on PCB

    EXTERN LCDInit, temp_wr, d_write, i_write, LCDLine_1, LCDLine_2
    EXTERN UMUL0808L, FXD1608U, AARGB0, AARGB1, BARGB0


ssprw macro ;check for idle SSP module routine
    movlw 0x00
    andwf SSPCON2,W
    sublw 0x00
    btfss STATUS,Z
    bra $-8

    btfsc SSPSTAT,R_W
    bra $-2
    endm

variables UDATA
ptr_pos RES 1
ptr_count RES 1
temp_1 RES 1
temp_2 RES 1
temp_3 RES 1
cmd_byte RES 1
LSD RES 1
MsD RES 1
MSD RES 1


NumH RES 1
NumL RES 1
TenK RES 1
Thou RES 1
Hund RES 1
Tens RES 1
Ones RES 1

STARTUP CODE
    NOP
    goto start
    NOP
    NOP
    NOP
PROG1 CODE

stan_table ;table for standard code
    ; "XXXXXXXXXXXXXXXX"
    ; ptr:
    data " Voltage Output " ;0
    data " S3 for reading " ;160
    data " GENSET OUTPUT " ;32
    data "Waiting........." ;48
    data " S3=Select " ;64
    data "RA4= --> RBO= ++" ;80
    data " RESET to EXIT " ;96
    data "Volts = " ;112
    data " Current " ;128
        data "Current = " ;144



start
    call LCDInit

    movlw B'10100100' ;initialize USART
    movwf TXSTA ;8-bit, Async, High Speed
    movlw .25
    movwf SPBRG ;9.6kbaud @ 4MHz
    movlw B'10010000'
    movwf RCSTA

    bcf TRISC,2 ;configure CCP1 period
    movlw 0x80 ;initialize PWM duty cycle
    movwf CCPR1L
    bcf CCP1CON,CCP1X
    bcf CCP1CON,CCP1Y

    movlw 0x05 ;postscale 1:1, prescaler 4, Timer2 ON
    movwf T2CON

    bsf TRISA,4 ;make switch RA4 an Input
    bsf TRISB,0 ;make switch RB0 an Input


;**************** STANDARD CODE MENU SELECTION *******************
            ;Introduction
    movlw .32 ;send to LCD
    movwf ptr_pos
    call stan_char_1

    movlw .48 ;send to LCD
    movwf ptr_pos
    call stan_char_2
    call delay_1s ;delay for display
    call delay_1s ;delay for display
menu

;------------------ VOLT MEASUREMENT ----------------------------
    btfss scroll ;wait for RA4 release
    goto $-2
    btfss select ;wait for RB0 release
    goto $-2

    movlw 0x00 ;voltmeter
    movwf ptr_pos
    call stan_char_1

    movlw .48 ;RA4=Next RB0=Now
    movwf ptr_pos
    call stan_char_2
v_wait
    btfss select ;voltmeter measurement ??
    bra voltmeter
    btfsc scroll ;next mode ??
    bra v_wait ;NO
    btfss scroll ;YES
    bra $-2 ;wait for RA4 release



;------------------ CURRENT MEASUREMENT ----------------------------
menu_current
    btfss scroll ;wait for RA4 release
    goto $-2
    btfss select ;wait for RB0 release
    goto $-2

    movlw .128 ;voltmeter
    movwf ptr_pos
    call stan_char_1

    movlw .48 ;RA4=Next RB0=Now
    movwf ptr_pos
    call stan_char_2
c_wait
    btfss select ;voltmeter measurement ??
    bra current
    btfsc scroll ;next mode ??
    bra c_wait ;NO
    btfss scroll ;YES
    bra $-2 ;wait for RA4 release




;-------------------------------------------------------------------
    bra menu ;begining of menu
    return

;************************************************* ******************




;************* STANDARD USER CODE **********************************



    ;------------- Voltmeter----------------------------

voltmeter
    btfss select ;wait for RB0 release
    bra $-2

    movlw B'01000001' ;configure A/D converter
    movwf ADCON0 ;turn A/D on
    movlw b'10001110' ;RA0 = analog input
    movwf ADCON1

    movlw .112 ;send "Volts = " to the LCD
    movwf ptr_pos
    call stan_char_1
volts_again
    bsf ADCON0,GO ;start conversion
again
    btfsc ADCON0,GO
    goto again
    movf ADRESH,W ;ADRESH --> WREG

    movwf AARGB0 ;move ADRESH into AARGB0
    movlw 0x64 ;19.5mV/step 0xC3 = 195
    movwf BARGB0
    call UMUL0808L

    movlw 0x64 ;divide result by 200 (0x128)
    movwf BARGB0
    call FXD1608U

    movf AARGB0,W ;prepare for 16-bit binary to BCD
    movwf NumH
    movf AARGB1,W
    movwf NumL
    call bin16_bcd ;get volts ready for LCD

    call LCDLine_2 ;display A/D result on 2nd line
    movf Hund,W ;get hunds
    call bin_bcd
    movf LSD,W ;send high digit from LSD
    movwf temp_wr

    movwf temp_wr
    call d_write

    movf Tens,W ;get tens
    call bin_bcd
    movf LSD,W ;send low digit x.#x
    movwf temp_wr
    call d_write

    movf Ones,W ;get ones
    call bin_bcd
    movf LSD,W ;send low digit x.x#
    movwf temp_wr
    call d_write
    movlw A'V' ;send "V" unit
    movwf temp_wr
    call d_write

    movlw 0x20 ;3 spaces
    movwf temp_wr
    call d_write
    movlw 0x20
    movwf temp_wr
    call d_write
    movlw 0x20
    movwf temp_wr
    call d_write
    movlw A'R' ;send "RB0=Exit" to LCD
    movwf temp_wr
    call d_write
    movlw A'E'
    movwf temp_wr
    call d_write
    movlw A'S'
    movwf temp_wr
    call d_write
    movlw A'='
    movwf temp_wr
    call d_write
    movlw A'E'
    movwf temp_wr
    call d_write
    movlw A'x'
    movwf temp_wr
    call d_write
    movlw A'i'
    movwf temp_wr
    call d_write
    movlw A't'
    movwf temp_wr
    call d_write
    movlw 0x20 ;2 spaces
    movwf temp_wr
    call d_write
    movlw 0x20
    movwf temp_wr
    call d_write

    movlw "\r" ;move data into TXREG
    movwf TXREG ;carriage return
    btfss TXSTA,TRMT ;wait for data TX
    bra $-2
    btfss select ;exit volt measurement ??
    bra menu_current ;YES
    bra volts_again ;NO, do conversion again

;------------- Currentmeter--------------------------------------------
current
    btfss select ;wait for RB0 release
    bra $-2

    movlw B'01000001' ;configure A/D converter
    movwf ADCON0 ;turn A/D on
    movlw b'00001110' ;RA0 = analog input
    movwf ADCON1

    movlw .144 ;send "Volts = " to the LCD
    movwf ptr_pos
    call stan_char_1
current_again
    bsf ADCON0,GO ;start conversion
again1
    btfsc ADCON0,GO
    goto again1
    movf ADRESH,W ;ADRESH --> WREG

    movwf AARGB0 ;move ADRESH into AARGB0
    movlw 0xC3 ;19.5mV/step 0xC3 = 195
    movwf BARGB0
    call UMUL0808L

    movlw 0xAA ;divide result by 100 (0x64)
    movwf BARGB0
    call FXD1608U

    movf AARGB0,W ;prepare for 16-bit binary to BCD
    movwf NumH
    movf AARGB1,W
    movwf NumL
    call bin16_bcd ;get volts ready for LCD

    call LCDLine_2 ;display A/D result on 2nd line
    movf Hund,W ;get hunds
    call bin_bcd
    movf LSD,W ;send high digit from the LSD #.xx
    movwf temp_wr
    call d_write


    movf Tens,W ;get tens
    call bin_bcd
    movf LSD,W ;send low digit x.#x
    movwf temp_wr
    call d_write
    movlw A'.' ;send decimal point "."
    movwf temp_wr
    call d_write

    movf Ones,W ;get ones
    call bin_bcd
    movf LSD,W ;send low digit x.x#
    movwf temp_wr
    call d_write
    movlw A'A' ;send "A" unit
    movwf temp_wr
    call d_write

    movlw 0x20 ;3 spaces
    movwf temp_wr
    call d_write
    movlw 0x20
    movwf temp_wr
    call d_write
    movlw 0x20
    movwf temp_wr
    call d_write
    movlw A'R' ;send "RB0=Exit" to LCD
    movwf temp_wr
    call d_write
    movlw A'E'
    movwf temp_wr
    call d_write
    movlw A'S'
    movwf temp_wr
    call d_write
    movlw A'='
    movwf temp_wr
    call d_write
    movlw A'E'
    movwf temp_wr
    call d_write
    movlw A'x'
    movwf temp_wr
    call d_write
    movlw A'i'
    movwf temp_wr
    call d_write
    movlw A't'
    movwf temp_wr
    call d_write
    movlw 0x20 ;2 spaces
    movwf temp_wr
    call d_write
    movlw 0x20
    movwf temp_wr
    call d_write

    movlw "\r" ;move data into TXREG
    movwf TXREG ;carriage return
    btfss TXSTA,TRMT ;wait for data TX
    bra $-2


    bra current_again ;NO, do conversion again




;------------------------
        ;adjust Duty Cycle
inc_dc
    btfss scroll ;wait for button release
    bra $-2

inc_ccpr1l
    btfsc select ;increment CCPR1L ???
    goto ccpr1l_out ;NO
    call delay_100ms ;YES
    call delay_100ms
    incf CCPR1L,F ;increment CCPR1L
ccpr1l_out
    movlw 0x8C ;move cursor into position
    movwf temp_wr
    call i_write

col1
    btfss scroll ;exit?
    bra pwm_out
    btfsc select ;wait for RB0 press
    bra col1

    movf CCPR1L,W ;send PR2 register to conversion
    call bin_bcd

    movf MSD,W ;send high digit
    movwf temp_wr
    call d_write
    movf MsD,W ;send middle digit
    movwf temp_wr
    call d_write
    movf LSD,W ;send low digit
    movwf temp_wr
    call d_write
    bra inc_ccpr1l

pwm_out
    movlw 0
    movwf CCP1CON ;turn buzzer off




;************************************************* ******************


;************************** ROUTINES ******************************


;----Standard code, Place characters on line-1--------------

stan_char_1
    call LCDLine_1 ;move cursor to line 1
    movlw .16 ;1-full line of LCD
    movwf ptr_count
    movlw UPPER stan_table
    movwf TBLPTRU
    movlw HIGH stan_table
    movwf TBLPTRH
    movlw LOW stan_table
    movwf TBLPTRL
    movf ptr_pos,W
    addwf TBLPTRL,F
    clrf WREG
    addwfc TBLPTRH,F
    addwfc TBLPTRU,F

stan_next_char_1
    tblrd *+
    movff TABLAT,temp_wr
    call d_write ;send character to LCD

    decfsz ptr_count,F ;move pointer to next char
    bra stan_next_char_1

    movlw "\n" ;move data into TXREG
    movwf TXREG ;next line
    btfss TXSTA,TRMT ;wait for data TX
    goto $-2
    movlw "\r" ;move data into TXREG
    movwf TXREG ;carriage return
    btfss TXSTA,TRMT ;wait for data TX
    goto $-2

    return

;----Standard code, Place characters on line-2--------------------------
stan_char_2
    call LCDLine_2 ;move cursor to line 2
    movlw .16 ;1-full line of LCD
    movwf ptr_count
    movlw UPPER stan_table
    movwf TBLPTRU
    movlw HIGH stan_table
    movwf TBLPTRH
    movlw LOW stan_table
    movwf TBLPTRL
    movf ptr_pos,W
    addwf TBLPTRL,F
    clrf WREG
    addwfc TBLPTRH,F
    addwfc TBLPTRU,F

stan_next_char_2
    tblrd *+
    movff TABLAT,temp_wr
    call d_write ;send character to LCD

    decfsz ptr_count,F ;move pointer to next char
    bra stan_next_char_2

    movlw "\n" ;move data into TXREG
    movwf TXREG ;next line
    btfss TXSTA,TRMT ;wait for data TX
    goto $-2
    movlw "\r" ;move data into TXREG
    movwf TXREG ;carriage return
    btfss TXSTA,TRMT ;wait for data TX
    goto $-2

    return
;----------------------------------------------------------------------


;------------------ 100ms Delay --------------------------------
delay_100ms
    movlw 0xFF
    movwf temp_1
    movlw 0x83
    movwf temp_2

d100l1
    decfsz temp_1,F
    bra d100l1
    decfsz temp_2,F
    bra d100l1
    return

;---------------- 1s Delay -----------------------------------
delay_1s
    movlw 0xFF
    movwf temp_1
    movwf temp_2
    movlw 0x05
    movwf temp_3
d1l1
    decfsz temp_1,F
    bra d1l1
    decfsz temp_2,F
    bra d1l1
    decfsz temp_3,F
    bra d1l1
    return




;---------------- Binary (8-bit) to BCD -----------------------
; 255 = highest possible result
bin_bcd
    clrf MSD
    clrf MsD
    movwf LSD ;move value to LSD
ghundreth
    movlw .100 ;subtract 100 from LSD
    subwf LSD,W
    btfss STATUS,C ;is value greater then 100
    bra gtenth ;NO goto tenths
    movwf LSD ;YES, move subtraction result into LSD
    incf MSD,F ;increment hundreths
    bra ghundreth
gtenth
    movlw .10 ;take care of tenths
    subwf LSD,W
    btfss STATUS,C
    bra over ;finished conversion
    movwf LSD
    incf MsD,F ;increment tenths position
    bra gtenth
over ;0 - 9, high nibble = 3 for LCD
    movf MSD,W ;get BCD values ready for LCD display
    xorlw 0x30 ;convert to LCD digit
    movwf MSD
    movf MsD,W
    xorlw 0x30 ;convert to LCD digit
    movwf MsD
    movf LSD,W
    xorlw 0x30 ;convert to LCD digit
    movwf LSD
    retlw 0

;---------------- Binary (16-bit) to BCD -----------------------
; xxx = highest possible result
bin16_bcd
                         ; Takes number in NumH:NumL
                                ; Returns decimal in
                                ; TenK:Thou:Hund:Tens:Ones
        swapf NumH,W
        andlw 0x0F
        addlw 0xF0
        movwf Thou
        addwf Thou,F
        addlw 0xE2
        movwf Hund
        addlw 0x32
        movwf Ones

        movf NumH,W
        andlw 0x0F
        addwf Hund,F
        addwf Hund,F
        addwf Ones,F
        addlw 0xE9
        movwf Tens
        addwf Tens,F
        addwf Tens,F

        swapf NumL,W
        andlw 0x0F
        addwf Tens,F
        addwf Ones,F

        rlcf Tens,F
        rlcf Ones,F
        comf Ones,F
        rlcf Ones,F

        movf NumL,W
        andlw 0x0F
        addwf Ones,F
        rlcf Thou,F

        movlw 0x07
        movwf TenK

        movlw 0x0A ; Ten
Lb1:
        decf Tens,F
        addwf Ones,F
        btfss STATUS,C
         bra Lb1
Lb2:
        decf Hund,F
        addwf Tens,F
        btfss STATUS,C
         bra Lb2
Lb3:
        decf Thou,F
        addwf Hund,F
        btfss STATUS,C
         bra Lb3
Lb4:
        decf TenK,F
        addwf Thou,F
        btfss STATUS,C
         bra Lb4

        retlw 0


;---------------------------- EEPROM WRITE -------------------------------
write_eeprom
    bsf SSPCON2,SEN ;start bit
    btfsc SSPCON2,SEN
    goto $-2
    movlw B'10100000' ;send control byte (write)
    movwf SSPBUF
    ssprw
    btfsc SSPCON2,ACKSTAT
    goto $-2

    movlw 0x00 ;send slave address HIGH byte
    movwf SSPBUF
    ssprw
    btfsc SSPCON2,ACKSTAT
    goto $-2

    movlw 0x05 ;send slave address LOW byte(0x0005)
    movwf SSPBUF
    ssprw
    btfsc SSPCON2,ACKSTAT
    goto $-2

    bsf SSPCON2,PEN ;stop bit
    btfsc SSPCON2,PEN
    goto $-2

    bcf PIR1,TMR1IF ;clear TIMER1 overflow flag
    clrf TMR1L ;clear registers for next overflow
    clrf TMR1H

    return

;************************************************* ********************
    end
 


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
If Else Trouble Cibressus Beginning PHP 0 May 1st, 2007 02:04 PM
How to draw fix measurement lines Abhi.Win C# 0 December 23rd, 2005 12:43 PM
Please i have had a Trouble hurted Wrox Book Feedback 1 June 28th, 2004 02:18 AM
trouble databass Classic ASP Databases 2 August 16th, 2003 10:27 AM



All times are GMT -4. The time now is 03:15 PM.


Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.